mirror of
https://gitflic.ru/project/lax1dude/eaglercraft-1_8.git
synced 2025-06-05 18:22:01 -09:00
Update #51 - Protocol and FPS improvements, better workspace
This commit is contained in:
parent
71c61e33fd
commit
325a6826bf
22
CREDITS
22
CREDITS
@ -6,21 +6,20 @@
|
||||
|
||||
- Creator of Eaglercraft
|
||||
- Ported the Minecraft 1.8 src to TeaVM
|
||||
- Wrote HW accelerated OpenGL 1.3 emulator
|
||||
- Wrote the default shader pack
|
||||
- Optimized the Minecraft 1.8 src
|
||||
- Made the platform abstraction layer
|
||||
- Made HW accelerated OpenGL 1.3 emulator
|
||||
- Made the default shader pack
|
||||
- Made the integrated PBR resource pack
|
||||
- Added touch and mobile device support
|
||||
- Wrote all desktop emulation code
|
||||
- Wrote EaglercraftXBungee
|
||||
- Wrote EaglercraftXVelocity
|
||||
- Wrote WebRTC relay server
|
||||
- Wrote voice chat server
|
||||
- Wrote the patch and build system
|
||||
- Made the multiplayer backends
|
||||
- Made the shared world relay server
|
||||
- Made the patch and build system
|
||||
|
||||
ayunami2000:
|
||||
|
||||
- Many bug fixes
|
||||
- WebRTC LAN worlds
|
||||
- WebRTC shared worlds
|
||||
- WebRTC voice chat
|
||||
- Worked on touch support
|
||||
- Made velocity plugin work
|
||||
@ -29,6 +28,11 @@
|
||||
- Added seamless fullscreen
|
||||
- Created the replit
|
||||
|
||||
cire3:
|
||||
|
||||
- Created the Gradle plugin
|
||||
- Proponent of Kotlin DSL
|
||||
|
||||
|
||||
|
||||
Code used within EaglercraftX
|
||||
|
@ -48,9 +48,9 @@ The JavaScript runtime of EaglercraftX 1.8 is currently known to work on browser
|
||||
|
||||
## WebAssembly GC Support
|
||||
|
||||
EaglercraftX 1.8 also has an experimental WebAssembly GC (WASM-GC) runtime, almost all of the features supported on the JavaScript runtime are also supported on the WebAssembly GC runtime, however it is still incompatible with several major browsers (especially Safari) and will not run in Chrome unless you can access the `chrome://flags` menu or request an origin trial token from Google for your website. Its based on experimental technology and may still crash sometimes due to browser bugs or unresolved issues in the Java to WASM compiler. Hopefully in the coming months the required feature (JSPI, WebAssembly JavaScript Promise Integration) will become enabled by default on the Chrome browser. It performs significantly better than the JavaScript client, around 50% more FPS and TPS in some cases, and will hopefully replace it someday. Just make sure you enable VSync when you play it, otherwise the game will run "too fast" and choke the browser's event loop, causing input lag.
|
||||
EaglercraftX 1.8 also has an experimental WebAssembly GC (WASM-GC) runtime, almost all of the features supported on the JavaScript runtime are also supported on the WebAssembly GC runtime, however it is still incompatible with several major browsers (especially Safari) and will not run in Chrome unless you can access the `chrome://flags` menu or request an origin trial token from Google for your website. Its based on experimental technology and may still crash sometimes, mostly due to browser bugs. Hopefully in the coming months the required feature (JSPI, WebAssembly JavaScript Promise Integration) will become enabled by default on the Chrome browser. It performs significantly better than the JavaScript client, around 50% more FPS and TPS in some cases, and will hopefully replace it someday. Just make sure you enable VSync when you play it, otherwise the game will run "too fast" and choke the browser's event loop, causing input lag.
|
||||
|
||||
You can compile the WebAssembly GC runtime by creating a development environment (workspace) and reading the README in the "wasm_gc_teavm" folder.
|
||||
There is no GUI for compiling the WASM-GC client at the moment, you need to compile it using the `MakeWASMClientBundle` script in the development environment.
|
||||
|
||||
## Singleplayer
|
||||
|
||||
@ -208,5 +208,3 @@ The `crashReportShow` hook can be used to capture crash reports and append addit
|
||||
## Developing a Client
|
||||
|
||||
There is currently no system in place to make forks of 1.8 and merge commits made to the patch files in this repository with the patch files or workspace of the fork, you're on your own if you try to keep a fork of this repo for reasons other than to contribute to it
|
||||
|
||||
**Note:** If you are trying to use the desktop runtime on Linux, make sure you add the "desktopRuntime" folder to the `LD_LIBRARY_PATH` environment variable of the Java process. This should be done automatically by the Eclipse project's default run configuration, but it might not work properly on every system, or when the Eclipse project is imported into IntelliJ.
|
||||
|
Binary file not shown.
BIN
buildtools/Java17Check.jar
Normal file
BIN
buildtools/Java17Check.jar
Normal file
Binary file not shown.
@ -471,7 +471,7 @@ public class CompileLatestClientFrame {
|
||||
txtpnfuckOffwelcome.setEditable(false);
|
||||
txtpnfuckOffwelcome.setMargin(new Insets(10, 10, 10, 10));
|
||||
txtpnfuckOffwelcome.setContentType("text/html");
|
||||
txtpnfuckOffwelcome.setText("<html>\r\n<head><title>fuck off</title></head>\r\n<body style=\"font-family:sans-serif;margin:0px;\">\r\n<p style=\"font-size:17px;\">Welcome to the EaglercraftX 1.8 Client Compiler</p>\r\n<p style=\"font-size:11px;\">This tool will allow you to automatically compile the latest version of the EaglercraftX 1.8 client using the files in this repository.</p>\r\n<p style=\"font-size:11px;\">You are required to download several required files manually in order to better respect the Microsoft/Mojang TOS. The links to these files will be provided.</p>\r\n<p style=\"font-size:11px;\">To view or modify portions of the EaglercraftX 1.8 source code directly, please use the other batch files to generate a gradle project instead of compiling the javascript files directly</p>\r\n<p style=\"font-size:11px;\">If you are from Microsoft/Mojang or the developer of MCP trying to get dirt on me, please just let me live my life, the repository does not contain your intellectual property. Using this code to play your game for free is not the default behavior of the gateway plugin or this compiler utility and is not encouraged by the documentation</p>\r\n</body>\r\n</html>");
|
||||
txtpnfuckOffwelcome.setText("<html>\r\n<head><title>fuck off</title></head>\r\n<body style=\"font-family:sans-serif;margin:0px;\">\r\n<p style=\"font-size:17px;\">Welcome to the EaglercraftX 1.8 Client Compiler</p>\r\n<p style=\"font-size:11px;\">This tool will allow you to automatically compile the latest version of the EaglercraftX 1.8 client using the files in this repository.</p>\r\n<p style=\"font-size:11px;\">You are required to download several required files manually in order to better respect the Microsoft/Mojang TOS. The links to these files will be provided.</p>\r\n<p style=\"font-size:11px;\">To view or modify portions of the EaglercraftX 1.8 source code directly, please use the other batch files to generate a gradle project instead of compiling the javascript files directly</p>\r\n<p style=\"font-size:11px;\">This tool will only build the JavaScript client, to build WASM-GC please create a workspace and use the Gradle project to build it instead.</p>\r\n</body>\r\n</html>");
|
||||
pageHome.add(txtpnfuckOffwelcome, BorderLayout.CENTER);
|
||||
|
||||
JPanel pageLicense = new JPanel();
|
||||
|
@ -66,16 +66,16 @@ public class CompileLatestClientGUI {
|
||||
| UnsupportedLookAndFeelException e) {
|
||||
System.err.println("Could not set system look and feel: " + e.toString());
|
||||
}
|
||||
if(!System.getProperty("eaglercraft.isJava11", "false").equalsIgnoreCase("true")) {
|
||||
if(!System.getProperty("eaglercraft.isJava17", "false").equalsIgnoreCase("true")) {
|
||||
try {
|
||||
if (!(boolean) Class
|
||||
.forName("net.lax1dude.eaglercraft.v1_8.buildtools.Java11Check", true,
|
||||
new URLClassLoader(new URL[] { (new File("buildtools/Java11Check.jar")).toURI().toURL() }))
|
||||
.forName("net.lax1dude.eaglercraft.v1_8.buildtools.Java17Check", true,
|
||||
new URLClassLoader(new URL[] { (new File("buildtools/Java17Check.jar")).toURI().toURL() }))
|
||||
.getMethod("classLoadCheck").invoke(null)) {
|
||||
throw new RuntimeException("wtf?");
|
||||
}
|
||||
}catch(Throwable t) {
|
||||
JOptionPane.showMessageDialog(null, "Error: Java 11 is required to run this program", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
JOptionPane.showMessageDialog(null, "Error: Java 17 is required to run this program", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
@ -90,7 +90,7 @@ public class CompileLatestClientGUI {
|
||||
System.setErr(new PrintStream(new ConsoleRedirector(true)));
|
||||
if(JavaC.jdkHome == null) {
|
||||
if(JOptionPane.showConfirmDialog(frame.frmCompileLatestClient, "Error: A JDK is required to run this program!\nYou are currently running on a JRE\nDo you have a JDK installed that you would like to use instead?", "Unsupported JRE", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "You need at least JDK 8 to compile EaglercraftX 1.8!\nSelect the path to the installation you want to use", "Unsupported JRE", JOptionPane.INFORMATION_MESSAGE);
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "You need at least JDK 17 to compile EaglercraftX 1.8!\nSelect the path to the installation you want to use", "Unsupported JRE", JOptionPane.INFORMATION_MESSAGE);
|
||||
JFileChooser fileChooser = new JFileChooser((new File(System.getProperty("java.home"))).getParentFile());
|
||||
fileChooser.setMultiSelectionEnabled(false);
|
||||
fileChooser.setFileHidingEnabled(false);
|
||||
@ -106,7 +106,7 @@ public class CompileLatestClientGUI {
|
||||
}
|
||||
}
|
||||
}
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "Please install JDK 8 or newer to continue", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
JOptionPane.showMessageDialog(frame.frmCompileLatestClient, "Please install JDK 17 or newer to continue", "Unsupported JRE", JOptionPane.ERROR_MESSAGE);
|
||||
System.exit(-1);
|
||||
return;
|
||||
}
|
||||
@ -256,6 +256,7 @@ public class CompileLatestClientGUI {
|
||||
new File(repositoryFolder, "sources/protocol-game/java"),
|
||||
new File(repositoryFolder, "sources/protocol-relay/java"),
|
||||
new File(repositoryFolder, "sources/teavm/java"),
|
||||
new File(repositoryFolder, "sources/teavm/resources"),
|
||||
new File(repositoryFolder, "sources/teavm-boot-menu/java"));
|
||||
}catch(IOException ex) {
|
||||
throw new CompileFailureException("failed to run javac compiler! " + ex.toString(), ex);
|
||||
@ -331,11 +332,11 @@ public class CompileLatestClientGUI {
|
||||
|
||||
File classesJS = new File(outputDirectory, "classes.js");
|
||||
|
||||
if(!ES6Compat.patchClassesJS(classesJS, new File(repositoryFolder, "sources/setup/workspace_template/javascript/ES6ShimScript.txt"))) {
|
||||
if(!ES6Compat.patchClassesJS(classesJS, new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/javascript/ES6ShimScript.txt"))) {
|
||||
System.err.println("Error: could not inject shim, continuing anyway because it is not required");
|
||||
}
|
||||
|
||||
File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/CompileEPK.jar");
|
||||
File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/buildtools/CompileEPK.jar");
|
||||
|
||||
if(!epkCompiler.exists()) {
|
||||
throw new CompileFailureException("EPKCompiler JAR file is missing: " + epkCompiler.getAbsolutePath());
|
||||
@ -390,9 +391,9 @@ public class CompileLatestClientGUI {
|
||||
if(generateOfflineDownload) {
|
||||
System.out.println("Running offline download generator...");
|
||||
System.out.println();
|
||||
File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/MakeOfflineDownload.jar");
|
||||
File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/buildtools/MakeOfflineDownload.jar");
|
||||
MakeOfflineDownload.compilerMain(offlineDownloadGenerator, new String[] {
|
||||
(new File(repositoryFolder, "sources/setup/workspace_template/javascript/OfflineDownloadTemplate.txt")).getAbsolutePath(),
|
||||
(new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/javascript/OfflineDownloadTemplate.txt")).getAbsolutePath(),
|
||||
classesJS.getAbsolutePath(), (new File(outputDirectory, "assets.epk")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_en_US.html")).getAbsolutePath(),
|
||||
(new File(outputDirectory, "EaglercraftX_1.8_Offline_International.html")).getAbsolutePath(),
|
||||
|
@ -37,7 +37,7 @@ public class JavaC {
|
||||
|
||||
public static final List<String> compilerFlags = Arrays.asList(
|
||||
"-Xlint:-unchecked", "-Xlint:-options", "-Xlint:-deprecation",
|
||||
"-source", "1.8", "-target", "1.8", "-encoding", "utf8"
|
||||
"-source", "17", "-target", "17", "-encoding", "utf8"
|
||||
);
|
||||
|
||||
private static int debugSourceFileCount = 0;
|
||||
|
@ -62,12 +62,16 @@ public class TeaVMBinaries {
|
||||
public static final MavenJAREntry teavmMetaprogrammingImpl = new MavenJAREntry("org/teavm/teavm-metaprogramming-impl/0.9.2/teavm-metaprogramming-impl-0.9.2.jar");
|
||||
public static final MavenJAREntry teavmJodaTime = new MavenJAREntry("joda-time/joda-time/2.12.2/joda-time-2.12.2.jar");
|
||||
public static final MavenJAREntry teavmJZLIB = new MavenJAREntry("com/jcraft/jzlib/1.1.3/jzlib-1.1.3.jar");
|
||||
public static final MavenJAREntry depJOrbis = new MavenJAREntry("org/jcraft/jorbis/0.0.17/jorbis-0.0.17.jar");
|
||||
public static final MavenJAREntry depLang3 = new MavenJAREntry("org/apache/commons/commons-lang3/3.6/commons-lang3-3.6.jar");
|
||||
public static final MavenJAREntry depHPPC = new MavenJAREntry("com/carrotsearch/hppc/0.10.0/hppc-0.10.0.jar");
|
||||
public static final MavenJAREntry depJSR305 = new MavenJAREntry("com/google/code/findbugs/jsr305/3.0.2/jsr305-3.0.2.jar");
|
||||
|
||||
private static final MavenJAREntry[] jarsList = new MavenJAREntry[] { teavmCore, teavmCli, teavmTooling,
|
||||
teavmPlatform, teavmClasslib, teavmInterop, teavmJSO, teavmJSOApis, teavmJSOImpl, teavmRelocatedLibsASM,
|
||||
teavmRelocatedLibsASMAnalysis, teavmRelocatedLibsASMCommons, teavmRelocatedLibsASMTree,
|
||||
teavmRelocatedLibsASMUtil, teavmRelocatedLibsHPPC, teavmRelocatedLibsRhino, teavmMetaprogrammingAPI,
|
||||
teavmMetaprogrammingImpl, teavmJodaTime, teavmJZLIB };
|
||||
teavmMetaprogrammingImpl, teavmJodaTime, teavmJZLIB, depJOrbis, depLang3, depHPPC, depJSR305 };
|
||||
|
||||
public static File teavmBridge = null;
|
||||
|
||||
@ -201,10 +205,12 @@ public class TeaVMBinaries {
|
||||
|
||||
public static String[] getTeaVMRuntimeClasspath() {
|
||||
return new String[] { teavmJodaTime.file.getAbsolutePath(), teavmJZLIB.file.getAbsolutePath(),
|
||||
teavmClasslib.file.getAbsolutePath(), teavmInterop.file.getAbsolutePath(), teavmJSO.file.getAbsolutePath(),
|
||||
teavmJSOApis.file.getAbsolutePath(), teavmJSOImpl.file.getAbsolutePath(),
|
||||
teavmMetaprogrammingAPI.file.getAbsolutePath(), teavmMetaprogrammingImpl.file.getAbsolutePath(),
|
||||
teavmPlatform.file.getAbsolutePath(), teavmCore.file.getAbsolutePath() };
|
||||
teavmClasslib.file.getAbsolutePath(), teavmInterop.file.getAbsolutePath(),
|
||||
teavmJSO.file.getAbsolutePath(), teavmJSOApis.file.getAbsolutePath(),
|
||||
teavmJSOImpl.file.getAbsolutePath(), teavmMetaprogrammingAPI.file.getAbsolutePath(),
|
||||
teavmMetaprogrammingImpl.file.getAbsolutePath(), teavmPlatform.file.getAbsolutePath(),
|
||||
teavmCore.file.getAbsolutePath(), depJOrbis.file.getAbsolutePath(), depLang3.file.getAbsolutePath(),
|
||||
depHPPC.file.getAbsolutePath(), depJSR305.file.getAbsolutePath() };
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ public class CompileLatestClientHeadless {
|
||||
|
||||
System.out.println();
|
||||
System.out.println("Launching client compiler...");
|
||||
System.out.println("Copyright (c) 2022-2024 lax1dude");
|
||||
System.out.println("Copyright (c) 2022-2025 lax1dude");
|
||||
System.out.println();
|
||||
|
||||
boolean yes = false;
|
||||
@ -327,6 +327,7 @@ public class CompileLatestClientHeadless {
|
||||
new File(repositoryFolder, "sources/protocol-game/java"),
|
||||
new File(repositoryFolder, "sources/protocol-relay/java"),
|
||||
new File(repositoryFolder, "sources/teavm/java"),
|
||||
new File(repositoryFolder, "sources/teavm/resources"),
|
||||
new File(repositoryFolder, "sources/teavm-boot-menu/java"));
|
||||
}catch(IOException ex) {
|
||||
throw new CompileFailureException("failed to run javac compiler! " + ex.toString(), ex);
|
||||
@ -404,11 +405,11 @@ public class CompileLatestClientHeadless {
|
||||
|
||||
File classesJS = new File(outputDirectory, "classes.js");
|
||||
|
||||
if(!ES6Compat.patchClassesJS(classesJS, new File(repositoryFolder, "sources/setup/workspace_template/javascript/ES6ShimScript.txt"))) {
|
||||
if(!ES6Compat.patchClassesJS(classesJS, new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/javascript/ES6ShimScript.txt"))) {
|
||||
System.err.println("Error: could not inject shim, continuing anyway because it is not required");
|
||||
}
|
||||
|
||||
File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/CompileEPK.jar");
|
||||
File epkCompiler = new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/buildtools/CompileEPK.jar");
|
||||
|
||||
if(!epkCompiler.exists()) {
|
||||
throw new CompileFailureException("EPKCompiler JAR file is missing: " + epkCompiler.getAbsolutePath());
|
||||
@ -586,7 +587,7 @@ public class CompileLatestClientHeadless {
|
||||
}
|
||||
}
|
||||
}
|
||||
File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/desktopRuntime/MakeOfflineDownload.jar");
|
||||
File offlineDownloadGenerator = new File(repositoryFolder, "sources/setup/workspace_template/target_teavm_javascript/buildtools/MakeOfflineDownload.jar");
|
||||
MakeOfflineDownload.compilerMain(offlineDownloadGenerator, new String[] {
|
||||
offlineTemplateArg.getAbsolutePath(),
|
||||
classesJS.getAbsolutePath(), (new File(outputDirectory, "assets.epk")).getAbsolutePath(),
|
||||
|
@ -68,7 +68,9 @@ public class PullRequestTask {
|
||||
File originalSourceMain = new File(EaglerBuildTools.repositoryRoot, "sources/main/java");
|
||||
File originalSourceProtoGame = new File(EaglerBuildTools.repositoryRoot, "sources/protocol-game/java");
|
||||
File originalSourceProtoRelay = new File(EaglerBuildTools.repositoryRoot, "sources/protocol-relay/java");
|
||||
File originalSourcePlatformAPI = new File(EaglerBuildTools.repositoryRoot, "sources/platform-api/java");
|
||||
File originalSourceTeaVM = new File(EaglerBuildTools.repositoryRoot, "sources/teavm/java");
|
||||
File originalSourceTeaVMRes = new File(EaglerBuildTools.repositoryRoot, "sources/teavm/resources");
|
||||
File originalSourceTeaVMC = new File(EaglerBuildTools.repositoryRoot, "sources/teavmc-classpath/resources");
|
||||
File originalSourceBootMenu = new File(EaglerBuildTools.repositoryRoot, "sources/teavm-boot-menu/java");
|
||||
File originalSourceLWJGL = new File(EaglerBuildTools.repositoryRoot, "sources/lwjgl/java");
|
||||
@ -84,7 +86,9 @@ public class PullRequestTask {
|
||||
File diffFromGame = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/game/java");
|
||||
File diffFromProtoGame = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/protocol-game/java");
|
||||
File diffFromProtoRelay = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/protocol-relay/java");
|
||||
File diffFromPlatformAPI = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/platform-api/java");
|
||||
File diffFromTeaVM = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavm/java");
|
||||
File diffFromTeaVMRes = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavm/resources");
|
||||
File diffFromBootMenu = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavm-boot-menu/java");
|
||||
File diffFromTeaVMC = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/teavmc-classpath/resources");
|
||||
File diffFromLWJGL = new File(EaglerBuildToolsConfig.getWorkspaceDirectory(), "src/lwjgl/java");
|
||||
@ -149,12 +153,24 @@ public class PullRequestTask {
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/protocol-relay/java/");
|
||||
|
||||
i = copyAllModified(diffFromPlatformAPI, originalSourcePlatformAPI);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/platform-api/java/");
|
||||
|
||||
i = copyAllModified(diffFromTeaVM, originalSourceTeaVM);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/teavm/java/");
|
||||
|
||||
i = copyAllModified(diffFromTeaVMRes, originalSourceTeaVMRes);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
}
|
||||
System.out.println("Found " + i + " changed files in /src/teavm/resources/");
|
||||
|
||||
i = copyAllModified(diffFromBootMenu, originalSourceBootMenu);
|
||||
if(i > 0) {
|
||||
flag = true;
|
||||
|
@ -124,9 +124,11 @@ public class SetupWorkspace {
|
||||
File repoSourcesSetup = new File(repoSources, "setup/workspace_template");
|
||||
File repoSourcesMain = new File(repoSources, "main/java");
|
||||
File repoSourcesTeaVM = new File(repoSources, "teavm/java");
|
||||
File repoSourcesTeaVMRes = new File(repoSources, "teavm/resources");
|
||||
File repoSourcesLWJGL = new File(repoSources, "lwjgl/java");
|
||||
File repoSourcesProtoGame = new File(repoSources, "protocol-game/java");
|
||||
File repoSourcesProtoRelay = new File(repoSources, "protocol-relay/java");
|
||||
File repoSourcesPlatformAPI = new File(repoSources, "platform-api/java");
|
||||
File repoSourcesBootMenu = new File(repoSources, "teavm-boot-menu/java");
|
||||
File repoSourcesTeavmCRes = new File(repoSources, "teavmc-classpath/resources");
|
||||
File repoSourcesWASMGCTeaVMJava = new File(repoSources, "wasm-gc-teavm/java");
|
||||
@ -139,8 +141,10 @@ public class SetupWorkspace {
|
||||
File srcGameJava = new File(workspaceDirectory, "src/game/java");
|
||||
File srcLWJGLJava = new File(workspaceDirectory, "src/lwjgl/java");
|
||||
File srcTeaVMJava = new File(workspaceDirectory, "src/teavm/java");
|
||||
File srcTeaVMRes = new File(workspaceDirectory, "src/teavm/resources");
|
||||
File srcProtoGame = new File(workspaceDirectory, "src/protocol-game/java");
|
||||
File srcProtoRelay = new File(workspaceDirectory, "src/protocol-relay/java");
|
||||
File srcPlatformAPI = new File(workspaceDirectory, "src/platform-api/java");
|
||||
File srcBootMenu = new File(workspaceDirectory, "src/teavm-boot-menu/java");
|
||||
File srcTeavmCRes = new File(workspaceDirectory, "src/teavmc-classpath/resources");
|
||||
File srcWASMGCTeaVMJava = new File(workspaceDirectory, "src/wasm-gc-teavm/java");
|
||||
@ -150,7 +154,9 @@ public class SetupWorkspace {
|
||||
File srcWASMGCTeaVMLoaderJS = new File(workspaceDirectory, "src/wasm-gc-teavm-loader/js");
|
||||
File resourcesExtractTo = new File(workspaceDirectory, "desktopRuntime/resources");
|
||||
File mcLanguagesZip = new File(mcTmpDirectory, "minecraft_languages.zip");
|
||||
File mcLanguagesExtractTo = new File(workspaceDirectory, "javascript/lang");
|
||||
File localLibsZip = new File(repoSources, "setup/local-libs.zip");
|
||||
File mcLanguagesExtractTo = new File(workspaceDirectory, "target_teavm_javascript/javascript/lang");
|
||||
File localLibsExtractTo = new File(workspaceDirectory, "gradle/local-libs");
|
||||
|
||||
System.out.println("Copying files from \"/setup/workspace_template/\" to \"" + workspaceDirectory.getName() + "\"...");
|
||||
|
||||
@ -161,23 +167,19 @@ public class SetupWorkspace {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
String os = System.getProperty("os.name").toLowerCase();
|
||||
if(os.contains("linux") || os.contains("macos") || os.contains("osx")) {
|
||||
File gradleW = new File(workspaceDirectory, "gradlew");
|
||||
if(!gradleW.setExecutable(true)) {
|
||||
System.err.println("ERROR: could not set executable bit on 'gradlew'!");
|
||||
System.err.println("Enter the root directory of the repository and run 'chmod +x gradlew' if you need access to the gradlew command");
|
||||
}
|
||||
}
|
||||
|
||||
File existingGi = new File(workspaceDirectory, ".gitignore");
|
||||
if((existingGi.exists() && !existingGi.delete()) || !(new File(workspaceDirectory, ".gitignore.default").renameTo(existingGi))) {
|
||||
System.err.println("ERROR: Could not rename \".gitignore.default\" to \".gitignore\" in the workspace directory!");
|
||||
}
|
||||
|
||||
existingGi = new File(workspaceDirectory, "wasm_gc_teavm/.gitignore");
|
||||
if((existingGi.exists() && !existingGi.delete()) || !(new File(workspaceDirectory, "wasm_gc_teavm/.gitignore.default").renameTo(existingGi))) {
|
||||
System.err.println("ERROR: Could not rename \"wasm_gc_teavm/.gitignore.default\" to \"wasm_gc_teavm/.gitignore\" in the workspace directory!");
|
||||
existingGi = new File(workspaceDirectory, "target_teavm_javascript/.gitignore");
|
||||
if((existingGi.exists() && !existingGi.delete()) || !(new File(workspaceDirectory, "target_teavm_javascript/.gitignore.default").renameTo(existingGi))) {
|
||||
System.err.println("ERROR: Could not rename \"target_teavm_javascript/.gitignore.default\" to \"target_teavm_javascript/.gitignore\" in the workspace directory!");
|
||||
}
|
||||
|
||||
existingGi = new File(workspaceDirectory, "target_teavm_wasm_gc/.gitignore");
|
||||
if((existingGi.exists() && !existingGi.delete()) || !(new File(workspaceDirectory, "target_teavm_wasm_gc/.gitignore.default").renameTo(existingGi))) {
|
||||
System.err.println("ERROR: Could not rename \"target_teavm_wasm_gc/.gitignore.default\" to \"target_teavm_wasm_gc/.gitignore\" in the workspace directory!");
|
||||
}
|
||||
|
||||
if(repoSourcesTeaVM.isDirectory()) {
|
||||
@ -195,6 +197,21 @@ public class SetupWorkspace {
|
||||
}
|
||||
}
|
||||
|
||||
if(repoSourcesTeaVMRes.isDirectory()) {
|
||||
System.out.println("Copying files from \"/sources/teavm/resources/\" to workspace...");
|
||||
|
||||
try {
|
||||
if(!srcTeaVMRes.isDirectory() && !srcTeaVMRes.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
FileUtils.copyDirectory(repoSourcesTeaVMRes, srcTeaVMRes);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/teavm/resources/\" to \"" + srcTeaVMRes.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Copying files from \"/sources/main/java/\" to workspace...");
|
||||
|
||||
try {
|
||||
@ -238,6 +255,21 @@ public class SetupWorkspace {
|
||||
}
|
||||
}
|
||||
|
||||
if(repoSourcesPlatformAPI.isDirectory()) {
|
||||
System.out.println("Copying files from \"/sources/platform-api/java/\" to workspace...");
|
||||
|
||||
try {
|
||||
if(!srcPlatformAPI.isDirectory() && !srcPlatformAPI.mkdirs()) {
|
||||
System.err.println("ERROR: Could not create destination directory!");
|
||||
return false;
|
||||
}
|
||||
FileUtils.copyDirectory(repoSourcesPlatformAPI, srcPlatformAPI);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not copy \"/sources/platform-api/java/\" to \"" + srcPlatformAPI.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
if(repoSourcesTeavmCRes.isDirectory()) {
|
||||
System.out.println("Copying files from \"/sources/teavmc-classpath/resources/\" to workspace...");
|
||||
|
||||
@ -448,7 +480,7 @@ public class SetupWorkspace {
|
||||
minecraftResJar.delete();
|
||||
}
|
||||
|
||||
System.out.println("Extracting files from \"minecraft_languages.zip\" to \"/javascript/lang/\"...");
|
||||
System.out.println("Extracting files from \"minecraft_languages.zip\" to \"/target_teavm_javascript/javascript/lang/\"...");
|
||||
|
||||
try {
|
||||
extractJarTo(mcLanguagesZip, mcLanguagesExtractTo);
|
||||
@ -458,12 +490,22 @@ public class SetupWorkspace {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
System.out.println("Creating eclipse project for desktop runtime...");
|
||||
if(!createDesktopRuntimeProject(new File(repoSources, "setup/eclipseProjectFiles"), workspaceDirectory)) {
|
||||
System.err.println("ERROR: could not create eclipse project for desktop runtime!");
|
||||
return false;
|
||||
System.out.println("Extracting files from \"local-libs.zip\" to \"/gradle/local-libs/\"...");
|
||||
|
||||
try {
|
||||
extractJarTo(localLibsZip, localLibsExtractTo);
|
||||
}catch(IOException ex) {
|
||||
System.err.println("ERROR: could not extract \"" + localLibsZip.getName() + "\" to \"" +
|
||||
localLibsExtractTo.getAbsolutePath() + "\"!");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// System.out.println("Creating eclipse project for desktop runtime...");
|
||||
// if(!createDesktopRuntimeProject(new File(repoSources, "setup/eclipseProjectFiles"), workspaceDirectory)) {
|
||||
// System.err.println("ERROR: could not create eclipse project for desktop runtime!");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -497,6 +539,7 @@ public class SetupWorkspace {
|
||||
return cnt;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
private static boolean createDesktopRuntimeProject(File templateFolderIn, File workspaceDirectory) throws Throwable {
|
||||
File desktopRuntimeDirectory = new File(workspaceDirectory, "desktopRuntime");
|
||||
File desktopRuntimeProjectDir = new File(desktopRuntimeDirectory, "eclipseProject");
|
||||
|
@ -1 +1 @@
|
||||
u50
|
||||
u51
|
@ -1,4 +1,4 @@
|
||||
# 148 files to delete:
|
||||
# 149 files to delete:
|
||||
net/minecraft/client/renderer/VertexBufferUploader.java
|
||||
net/minecraft/realms/DisconnectedRealmsScreen.java
|
||||
net/minecraft/client/stream/Metadata.java
|
||||
@ -14,6 +14,7 @@ net/minecraft/command/server/CommandSaveAll.java
|
||||
net/minecraft/realms/RealmsVertexFormat.java
|
||||
net/minecraft/network/NettyCompressionDecoder.java
|
||||
net/minecraft/profiler/PlayerUsageSnooper.java
|
||||
net/minecraft/util/MinecraftError.java
|
||||
net/minecraft/command/server/CommandPublishLocalServer.java
|
||||
net/minecraft/command/CommandDebug.java
|
||||
net/minecraft/client/renderer/chunk/VboChunkFactory.java
|
||||
|
@ -18,23 +18,29 @@
|
||||
|
||||
~ import net.minecraft.client.resources.I18n;
|
||||
|
||||
> DELETE 9 @ 9 : 11
|
||||
> DELETE 1 @ 1 : 2
|
||||
|
||||
> DELETE 7 @ 7 : 9
|
||||
|
||||
> DELETE 3 @ 3 : 6
|
||||
|
||||
> CHANGE 22 : 24 @ 22 : 32
|
||||
> CHANGE 14 : 15 @ 14 : 19
|
||||
|
||||
~ if (this.mc.running) {
|
||||
|
||||
> CHANGE 3 : 5 @ 3 : 13
|
||||
|
||||
~ GlStateManager.ortho(0.0D, mc.scaledResolution.getScaledWidth_double(),
|
||||
~ mc.scaledResolution.getScaledHeight_double(), 0.0D, 100.0D, 300.0D);
|
||||
|
||||
> INSERT 19 : 37 @ 19
|
||||
> CHANGE 7 : 8 @ 7 : 12
|
||||
|
||||
~ if (this.mc.running) {
|
||||
|
||||
> INSERT 7 : 21 @ 7
|
||||
|
||||
+ public void eaglerShow(String line1, String line2) {
|
||||
+ if (!this.mc.running) {
|
||||
+ if (!this.field_73724_e) {
|
||||
+ throw new MinecraftError();
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (this.mc.running) {
|
||||
+ this.systemTime = 0L;
|
||||
+ this.currentlyDisplayedText = line1;
|
||||
+ this.message = line2;
|
||||
@ -48,7 +54,11 @@
|
||||
+ }
|
||||
+
|
||||
|
||||
> CHANGE 9 : 10 @ 9 : 10
|
||||
> CHANGE 1 : 2 @ 1 : 6
|
||||
|
||||
~ if (this.mc.running) {
|
||||
|
||||
> CHANGE 3 : 4 @ 3 : 4
|
||||
|
||||
~ ScaledResolution scaledresolution = mc.scaledResolution;
|
||||
|
||||
|
@ -18,14 +18,13 @@
|
||||
|
||||
> DELETE 1 @ 1 : 4
|
||||
|
||||
> CHANGE 1 : 75 @ 1 : 4
|
||||
> CHANGE 1 : 76 @ 1 : 4
|
||||
|
||||
~
|
||||
~ import net.lax1dude.eaglercraft.v1_8.ClientUUIDLoadingCache;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.Display;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.EagUtils;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.EaglerXBungeeVersion;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.HString;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.IOUtils;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.Keyboard;
|
||||
@ -43,6 +42,7 @@
|
||||
~ import net.lax1dude.eaglercraft.v1_8.futures.FutureTask;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.futures.ListenableFuture;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.futures.ListenableFutureTask;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.internal.ContextLostError;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformType;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.internal.PlatformWebRTC;
|
||||
@ -76,6 +76,7 @@
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.AddressResolver;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.RateLimitTracker;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.client.StateFlags;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.IntegratedServerState;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.SkullCommand;
|
||||
@ -139,7 +140,9 @@
|
||||
+ import net.minecraft.util.ChatStyle;
|
||||
+ import net.minecraft.util.EnumChatFormatting;
|
||||
|
||||
> INSERT 7 : 8 @ 7
|
||||
> DELETE 3 @ 3 : 4
|
||||
|
||||
> INSERT 3 : 4 @ 3
|
||||
|
||||
+ import net.minecraft.util.MovingObjectPosition.MovingObjectType;
|
||||
|
||||
@ -256,12 +259,14 @@
|
||||
|
||||
~ this.runGameLoop();
|
||||
|
||||
> DELETE 4 @ 4 : 21
|
||||
> CHANGE 4 : 5 @ 4 : 21
|
||||
|
||||
~ return;
|
||||
|
||||
> CHANGE 1 : 14 @ 1 : 3
|
||||
|
||||
~ } catch (MinecraftError var12) {
|
||||
~ // ??
|
||||
~ } catch (ContextLostError err) {
|
||||
~ throw err;
|
||||
~ } catch (ReportedException reportedexception) {
|
||||
~ this.addGraphicsAndWorldToCrashReport(reportedexception.getCrashReport());
|
||||
~ logger.fatal("Reported exception thrown!", reportedexception);
|
||||
@ -555,8 +560,10 @@
|
||||
~ long i = EagRuntime.nanoTime();
|
||||
~ if (Display.isCloseRequested()) {
|
||||
|
||||
> INSERT 3 : 6 @ 3
|
||||
> INSERT 3 : 8 @ 3
|
||||
|
||||
+ Display.checkContextLost();
|
||||
+
|
||||
+ PointerInputAbstraction.runGameLoop();
|
||||
+ this.gameSettings.touchscreen = PointerInputAbstraction.isTouchMode();
|
||||
+
|
||||
@ -583,34 +590,31 @@
|
||||
|
||||
> DELETE 1 @ 1 : 2
|
||||
|
||||
> DELETE 1 @ 1 : 11
|
||||
> CHANGE 1 : 6 @ 1 : 3
|
||||
|
||||
> CHANGE 1 : 12 @ 1 : 7
|
||||
~
|
||||
~ EaglercraftGPU.optimize();
|
||||
~ _wglBindFramebuffer(0x8D40, null);
|
||||
~ GlStateManager.viewport(0, 0, this.displayWidth, this.displayHeight);
|
||||
~ GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
~ if (!Display.contextLost()) {
|
||||
~ EaglercraftGPU.optimize();
|
||||
~ _wglBindFramebuffer(0x8D40, null);
|
||||
~ GlStateManager.viewport(0, 0, this.displayWidth, this.displayHeight);
|
||||
~ GlStateManager.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
~ GlStateManager.pushMatrix();
|
||||
~ GlStateManager.clear(16640);
|
||||
~ GlStateManager.enableTexture2D();
|
||||
~ if (this.thePlayer != null && this.thePlayer.isEntityInsideOpaqueBlock()) {
|
||||
~ this.gameSettings.thirdPersonView = 0;
|
||||
~ }
|
||||
> DELETE 2 @ 2 : 4
|
||||
|
||||
> CHANGE 1 : 3 @ 1 : 5
|
||||
> DELETE 5 @ 5 : 6
|
||||
|
||||
~ if (!this.skipRenderWorld) {
|
||||
~ this.entityRenderer.func_181560_a(this.timer.renderPartialTicks, i);
|
||||
> DELETE 1 @ 1 : 2
|
||||
|
||||
> CHANGE 2 : 5 @ 2 : 7
|
||||
> DELETE 1 @ 1 : 2
|
||||
|
||||
~ this.guiAchievement.updateAchievementWindow();
|
||||
~ this.touchOverlayRenderer.render(displayWidth, displayHeight, scaledResolution);
|
||||
~ GlStateManager.popMatrix();
|
||||
> DELETE 2 @ 2 : 15
|
||||
|
||||
> DELETE 2 @ 2 : 12
|
||||
> CHANGE 1 : 2 @ 1 : 2
|
||||
|
||||
~ this.touchOverlayRenderer.render(displayWidth, displayHeight, scaledResolution);
|
||||
|
||||
> CHANGE 1 : 2 @ 1 : 8
|
||||
|
||||
~
|
||||
|
||||
> DELETE 1 @ 1 : 9
|
||||
|
||||
@ -777,7 +781,7 @@
|
||||
|
||||
> CHANGE 4 : 6 @ 4 : 5
|
||||
|
||||
~ VoiceClientController.tickVoiceClient(this);
|
||||
~ VoiceClientController.tickVoiceClient();
|
||||
~
|
||||
|
||||
> DELETE 1 @ 1 : 2
|
||||
@ -1047,29 +1051,29 @@
|
||||
~ if (bungeeOutdatedMsgTimer > 0) {
|
||||
~ if (--bungeeOutdatedMsgTimer == 0 && this.thePlayer.sendQueue != null) {
|
||||
~ String pluginBrand = this.thePlayer.sendQueue.getNetworkManager().getPluginBrand();
|
||||
~ String pluginVersion = this.thePlayer.sendQueue.getNetworkManager().getPluginVersion();
|
||||
~ if (pluginBrand != null && pluginVersion != null
|
||||
~ && EaglerXBungeeVersion.isUpdateToPluginAvailable(pluginBrand, pluginVersion)) {
|
||||
~ if (pluginBrand != null && ("EaglercraftXBungee".equals(pluginBrand)
|
||||
~ || "EaglercraftXVelocity".equals(pluginBrand))) {
|
||||
~ String pfx = EnumChatFormatting.GOLD + "[EagX]" + EnumChatFormatting.AQUA;
|
||||
~ ingameGUI.getChatGUI().printChatMessage(
|
||||
~ new ChatComponentText(pfx + " ---------------------------------------"));
|
||||
~ ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(pfx + " This server is running "
|
||||
~ + EnumChatFormatting.YELLOW + pluginBrand + EnumChatFormatting.AQUA + ","));
|
||||
~ ingameGUI.getChatGUI().printChatMessage(
|
||||
~ new ChatComponentText(pfx + " This server appears to be using version "
|
||||
~ + EnumChatFormatting.YELLOW + pluginVersion));
|
||||
~ new ChatComponentText(pfx + " which has been discontinued by lax1dude."));
|
||||
~ ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(pfx));
|
||||
~ ingameGUI.getChatGUI().printChatMessage(
|
||||
~ new ChatComponentText(pfx + " of the EaglerXBungee plugin which is outdated"));
|
||||
~ new ChatComponentText(pfx + " If you are the admin of this server, please"));
|
||||
~ ingameGUI.getChatGUI().printChatMessage(
|
||||
~ new ChatComponentText(pfx + " upgrade to EaglercraftXServer if you want to"));
|
||||
~ ingameGUI.getChatGUI().printChatMessage(
|
||||
~ new ChatComponentText(pfx + " to continue to receive support and bugfixes."));
|
||||
~ ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(pfx));
|
||||
~ ingameGUI.getChatGUI()
|
||||
~ .printChatMessage(new ChatComponentText(pfx + " If you are the admin update to "
|
||||
~ + EnumChatFormatting.YELLOW + EaglerXBungeeVersion.getPluginVersion()
|
||||
~ + EnumChatFormatting.AQUA + " or newer"));
|
||||
~ ingameGUI.getChatGUI().printChatMessage(new ChatComponentText(pfx));
|
||||
~ ingameGUI.getChatGUI().printChatMessage((new ChatComponentText(pfx + " Click: "))
|
||||
~ .appendSibling((new ChatComponentText("" + EnumChatFormatting.GREEN
|
||||
~ + EnumChatFormatting.UNDERLINE + EaglerXBungeeVersion.getPluginButton()))
|
||||
~ .setChatStyle((new ChatStyle()).setChatClickEvent(
|
||||
~ new ClickEvent(ClickEvent.Action.EAGLER_PLUGIN_DOWNLOAD,
|
||||
~ "plugin_download.zip")))));
|
||||
~ .printChatMessage((new ChatComponentText(pfx + " " + EnumChatFormatting.GREEN
|
||||
~ + EnumChatFormatting.UNDERLINE + "https://lax1dude.net/eaglerxserver"))
|
||||
~ .setChatStyle((new ChatStyle())
|
||||
~ .setChatClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL,
|
||||
~ "https://lax1dude.net/eaglerxserver"))));
|
||||
~ ingameGUI.getChatGUI().printChatMessage(
|
||||
~ new ChatComponentText(pfx + " ---------------------------------------"));
|
||||
~ }
|
||||
@ -1228,7 +1232,7 @@
|
||||
+ EaglerProfile.clearServerSkinOverride();
|
||||
+ PauseMenuCustomizeState.reset();
|
||||
+ ClientUUIDLoadingCache.flushRequestCache();
|
||||
+ ClientUUIDLoadingCache.resetFlags();
|
||||
+ StateFlags.reset();
|
||||
+ WebViewOverlayController.setPacketSendCallback(null);
|
||||
|
||||
> DELETE 1 @ 1 : 7
|
||||
@ -1254,7 +1258,11 @@
|
||||
|
||||
~ public void middleClickMouse() {
|
||||
|
||||
> CHANGE 127 : 128 @ 127 : 128
|
||||
> CHANGE 76 : 77 @ 76 : 77
|
||||
|
||||
~ if (!EntityList.entityEggs.containsKey(i)) {
|
||||
|
||||
> CHANGE 50 : 51 @ 50 : 51
|
||||
|
||||
~ return EagRuntime.getVersion();
|
||||
|
||||
|
@ -10,11 +10,10 @@
|
||||
+ import java.io.IOException;
|
||||
+
|
||||
|
||||
> CHANGE 2 : 18 @ 2 : 15
|
||||
> CHANGE 2 : 17 @ 2 : 15
|
||||
|
||||
~
|
||||
~ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.EaglerXBungeeVersion;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.Keyboard;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.Mouse;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.cookie.ServerCookieDataStore;
|
||||
@ -207,7 +206,7 @@
|
||||
+ GlStateManager.scale(0.75f, 0.75f, 0.75f);
|
||||
+ GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
+
|
||||
+ String text = EaglerXBungeeVersion.getPluginButton();
|
||||
+ String text = "Download EaglerXServer";
|
||||
+ int w = mc.fontRendererObj.getStringWidth(text);
|
||||
+ boolean hover = xx > width - 5 - (w + 5) * 3 / 4 && yy > 1 && xx < width - 2 && yy < 12;
|
||||
+ if (hover) {
|
||||
@ -268,12 +267,12 @@
|
||||
|
||||
> INSERT 2 : 9 @ 2
|
||||
|
||||
+ String text = EaglerXBungeeVersion.getPluginButton();
|
||||
+ String text = "Download EaglerXServer";
|
||||
+ int w = mc.fontRendererObj.getStringWidth(text);
|
||||
+ if (parInt1 > width - 5 - (w + 5) * 3 / 4 && parInt2 > 1 && parInt1 < width - 2 && parInt2 < 12) {
|
||||
+ this.mc.getSoundHandler()
|
||||
+ .playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F));
|
||||
+ EaglerXBungeeVersion.startPluginDownload();
|
||||
+ EagRuntime.openLink("https://lax1dude.net/eaglerxserver");
|
||||
+ }
|
||||
|
||||
> INSERT 11 : 15 @ 11
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
> DELETE 1 @ 1 : 3
|
||||
|
||||
> INSERT 4 : 29 @ 4
|
||||
> INSERT 4 : 28 @ 4
|
||||
|
||||
+
|
||||
+ import net.lax1dude.eaglercraft.v1_8.internal.EnumTouchEvent;
|
||||
@ -22,7 +22,6 @@
|
||||
+ import com.google.common.collect.Sets;
|
||||
+
|
||||
+ import net.lax1dude.eaglercraft.v1_8.EagRuntime;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.EaglerXBungeeVersion;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.Keyboard;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.Mouse;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.PauseMenuCustomizeState;
|
||||
@ -221,7 +220,7 @@
|
||||
|
||||
~ // rip
|
||||
|
||||
> CHANGE 5 : 15 @ 5 : 8
|
||||
> CHANGE 5 : 12 @ 5 : 11
|
||||
|
||||
~ /*
|
||||
~ * ChatUserInfo chatuserinfo =
|
||||
@ -230,16 +229,8 @@
|
||||
~ * GuiTwitchUserMode(this.mc.getTwitchStream(), chatuserinfo)); } else { }
|
||||
~ */
|
||||
~ LOGGER.error("Tried to handle twitch user but couldn\'t find them!");
|
||||
~ } else if (clickevent.getAction() == ClickEvent.Action.EAGLER_PLUGIN_DOWNLOAD) {
|
||||
~ if (EaglerXBungeeVersion.pluginFileEPK.equals(clickevent.getValue())) {
|
||||
~ EaglerXBungeeVersion.startPluginDownload();
|
||||
|
||||
> CHANGE 1 : 3 @ 1 : 2
|
||||
|
||||
~ LOGGER.error("Invalid plugin download from EPK was blocked: {}",
|
||||
~ EaglerXBungeeVersion.pluginFileEPK);
|
||||
|
||||
> CHANGE 24 : 49 @ 24 : 26
|
||||
> CHANGE 23 : 48 @ 23 : 25
|
||||
|
||||
~ protected void touchStarted(int parInt1, int parInt2, int parInt3) {
|
||||
~ if (shouldTouchGenerateMouseEvents()) {
|
||||
|
@ -23,6 +23,6 @@
|
||||
> CHANGE 11 : 13 @ 11 : 12
|
||||
|
||||
~ Minecraft.getMinecraft().getTextureManager().bindTexture(
|
||||
~ Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(profile).getResourceLocation());
|
||||
~ Minecraft.getMinecraft().getNetHandler().getTextureCache().getPlayerSkin(profile).getLocation());
|
||||
|
||||
> EOF
|
||||
|
@ -5,7 +5,7 @@
|
||||
# Version: 1.0
|
||||
# Author: lax1dude
|
||||
|
||||
> CHANGE 3 : 21 @ 3 : 6
|
||||
> CHANGE 2 : 16 @ 2 : 6
|
||||
|
||||
~ import java.util.List;
|
||||
~
|
||||
@ -17,22 +17,14 @@
|
||||
~ import net.lax1dude.eaglercraft.v1_8.internal.PlatformNetworking;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.log4j.Logger;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.AddressResolver;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.ConnectionHandshake;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.RateLimitTracker;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.WebSocketNetworkManager;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageConstants;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.client.GameProtocolMessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.handshake.HandshakerHandler;
|
||||
|
||||
> CHANGE 4 : 5 @ 4 : 8
|
||||
> DELETE 4 @ 4 : 8
|
||||
|
||||
~ import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
|
||||
> CHANGE 2 : 3 @ 2 : 5
|
||||
|
||||
~ import net.minecraft.network.play.client.C17PacketCustomPayload;
|
||||
> DELETE 1 @ 1 : 5
|
||||
|
||||
> DELETE 1 @ 1 : 4
|
||||
|
||||
@ -41,17 +33,13 @@
|
||||
> CHANGE 1 : 7 @ 1 : 2
|
||||
|
||||
~ private IWebSocketClient webSocket;
|
||||
~ private EaglercraftNetworkManager networkManager;
|
||||
~ private HandshakerHandler handshaker;
|
||||
~ private String currentAddress;
|
||||
~ private String currentPassword;
|
||||
~ private boolean allowPlaintext;
|
||||
~ private boolean allowCookies;
|
||||
|
||||
> INSERT 1 : 2 @ 1
|
||||
|
||||
+ private boolean hasOpened;
|
||||
|
||||
> INSERT 1 : 2 @ 1
|
||||
> INSERT 2 : 3 @ 2
|
||||
|
||||
+ private int timer = 0;
|
||||
|
||||
@ -155,12 +143,15 @@
|
||||
~ new ChatComponentText("Could not open WebSocket to \"" + currentAddress + "\"!")));
|
||||
~ }
|
||||
|
||||
> CHANGE 1 : 81 @ 1 : 2
|
||||
> CHANGE 1 : 38 @ 1 : 2
|
||||
|
||||
~ if (webSocket.getState() == EnumEaglerConnectionState.CONNECTED) {
|
||||
~ if (!hasOpened) {
|
||||
~ hasOpened = true;
|
||||
~ EnumEaglerConnectionState connState = webSocket.getState();
|
||||
~ if (connState == EnumEaglerConnectionState.CONNECTED) {
|
||||
~ if (handshaker == null) {
|
||||
~ this.mc.getSession().reset();
|
||||
~
|
||||
~ logger.info("Logging in: {}", currentAddress);
|
||||
~
|
||||
~ byte[] cookieData = null;
|
||||
~ if (allowCookies) {
|
||||
~ ServerCookieDataStore.ServerCookie cookie = ServerCookieDataStore
|
||||
@ -169,61 +160,15 @@
|
||||
~ cookieData = cookie.cookie;
|
||||
~ }
|
||||
~ }
|
||||
~ if (ConnectionHandshake.attemptHandshake(this.mc, webSocket, this, previousGuiScreen,
|
||||
~ currentPassword, allowPlaintext, allowCookies, cookieData)) {
|
||||
~ logger.info("Handshake Success");
|
||||
~ webSocket.setEnableStringFrames(false);
|
||||
~ webSocket.clearStringFrames();
|
||||
~ this.networkManager = new WebSocketNetworkManager(webSocket);
|
||||
~ this.networkManager.setPluginInfo(ConnectionHandshake.pluginBrand,
|
||||
~ ConnectionHandshake.pluginVersion);
|
||||
~ mc.bungeeOutdatedMsgTimer = 80;
|
||||
~ mc.clearTitles();
|
||||
~ this.networkManager.setConnectionState(EnumConnectionState.PLAY);
|
||||
~ NetHandlerPlayClient netHandler = new NetHandlerPlayClient(this.mc, previousGuiScreen,
|
||||
~ this.networkManager, this.mc.getSession().getProfile());
|
||||
~ this.networkManager.setNetHandler(netHandler);
|
||||
~ netHandler.setEaglerMessageController(new GameProtocolMessageController(
|
||||
~ GamePluginMessageProtocol.getByVersion(ConnectionHandshake.protocolVersion),
|
||||
~ GamePluginMessageConstants.CLIENT_TO_SERVER,
|
||||
~ GameProtocolMessageController
|
||||
~ .createClientHandler(ConnectionHandshake.protocolVersion, netHandler),
|
||||
~ (ch, msg) -> netHandler.addToSendQueue(new C17PacketCustomPayload(ch, msg))));
|
||||
~ } else {
|
||||
~ if (mc.currentScreen == this) {
|
||||
~ checkRatelimit();
|
||||
~ logger.info("Handshake Failure");
|
||||
~ mc.getSession().reset();
|
||||
~ mc.displayGuiScreen(
|
||||
~ new GuiDisconnected(previousGuiScreen, "connect.failed", new ChatComponentText(
|
||||
~ "Handshake Failure\n\nAre you sure this is an eagler 1.8 server?")));
|
||||
~ }
|
||||
~ webSocket.close();
|
||||
~ return;
|
||||
~ }
|
||||
~ }
|
||||
~ if (this.networkManager != null) {
|
||||
~ try {
|
||||
~ this.networkManager.processReceivedPackets();
|
||||
~ } catch (IOException ex) {
|
||||
~ }
|
||||
~
|
||||
~ handshaker = new HandshakerHandler(this, webSocket, EaglerProfile.getName(), currentPassword,
|
||||
~ allowPlaintext, allowCookies, cookieData);
|
||||
~ }
|
||||
~ handshaker.tick();
|
||||
~ } else {
|
||||
~ if (webSocket.getState() == EnumEaglerConnectionState.FAILED) {
|
||||
~ if (!hasOpened) {
|
||||
~ mc.getSession().reset();
|
||||
~ checkRatelimit();
|
||||
~ if (mc.currentScreen == this) {
|
||||
~ if (RateLimitTracker.isProbablyLockedOut(currentAddress)) {
|
||||
~ mc.displayGuiScreen(GuiDisconnected.createRateLimitKick(previousGuiScreen));
|
||||
~ } else {
|
||||
~ mc.displayGuiScreen(new GuiDisconnected(previousGuiScreen, "connect.failed",
|
||||
~ new ChatComponentText("Connection Refused")));
|
||||
~ }
|
||||
~ }
|
||||
~ }
|
||||
~ } else {
|
||||
~ if (this.networkManager != null && this.networkManager.checkDisconnected()) {
|
||||
~ if (handshaker != null) {
|
||||
~ handshaker.tick();
|
||||
~ if (connState == EnumEaglerConnectionState.FAILED) {
|
||||
~ this.mc.getSession().reset();
|
||||
~ checkRatelimit();
|
||||
~ if (mc.currentScreen == this) {
|
||||
@ -263,16 +208,15 @@
|
||||
|
||||
~ protected void actionPerformed(GuiButton parGuiButton) {
|
||||
|
||||
> INSERT 4 : 6 @ 4
|
||||
> CHANGE 2 : 3 @ 2 : 6
|
||||
|
||||
+ } else if (this.webSocket != null) {
|
||||
+ this.webSocket.close();
|
||||
~ this.webSocket.close();
|
||||
|
||||
> CHANGE 9 : 10 @ 9 : 10
|
||||
> CHANGE 7 : 8 @ 7 : 8
|
||||
|
||||
~ if (this.networkManager == null || !this.networkManager.isChannelOpen()) {
|
||||
~ if (this.handshaker == null) {
|
||||
|
||||
> INSERT 9 : 34 @ 9
|
||||
> INSERT 9 : 43 @ 9
|
||||
|
||||
+
|
||||
+ private void checkRatelimit() {
|
||||
@ -299,5 +243,14 @@
|
||||
+ public boolean canCloseGui() {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ public static Minecraft getMC(GuiConnecting gui) {
|
||||
+ return gui.mc;
|
||||
+ }
|
||||
+
|
||||
+ public static GuiScreen getPrevScreen(GuiConnecting gui) {
|
||||
+ return gui.previousGuiScreen;
|
||||
+ }
|
||||
+
|
||||
|
||||
> EOF
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
+ import net.minecraft.util.ChatComponentText;
|
||||
|
||||
> CHANGE 228 : 242 @ 228 : 229
|
||||
> CHANGE 228 : 241 @ 228 : 229
|
||||
|
||||
~ try {
|
||||
~ this.netClientHandler.getNetworkManager().processReceivedPackets();
|
||||
@ -30,8 +30,7 @@
|
||||
~ this.netClientHandler.getNetworkManager()
|
||||
~ .closeChannel(new ChatComponentText("Exception thrown: " + ex.toString()));
|
||||
~ }
|
||||
~ this.netClientHandler.getSkinCache().flush();
|
||||
~ this.netClientHandler.getCapeCache().flush();
|
||||
~ this.netClientHandler.getTextureCache().runTick();
|
||||
~ this.netClientHandler.getNotifManager().runTick();
|
||||
~ ClientUUIDLoadingCache.update();
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
> DELETE 2 @ 2 : 8
|
||||
|
||||
> CHANGE 4 : 28 @ 4 : 7
|
||||
> CHANGE 4 : 32 @ 4 : 7
|
||||
|
||||
~
|
||||
~ import net.lax1dude.eaglercraft.v1_8.ClientUUIDLoadingCache;
|
||||
@ -19,11 +19,15 @@
|
||||
~
|
||||
~ import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.notifications.ServerNotificationManager;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.profile.ServerCapeCache;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.profile.ServerSkinCache;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.skin_cache.ServerTextureCache;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageConstants;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.client.GameProtocolMessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.client.ClientMessageHandler;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.handshake.StandardCaps;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.message.InjectedMessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.message.LegacyMessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.message.MessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.lan.LANClientNetworkManager;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.socket.ClientIntegratedServerNetworkManager;
|
||||
@ -68,70 +72,71 @@
|
||||
|
||||
~ private final Map<EaglercraftUUID, NetworkPlayerInfo> playerInfoMap = Maps.newHashMap();
|
||||
|
||||
> CHANGE 2 : 12 @ 2 : 3
|
||||
> CHANGE 2 : 13 @ 2 : 3
|
||||
|
||||
~ private boolean isIntegratedServer = false;
|
||||
~ private final EaglercraftRandom avRandomizer = new EaglercraftRandom();
|
||||
~ private final ServerSkinCache skinCache;
|
||||
~ private final ServerCapeCache capeCache;
|
||||
~ private final ServerTextureCache textureCache;
|
||||
~ private final ServerNotificationManager notifManager;
|
||||
~ public boolean currentFNAWSkinAllowedState = true;
|
||||
~ public boolean currentFNAWSkinForcedState = true;
|
||||
~ private GameProtocolMessageController eaglerMessageController = null;
|
||||
~ public boolean hasRequestedServerInfo = false;
|
||||
~ private final MessageController eaglerMessageController;
|
||||
~ public byte[] cachedServerInfoHash = null;
|
||||
~ public byte[] cachedServerInfoData = null;
|
||||
~ public boolean allowedDisplayWebview = false;
|
||||
~ public boolean allowedDisplayWebviewYes = false;
|
||||
|
||||
> CHANGE 1 : 2 @ 1 : 2
|
||||
> CHANGE 1 : 3 @ 1 : 3
|
||||
|
||||
~ public NetHandlerPlayClient(Minecraft mcIn, GuiScreen parGuiScreen, EaglercraftNetworkManager parNetworkManager,
|
||||
~ GameProfile parGameProfile, GamePluginMessageProtocol eaglerProtocol) {
|
||||
|
||||
> INSERT 5 : 10 @ 5
|
||||
> INSERT 3 : 4 @ 3
|
||||
|
||||
+ this.netManager.setNetHandler(this);
|
||||
|
||||
> INSERT 1 : 15 @ 1
|
||||
|
||||
+ this.skinCache = new ServerSkinCache(this, mcIn.getTextureManager());
|
||||
+ this.capeCache = new ServerCapeCache(this, mcIn.getTextureManager());
|
||||
+ this.notifManager = new ServerNotificationManager();
|
||||
+ this.isIntegratedServer = (parNetworkManager instanceof ClientIntegratedServerNetworkManager)
|
||||
+ || (parNetworkManager instanceof LANClientNetworkManager);
|
||||
+ ClientMessageHandler handler = ClientMessageHandler.createClientHandler(eaglerProtocol.ver, this);
|
||||
+ if (eaglerProtocol.ver >= 5) {
|
||||
+ this.eaglerMessageController = new InjectedMessageController(eaglerProtocol, handler,
|
||||
+ GamePluginMessageConstants.CLIENT_TO_SERVER, parNetworkManager::injectRawFrame);
|
||||
+ parNetworkManager.setInjectedMessageController((InjectedMessageController) eaglerMessageController);
|
||||
+ } else {
|
||||
+ this.eaglerMessageController = new LegacyMessageController(eaglerProtocol, handler,
|
||||
+ GamePluginMessageConstants.CLIENT_TO_SERVER,
|
||||
+ (ch, msg) -> addToSendQueue(new C17PacketCustomPayload(ch, msg)));
|
||||
+ }
|
||||
+ this.textureCache = ServerTextureCache.create(this, mcIn.getTextureManager());
|
||||
+ this.notifManager = new ServerNotificationManager(mcIn.getTextureManager());
|
||||
|
||||
> INSERT 4 : 7 @ 4
|
||||
> INSERT 4 : 6 @ 4
|
||||
|
||||
+ this.skinCache.destroy();
|
||||
+ this.capeCache.destroy();
|
||||
+ this.textureCache.destroy();
|
||||
+ this.notifManager.destroy();
|
||||
|
||||
> INSERT 2 : 51 @ 2
|
||||
> INSERT 2 : 38 @ 2
|
||||
|
||||
+ public ServerSkinCache getSkinCache() {
|
||||
+ return this.skinCache;
|
||||
+ }
|
||||
+
|
||||
+ public ServerCapeCache getCapeCache() {
|
||||
+ return this.capeCache;
|
||||
+ public ServerTextureCache getTextureCache() {
|
||||
+ return this.textureCache;
|
||||
+ }
|
||||
+
|
||||
+ public ServerNotificationManager getNotifManager() {
|
||||
+ return this.notifManager;
|
||||
+ }
|
||||
+
|
||||
+ public GameProtocolMessageController getEaglerMessageController() {
|
||||
+ public MessageController getEaglerMessageController() {
|
||||
+ return eaglerMessageController;
|
||||
+ }
|
||||
+
|
||||
+ public void setEaglerMessageController(GameProtocolMessageController eaglerMessageController) {
|
||||
+ this.eaglerMessageController = eaglerMessageController;
|
||||
+ }
|
||||
+
|
||||
+ public GamePluginMessageProtocol getEaglerMessageProtocol() {
|
||||
+ return eaglerMessageController != null ? eaglerMessageController.protocol : null;
|
||||
+ return eaglerMessageController != null ? eaglerMessageController.getProtocol() : null;
|
||||
+ }
|
||||
+
|
||||
+ public void sendEaglerMessage(GameMessagePacket packet) {
|
||||
+ try {
|
||||
+ eaglerMessageController.sendPacket(packet);
|
||||
+ } catch (IOException e) {
|
||||
+ logger.error("Failed to send eaglercraft plugin message packet: " + packet);
|
||||
+ logger.error(e);
|
||||
+ }
|
||||
+ eaglerMessageController.sendPacket(packet);
|
||||
+ }
|
||||
+
|
||||
+ public boolean webViewSendHandler(GameMessagePacket pkt) {
|
||||
@ -142,7 +147,7 @@
|
||||
+ logger.error("WebView sent message on a dead handler!");
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (eaglerMessageController.protocol.ver >= 4) {
|
||||
+ if (eaglerMessageController.getProtocol().ver >= 4) {
|
||||
+ sendEaglerMessage(pkt);
|
||||
+ return true;
|
||||
+ } else {
|
||||
@ -158,12 +163,21 @@
|
||||
~ this.clientWorldController = new WorldClient(this, new WorldSettings(0L, packetIn.getGameType(), false,
|
||||
~ packetIn.isHardcoreMode(), packetIn.getWorldType()), packetIn.getDimension(), packetIn.getDifficulty());
|
||||
|
||||
> INSERT 11 : 15 @ 11
|
||||
> INSERT 11 : 24 @ 11
|
||||
|
||||
+ if (VoiceClientController.isClientSupported()) {
|
||||
+ VoiceClientController.initializeVoiceClient(this::sendEaglerMessage, eaglerMessageController.protocol.ver);
|
||||
+ if (netManager.getServerCapabilities().hasCapability(StandardCaps.VOICE, 0)) {
|
||||
+ VoiceClientController.initializeVoiceClient(this::sendEaglerMessage,
|
||||
+ eaglerMessageController.getProtocol().ver);
|
||||
+ } else {
|
||||
+ VoiceClientController.initializeVoiceClient(null, -1);
|
||||
+ }
|
||||
+ }
|
||||
+ if (netManager.getServerCapabilities().hasCapability(StandardCaps.WEBVIEW, 0)) {
|
||||
+ WebViewOverlayController.setPacketSendCallback(this::webViewSendHandler);
|
||||
+ } else {
|
||||
+ WebViewOverlayController.setPacketSendCallback(null);
|
||||
+ }
|
||||
+ WebViewOverlayController.setPacketSendCallback(this::webViewSendHandler);
|
||||
|
||||
> DELETE 3 @ 3 : 4
|
||||
|
||||
@ -477,12 +491,11 @@
|
||||
~ for (int i = 0, l = lst.size(); i < l; ++i) {
|
||||
~ S38PacketPlayerListItem.AddPlayerData s38packetplayerlistitem$addplayerdata = lst.get(i);
|
||||
|
||||
> CHANGE 1 : 6 @ 1 : 2
|
||||
> CHANGE 1 : 5 @ 1 : 2
|
||||
|
||||
~ EaglercraftUUID uuid = s38packetplayerlistitem$addplayerdata.getProfile().getId();
|
||||
~ this.playerInfoMap.remove(uuid);
|
||||
~ this.skinCache.evictSkin(uuid);
|
||||
~ this.capeCache.evictCape(uuid);
|
||||
~ this.textureCache.evictPlayer(uuid);
|
||||
~ ClientUUIDLoadingCache.evict(uuid);
|
||||
|
||||
> DELETE 34 @ 34 : 35
|
||||
@ -573,11 +586,12 @@
|
||||
|
||||
> DELETE 11 @ 11 : 13
|
||||
|
||||
> INSERT 9 : 17 @ 9
|
||||
> INSERT 9 : 18 @ 9
|
||||
|
||||
+ } else {
|
||||
+ } else if (eaglerMessageController instanceof LegacyMessageController) {
|
||||
+ try {
|
||||
+ eaglerMessageController.handlePacket(packetIn.getChannelName(), packetIn.getBufferData());
|
||||
+ ((LegacyMessageController) eaglerMessageController).handlePacket(packetIn.getChannelName(),
|
||||
+ packetIn.getBufferData());
|
||||
+ } catch (IOException e) {
|
||||
+ logger.error("Couldn't read \"{}\" packet as an eaglercraft plugin message!",
|
||||
+ packetIn.getChannelName());
|
||||
|
@ -31,26 +31,24 @@
|
||||
|
||||
~ return true;
|
||||
|
||||
> CHANGE 3 : 5 @ 3 : 4
|
||||
> CHANGE 3 : 4 @ 3 : 4
|
||||
|
||||
~ return Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(this.gameProfile)
|
||||
~ .getSkinModel().profileSkinType;
|
||||
~ return getEaglerSkinModel().profileSkinType;
|
||||
|
||||
> CHANGE 2 : 5 @ 2 : 6
|
||||
|
||||
~ public SkinModel getEaglerSkinModel() {
|
||||
~ return Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(this.gameProfile).getSkinModel();
|
||||
~ return Minecraft.getMinecraft().getNetHandler().getTextureCache().getPlayerSkin(this.gameProfile).getModel();
|
||||
~ }
|
||||
|
||||
> CHANGE 1 : 3 @ 1 : 3
|
||||
|
||||
~ public ResourceLocation getLocationSkin() {
|
||||
~ return Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(this.gameProfile).getResourceLocation();
|
||||
~ return Minecraft.getMinecraft().getNetHandler().getTextureCache().getPlayerSkin(this.gameProfile).getLocation();
|
||||
|
||||
> CHANGE 3 : 5 @ 3 : 8
|
||||
> CHANGE 3 : 4 @ 3 : 8
|
||||
|
||||
~ return Minecraft.getMinecraft().getNetHandler().getCapeCache().getCape(this.gameProfile.getId())
|
||||
~ .getResourceLocation();
|
||||
~ return Minecraft.getMinecraft().getNetHandler().getTextureCache().getPlayerCape(this.gameProfile);
|
||||
|
||||
> DELETE 6 @ 6 : 33
|
||||
|
||||
|
@ -5,13 +5,12 @@
|
||||
# Version: 1.0
|
||||
# Author: lax1dude
|
||||
|
||||
> INSERT 2 : 8 @ 2
|
||||
> INSERT 2 : 7 @ 2
|
||||
|
||||
+ import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerTextureAtlasSprite;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.BlockVertexIDs;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.dynamiclights.DynamicLightsStateManager;
|
||||
+ import net.minecraft.block.Block;
|
||||
|
||||
> DELETE 4 @ 4 : 6
|
||||
@ -25,7 +24,7 @@
|
||||
|
||||
+ BlockPos tmp = new BlockPos(0, 0, 0);
|
||||
+ boolean deferred = DeferredStateManager.isDeferredRenderer();
|
||||
+ boolean isDynamicLights = deferred || DynamicLightsStateManager.isDynamicLightsRender();
|
||||
+ boolean isDynamicLights = deferred;// || DynamicLightsStateManager.isDynamicLightsRender();
|
||||
|
||||
> INSERT 1 : 3 @ 1
|
||||
|
||||
|
@ -5,14 +5,13 @@
|
||||
# Version: 1.0
|
||||
# Author: lax1dude
|
||||
|
||||
> INSERT 4 : 10 @ 4
|
||||
> INSERT 4 : 9 @ 4
|
||||
|
||||
+
|
||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.VertexMarkerState;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.opengl.ext.dynamiclights.DynamicLightsStateManager;
|
||||
|
||||
> DELETE 3 @ 3 : 7
|
||||
|
||||
@ -193,7 +192,7 @@
|
||||
~ private void renderModelAmbientOcclusionQuads(IBlockAccess blockAccessIn, IBlockState blockStateIn,
|
||||
~ BlockPos blockPosIn, WorldRenderer worldRendererIn, List<BakedQuad> listQuadsIn, RenderEnv renderenv) {
|
||||
~ boolean isDeferred = DeferredStateManager.isDeferredRenderer();
|
||||
~ boolean isDynamicLights = isDeferred || DynamicLightsStateManager.isDynamicLightsRender();
|
||||
~ boolean isDynamicLights = isDeferred;// || DynamicLightsStateManager.isDynamicLightsRender();
|
||||
~ float[] quadBounds = renderenv.getQuadBounds();
|
||||
~ BitSet boundsFlags = renderenv.getBoundsFlags();
|
||||
~ BlockModelRenderer.AmbientOcclusionFace aoFaceIn = renderenv.getAoFace();
|
||||
@ -249,7 +248,7 @@
|
||||
|
||||
~ List<BakedQuad> listQuadsIn, RenderEnv renderenv) {
|
||||
~ boolean isDeferred = DeferredStateManager.isDeferredRenderer();
|
||||
~ boolean isDynamicLights = isDeferred || DynamicLightsStateManager.isDynamicLightsRender();
|
||||
~ boolean isDynamicLights = isDeferred;// || DynamicLightsStateManager.isDynamicLightsRender();
|
||||
~ BitSet boundsFlags = renderenv.getBoundsFlags();
|
||||
~ float[] quadBounds = renderenv.getQuadBounds();
|
||||
|
||||
|
@ -832,12 +832,13 @@
|
||||
|
||||
> DELETE 5 @ 5 : 6
|
||||
|
||||
> CHANGE 155 : 159 @ 155 : 156
|
||||
> CHANGE 155 : 160 @ 155 : 156
|
||||
|
||||
~ worldRendererIn.begin(7,
|
||||
~ (DeferredStateManager.isDeferredRenderer() || DynamicLightsStateManager.isDynamicLightsRender())
|
||||
~ ? VertexFormat.BLOCK_SHADERS
|
||||
~ : DefaultVertexFormats.BLOCK);
|
||||
~ (DeferredStateManager
|
||||
~ .isDeferredRenderer() /* || DynamicLightsStateManager.isDynamicLightsRender() */)
|
||||
~ ? VertexFormat.BLOCK_SHADERS
|
||||
~ : DefaultVertexFormats.BLOCK);
|
||||
|
||||
> CHANGE 19 : 20 @ 19 : 20
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
> DELETE 2 @ 2 : 5
|
||||
|
||||
> CHANGE 3 : 11 @ 3 : 4
|
||||
> CHANGE 3 : 10 @ 3 : 4
|
||||
|
||||
~
|
||||
~ import com.google.common.collect.Maps;
|
||||
@ -16,7 +16,6 @@
|
||||
~ import net.lax1dude.eaglercraft.v1_8.opengl.VertexFormat;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.opengl.ext.dynamiclights.DynamicLightsStateManager;
|
||||
|
||||
> DELETE 4 @ 4 : 7
|
||||
|
||||
@ -186,7 +185,7 @@
|
||||
> CHANGE 3 : 7 @ 3 : 4
|
||||
|
||||
~ worldRendererIn.begin(7,
|
||||
~ (DeferredStateManager.isDeferredRenderer() || DynamicLightsStateManager.isDynamicLightsRender())
|
||||
~ (DeferredStateManager.isDeferredRenderer() /* || DynamicLightsStateManager.isDynamicLightsRender() */)
|
||||
~ ? VertexFormat.BLOCK_SHADERS
|
||||
~ : DefaultVertexFormats.BLOCK);
|
||||
|
||||
|
@ -17,11 +17,10 @@
|
||||
|
||||
> DELETE 1 @ 1 : 4
|
||||
|
||||
> CHANGE 28 : 32 @ 28 : 29
|
||||
> CHANGE 28 : 31 @ 28 : 29
|
||||
|
||||
~ worldrenderer.begin(7,
|
||||
~ (DeferredStateManager.isDeferredRenderer()
|
||||
~ || DynamicLightsStateManager.isDynamicLightsRender()) ? VertexFormat.BLOCK_SHADERS
|
||||
~ : DefaultVertexFormats.BLOCK);
|
||||
~ worldrenderer.begin(7, (DeferredStateManager.isDeferredRenderer()
|
||||
~ /* || DynamicLightsStateManager.isDynamicLightsRender() */) ? VertexFormat.BLOCK_SHADERS
|
||||
~ : DefaultVertexFormats.BLOCK);
|
||||
|
||||
> EOF
|
||||
|
@ -21,7 +21,7 @@
|
||||
~ if (parGameProfile != null && parGameProfile.getId() != null) {
|
||||
~ NetHandlerPlayClient netHandler = Minecraft.getMinecraft().getNetHandler();
|
||||
~ if (netHandler != null) {
|
||||
~ resourcelocation = netHandler.getSkinCache().getSkin(parGameProfile).getResourceLocation();
|
||||
~ resourcelocation = netHandler.getTextureCache().getPlayerSkin(parGameProfile).getLocation();
|
||||
|
||||
> DELETE 2 @ 2 : 3
|
||||
|
||||
|
@ -5,14 +5,13 @@
|
||||
# Version: 1.0
|
||||
# Author: lax1dude
|
||||
|
||||
> INSERT 2 : 8 @ 2
|
||||
> INSERT 2 : 7 @ 2
|
||||
|
||||
+ import com.carrotsearch.hppc.IntArrayList;
|
||||
+ import com.carrotsearch.hppc.IntObjectHashMap;
|
||||
+ import com.carrotsearch.hppc.IntObjectMap;
|
||||
+ import com.carrotsearch.hppc.ObjectContainer;
|
||||
+ import com.carrotsearch.hppc.cursors.IntObjectCursor;
|
||||
+ import com.carrotsearch.hppc.cursors.ObjectCursor;
|
||||
+ import com.carrotsearch.hppc.procedures.IntObjectProcedure;
|
||||
|
||||
> CHANGE 2 : 5 @ 2 : 5
|
||||
|
||||
@ -68,30 +67,30 @@
|
||||
|
||||
~ this.activePotionsMap.put(potioneffect.getPotionID(), potioneffect);
|
||||
|
||||
> CHANGE 23 : 24 @ 23 : 24
|
||||
> CHANGE 23 : 26 @ 23 : 31
|
||||
|
||||
~ IntArrayList deadPotionEffects = null;
|
||||
~ if (!this.worldObj.isRemote) {
|
||||
~ this.activePotionsMap.removeAll((integer, potioneffect) -> {
|
||||
~ if (!potioneffect.onUpdate(this)) {
|
||||
|
||||
> CHANGE 1 : 4 @ 1 : 4
|
||||
> INSERT 1 : 4 @ 1
|
||||
|
||||
~ for (IntObjectCursor<PotionEffect> cur : this.activePotionsMap) {
|
||||
~ int integer = cur.key;
|
||||
~ PotionEffect potioneffect = cur.value;
|
||||
+ return true;
|
||||
+ } else if (potioneffect.getDuration() % 600 == 0) {
|
||||
+ this.onChangedPotionEffect(potioneffect, false);
|
||||
|
||||
> CHANGE 2 : 5 @ 2 : 3
|
||||
> CHANGE 1 : 9 @ 1 : 4
|
||||
|
||||
~ if (deadPotionEffects == null)
|
||||
~ deadPotionEffects = new IntArrayList(4);
|
||||
~ deadPotionEffects.add(integer);
|
||||
~ return false;
|
||||
~ });
|
||||
~ } else {
|
||||
~ this.activePotionsMap.forEach((IntObjectProcedure<PotionEffect>) (integer, potioneffect) -> {
|
||||
~ if (potioneffect.onUpdate(this) && potioneffect.getDuration() % 600 == 0) {
|
||||
~ this.onChangedPotionEffect(potioneffect, false);
|
||||
~ }
|
||||
~ });
|
||||
|
||||
> INSERT 7 : 11 @ 7
|
||||
|
||||
+ if (deadPotionEffects != null) {
|
||||
+ this.activePotionsMap.removeAll(deadPotionEffects);
|
||||
+ }
|
||||
+
|
||||
|
||||
> CHANGE 40 : 43 @ 40 : 43
|
||||
> CHANGE 42 : 45 @ 42 : 45
|
||||
|
||||
~ ObjectContainer<PotionEffect> cc = this.activePotionsMap.values();
|
||||
~ int i = PotionHelper.calcPotionLiquidColor(cc);
|
||||
|
@ -14,10 +14,12 @@
|
||||
+ import com.carrotsearch.hppc.cursors.IntCursor;
|
||||
+ import com.carrotsearch.hppc.cursors.LongCursor;
|
||||
|
||||
> CHANGE 2 : 4 @ 2 : 4
|
||||
> CHANGE 2 : 6 @ 2 : 4
|
||||
|
||||
~ import net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.netty.Unpooled;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.server.skins.PlayerTextureData;
|
||||
~
|
||||
|
||||
> DELETE 17 @ 17 : 18
|
||||
|
||||
@ -45,9 +47,10 @@
|
||||
|
||||
~ private long playerLastActiveTime = EagRuntime.steadyTimeMillis();
|
||||
|
||||
> INSERT 5 : 7 @ 5
|
||||
> INSERT 5 : 8 @ 5
|
||||
|
||||
+ public byte[] updateCertificate = null;
|
||||
+ public PlayerTextureData textureData = null;
|
||||
+ public EaglercraftUUID clientBrandUUID = null;
|
||||
|
||||
> CHANGE 87 : 88 @ 87 : 88
|
||||
|
@ -12,11 +12,7 @@
|
||||
+ import com.google.common.collect.Maps;
|
||||
+
|
||||
|
||||
> CHANGE 53 : 54 @ 53 : 54
|
||||
|
||||
~ CHANGE_PAGE("change_page", true), EAGLER_PLUGIN_DOWNLOAD("eagler_plugin_download", true);
|
||||
|
||||
> CHANGE 23 : 26 @ 23 : 25
|
||||
> CHANGE 77 : 80 @ 77 : 79
|
||||
|
||||
~ ClickEvent.Action[] types = values();
|
||||
~ for (int i = 0; i < types.length; ++i) {
|
||||
|
@ -10,10 +10,14 @@
|
||||
+ import com.carrotsearch.hppc.IntShortHashMap;
|
||||
+ import com.carrotsearch.hppc.IntShortMap;
|
||||
|
||||
> CHANGE 3 : 8 @ 3 : 7
|
||||
> CHANGE 3 : 12 @ 3 : 7
|
||||
|
||||
~
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageConstants;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.client.GameProtocolMessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.message.InjectedMessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.message.LegacyMessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.message.MessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.GameMessagePacket;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketUpdateCertEAG;
|
||||
~
|
||||
@ -28,13 +32,18 @@
|
||||
|
||||
> DELETE 25 @ 25 : 29
|
||||
|
||||
> DELETE 35 @ 35 : 36
|
||||
> INSERT 33 : 34 @ 33
|
||||
|
||||
+ import net.minecraft.network.play.server.S3FPacketCustomPayload;
|
||||
|
||||
> DELETE 2 @ 2 : 3
|
||||
|
||||
> DELETE 13 @ 13 : 14
|
||||
|
||||
> INSERT 2 : 4 @ 2
|
||||
> INSERT 2 : 5 @ 2
|
||||
|
||||
+ import net.lax1dude.eaglercraft.v1_8.sp.server.socket.IntegratedServerPlayerNetworkManager;
|
||||
+ import net.lax1dude.eaglercraft.v1_8.sp.server.socket.protocol.ServerMessageHandler;
|
||||
+
|
||||
|
||||
> DELETE 1 @ 1 : 3
|
||||
@ -62,34 +71,42 @@
|
||||
> INSERT 4 : 6 @ 4
|
||||
|
||||
+ private boolean hasDisconnected = false;
|
||||
+ private GameProtocolMessageController eaglerMessageController = null;
|
||||
+ private MessageController eaglerMessageController = null;
|
||||
|
||||
> CHANGE 1 : 3 @ 1 : 2
|
||||
|
||||
~ public NetHandlerPlayServer(MinecraftServer server, IntegratedServerPlayerNetworkManager networkManagerIn,
|
||||
~ EntityPlayerMP playerIn) {
|
||||
~ EntityPlayerMP playerIn, GamePluginMessageProtocol eaglerProtocol) {
|
||||
|
||||
> INSERT 7 : 28 @ 7
|
||||
> INSERT 5 : 15 @ 5
|
||||
|
||||
+ public GameProtocolMessageController getEaglerMessageController() {
|
||||
+ ServerMessageHandler handler = ServerMessageHandler.createServerHandler(eaglerProtocol.ver, this);
|
||||
+ if (eaglerProtocol.ver >= 5) {
|
||||
+ this.eaglerMessageController = new InjectedMessageController(eaglerProtocol, handler,
|
||||
+ GamePluginMessageConstants.SERVER_TO_CLIENT, networkManagerIn::injectRawFrame);
|
||||
+ networkManagerIn.setInjectedMessageController((InjectedMessageController) eaglerMessageController);
|
||||
+ } else {
|
||||
+ this.eaglerMessageController = new LegacyMessageController(eaglerProtocol, handler,
|
||||
+ GamePluginMessageConstants.SERVER_TO_CLIENT,
|
||||
+ (ch, msg) -> sendPacket(new S3FPacketCustomPayload(ch, msg)));
|
||||
+ }
|
||||
|
||||
> INSERT 2 : 18 @ 2
|
||||
|
||||
+ public MessageController getEaglerMessageController() {
|
||||
+ return eaglerMessageController;
|
||||
+ }
|
||||
+
|
||||
+ public void setEaglerMessageController(GameProtocolMessageController eaglerMessageController) {
|
||||
+ public void setEaglerMessageController(MessageController eaglerMessageController) {
|
||||
+ this.eaglerMessageController = eaglerMessageController;
|
||||
+ }
|
||||
+
|
||||
+ public GamePluginMessageProtocol getEaglerMessageProtocol() {
|
||||
+ return eaglerMessageController != null ? eaglerMessageController.protocol : null;
|
||||
+ return eaglerMessageController != null ? eaglerMessageController.getProtocol() : null;
|
||||
+ }
|
||||
+
|
||||
+ public void sendEaglerMessage(GameMessagePacket packet) {
|
||||
+ try {
|
||||
+ eaglerMessageController.sendPacket(packet);
|
||||
+ } catch (IOException e) {
|
||||
+ logger.error("Failed to send eaglercraft plugin message packet: " + packet);
|
||||
+ logger.error(e);
|
||||
+ }
|
||||
+ eaglerMessageController.sendPacket(packet);
|
||||
+ }
|
||||
+
|
||||
|
||||
@ -268,10 +285,10 @@
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ } else {
|
||||
+ } else if (eaglerMessageController instanceof LegacyMessageController) {
|
||||
+ try {
|
||||
+ eaglerMessageController.handlePacket(c17packetcustompayload.getChannelName(),
|
||||
+ c17packetcustompayload.getBufferData());
|
||||
+ ((LegacyMessageController) eaglerMessageController)
|
||||
+ .handlePacket(c17packetcustompayload.getChannelName(), c17packetcustompayload.getBufferData());
|
||||
+ } catch (IOException e) {
|
||||
+ logger.error("Couldn't read \"{}\" packet as an eaglercraft plugin message!",
|
||||
+ c17packetcustompayload.getChannelName());
|
||||
|
@ -138,6 +138,15 @@
|
||||
|
||||
> DELETE 20 @ 20 : 36
|
||||
|
||||
> DELETE 88 @ 88 : 107
|
||||
> CHANGE 88 : 94 @ 88 : 90
|
||||
|
||||
~ public byte[] toBytes() {
|
||||
~ int readerIndex = buf.readerIndex();
|
||||
~ int writerIndex = buf.writerIndex();
|
||||
~ byte[] bytes = new byte[writerIndex - readerIndex];
|
||||
~ buf.getBytes(readerIndex, bytes);
|
||||
~ return bytes;
|
||||
|
||||
> DELETE 2 @ 2 : 17
|
||||
|
||||
> EOF
|
||||
|
@ -30,14 +30,13 @@
|
||||
|
||||
+ import net.minecraft.util.ChatComponentText;
|
||||
|
||||
> CHANGE 12 : 22 @ 12 : 14
|
||||
> CHANGE 12 : 21 @ 12 : 14
|
||||
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageConstants;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.client.GameProtocolMessageController;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.pkt.server.SPacketUpdateCertEAG;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.server.WorldsDB;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.server.skins.PlayerTextureData;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.server.socket.IntegratedServerPlayerNetworkManager;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.server.voice.IntegratedVoiceService;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.log4j.LogManager;
|
||||
@ -69,20 +68,18 @@
|
||||
> CHANGE 2 : 6 @ 2 : 8
|
||||
|
||||
~ public void initializeConnectionToPlayer(IntegratedServerPlayerNetworkManager netManager, EntityPlayerMP playerIn,
|
||||
~ int protocolVersion, EaglercraftUUID clientBrandUUID) {
|
||||
~ GamePluginMessageProtocol protocolVersion, PlayerTextureData textureData, EaglercraftUUID clientBrandUUID) {
|
||||
~ playerIn.textureData = textureData;
|
||||
~ playerIn.clientBrandUUID = clientBrandUUID;
|
||||
~ GameProfile gameprofile1 = playerIn.getGameProfile();
|
||||
|
||||
> CHANGE 3 : 4 @ 3 : 7
|
||||
|
||||
~ String s1 = "channel:" + netManager.playerChannel;
|
||||
|
||||
> INSERT 8 : 12 @ 8
|
||||
> CHANGE 7 : 9 @ 7 : 8
|
||||
|
||||
+ nethandlerplayserver.setEaglerMessageController(new GameProtocolMessageController(
|
||||
+ GamePluginMessageProtocol.getByVersion(protocolVersion), GamePluginMessageConstants.SERVER_TO_CLIENT,
|
||||
+ GameProtocolMessageController.createServerHandler(protocolVersion, nethandlerplayserver),
|
||||
+ (ch, msg) -> nethandlerplayserver.sendPacket(new S3FPacketCustomPayload(ch, msg))));
|
||||
~ NetHandlerPlayServer nethandlerplayserver = new NetHandlerPlayServer(this.mcServer, netManager, playerIn,
|
||||
~ protocolVersion);
|
||||
|
||||
> DELETE 4 @ 4 : 6
|
||||
|
||||
@ -142,10 +139,8 @@
|
||||
|
||||
~ this.playerStatFiles.remove(entityplayermp.getName());
|
||||
|
||||
> INSERT 2 : 9 @ 2
|
||||
> INSERT 2 : 7 @ 2
|
||||
|
||||
+ ((EaglerMinecraftServer) mcServer).getSkinService().unregisterPlayer(uuid);
|
||||
+ ((EaglerMinecraftServer) mcServer).getCapeService().unregisterPlayer(uuid);
|
||||
+ IntegratedVoiceService vcs = ((EaglerMinecraftServer) mcServer).getVoiceService();
|
||||
+ if (vcs != null) {
|
||||
+ vcs.handlePlayerLoggedOut(playerIn);
|
||||
|
@ -5,14 +5,16 @@
|
||||
# Version: 1.0
|
||||
# Author: lax1dude
|
||||
|
||||
> CHANGE 3 : 9 @ 3 : 15
|
||||
> CHANGE 3 : 11 @ 3 : 15
|
||||
|
||||
~ import net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.socket.protocol.GamePluginMessageProtocol;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.ClientUUIDLoadingCache;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.EaglerInputStream;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer;
|
||||
~ import net.lax1dude.eaglercraft.v1_8.sp.server.skins.IntegratedTexturePackets;
|
||||
|
||||
> CHANGE 1 : 2 @ 1 : 2
|
||||
|
||||
@ -62,19 +64,14 @@
|
||||
|
||||
> DELETE 2 @ 2 : 3
|
||||
|
||||
> CHANGE 11 : 23 @ 11 : 12
|
||||
> CHANGE 11 : 18 @ 11 : 12
|
||||
|
||||
~ this.field_181025_l, this.selectedProtocol, this.clientBrandUUID);
|
||||
~ ((EaglerMinecraftServer) field_181025_l.mcServer).getSkinService()
|
||||
~ .processLoginPacket(this.loginSkinPacket, field_181025_l, 3); // singleplayer always sends V3
|
||||
~ // skin in handshake
|
||||
~ if (this.loginCapePacket != null) {
|
||||
~ ((EaglerMinecraftServer) field_181025_l.mcServer).getCapeService()
|
||||
~ .processLoginPacket(this.loginCapePacket, field_181025_l);
|
||||
~ }
|
||||
~ this.field_181025_l, GamePluginMessageProtocol.getByVersion(this.selectedProtocol),
|
||||
~ IntegratedTexturePackets.handleTextureData(this.loginSkinPacket, this.loginCapePacket),
|
||||
~ this.clientBrandUUID);
|
||||
~ IntegratedVoiceService svc = ((EaglerMinecraftServer) field_181025_l.mcServer).getVoiceService();
|
||||
~ if (svc != null) {
|
||||
~ svc.handlePlayerLoggedIn(entityplayermp);
|
||||
~ svc.handlePlayerLoggedIn(this.field_181025_l);
|
||||
~ }
|
||||
|
||||
> CHANGE 23 : 24 @ 23 : 29
|
||||
@ -86,18 +83,13 @@
|
||||
~ this.networkManager.sendPacket(new S02PacketLoginSuccess(this.loginGameProfile, this.selectedProtocol));
|
||||
~ this.networkManager.setConnectionState(EnumConnectionState.PLAY);
|
||||
|
||||
> CHANGE 6 : 20 @ 6 : 8
|
||||
> CHANGE 6 : 15 @ 6 : 8
|
||||
|
||||
~ entityplayermp = this.server.getConfigurationManager().createPlayerForUser(this.loginGameProfile);
|
||||
~ this.server.getConfigurationManager().initializeConnectionToPlayer(this.networkManager, entityplayermp,
|
||||
~ this.selectedProtocol, this.clientBrandUUID);
|
||||
~ ((EaglerMinecraftServer) entityplayermp.mcServer).getSkinService()
|
||||
~ .processLoginPacket(this.loginSkinPacket, entityplayermp, 3); // singleplayer always sends V3
|
||||
~ // skin in handshake
|
||||
~ if (this.loginCapePacket != null) {
|
||||
~ ((EaglerMinecraftServer) entityplayermp.mcServer).getCapeService()
|
||||
~ .processLoginPacket(this.loginCapePacket, entityplayermp);
|
||||
~ }
|
||||
~ GamePluginMessageProtocol.getByVersion(this.selectedProtocol),
|
||||
~ IntegratedTexturePackets.handleTextureData(this.loginSkinPacket, this.loginCapePacket),
|
||||
~ this.clientBrandUUID);
|
||||
~ IntegratedVoiceService svc = ((EaglerMinecraftServer) entityplayermp.mcServer).getVoiceService();
|
||||
~ if (svc != null) {
|
||||
~ svc.handlePlayerLoggedIn(entityplayermp);
|
||||
@ -117,7 +109,7 @@
|
||||
~ int protocolCount = dis.readUnsignedShort();
|
||||
~ for (int i = 0; i < protocolCount; ++i) {
|
||||
~ int p = dis.readUnsignedShort();
|
||||
~ if ((p == 3 || p == 4) && p > maxSupported) {
|
||||
~ if ((p == 3 || p == 4 || p == 5) && p > maxSupported) {
|
||||
~ maxSupported = p;
|
||||
~ }
|
||||
~ }
|
||||
|
@ -38,14 +38,13 @@
|
||||
~ private StringTranslate() {
|
||||
~ }
|
||||
|
||||
> CHANGE 1 : 25 @ 1 : 9
|
||||
> CHANGE 1 : 24 @ 1 : 9
|
||||
|
||||
~ public static void initClient() {
|
||||
~ try (InputStream inputstream = EagRuntime.getRequiredResourceStream("/assets/minecraft/lang/en_US.lang")) {
|
||||
~ initServer(IOUtils.readLines(inputstream, StandardCharsets.UTF_8));
|
||||
~ fallbackInstance = new StringTranslate();
|
||||
~ fallbackInstance.replaceWith(instance.languageList);
|
||||
~ SingleplayerServerController.updateLocale(dump());
|
||||
~ } catch (IOException e) {
|
||||
~ EagRuntime.debugPrintStackTrace(e);
|
||||
~ }
|
||||
@ -75,9 +74,10 @@
|
||||
|
||||
~ public static void replaceWith(Map<String, String> parMap) {
|
||||
|
||||
> CHANGE 2 : 3 @ 2 : 3
|
||||
> CHANGE 2 : 4 @ 2 : 3
|
||||
|
||||
~ instance.lastUpdateTimeInMilliseconds = EagRuntime.steadyTimeMillis();
|
||||
~ SingleplayerServerController.updateLocale(dump());
|
||||
|
||||
> CHANGE 2 : 3 @ 2 : 3
|
||||
|
||||
|
@ -37,15 +37,13 @@
|
||||
|
||||
~ byte b0 = (byte) spawnHostileMobs.getMinecraftServer().getConfigurationManager().getViewDistance();
|
||||
|
||||
> CHANGE 4 : 9 @ 4 : 6
|
||||
> CHANGE 4 : 7 @ 4 : 5
|
||||
|
||||
~ int cx = l + j;
|
||||
~ int cz = i1 + k;
|
||||
~ long chunkcoordintpair = ChunkCoordIntPair.chunkXZ2Int(cx, cz);
|
||||
~ if (!this.eligibleChunksForSpawning.contains(chunkcoordintpair)
|
||||
~ && spawnHostileMobs.theChunkProviderServer.chunkExists(cx, cz)) {
|
||||
|
||||
> CHANGE 13 : 16 @ 13 : 14
|
||||
> CHANGE 14 : 17 @ 14 : 15
|
||||
|
||||
~ EnumCreatureType[] types = EnumCreatureType._VALUES;
|
||||
~ for (int m = 0; m < types.length; ++m) {
|
||||
|
@ -16,7 +16,7 @@
|
||||
~ eaglercraft.resourcePack.load.loading=Loading resource pack...
|
||||
~ eaglercraft.resourcePack.load.deleting=Deleting resource pack...
|
||||
|
||||
> INSERT 1 : 246 @ 1
|
||||
> INSERT 1 : 247 @ 1
|
||||
|
||||
+ eaglercraft.gui.exitKey=Use '%s' to close this screen!
|
||||
+ eaglercraft.gui.exitKeyRetarded=Use Backtick (`) to close this screen!
|
||||
@ -201,8 +201,9 @@
|
||||
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.label=God Rays
|
||||
+
|
||||
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.0=Render god rays (light shafts) for sunlight and moonlight shadows
|
||||
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.2=ON: render god rays (slower)
|
||||
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.3=OFF: disable god rays (faster)
|
||||
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.2=This shader tends to look unpleasent if the render distance is greater than the shadow map size
|
||||
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.4=ON: render god rays (slower)
|
||||
+ eaglercraft.shaders.gui.option.LIGHT_SHAFTS.desc.5=OFF: disable god rays (faster)
|
||||
+
|
||||
+ eaglercraft.shaders.gui.option.SCREEN_SPACE_REFLECTIONS.label=Raytracing
|
||||
+
|
||||
@ -264,7 +265,7 @@
|
||||
+ eaglercraft.command.clientStub=This command is client side!
|
||||
+
|
||||
|
||||
> INSERT 163 : 574 @ 163
|
||||
> INSERT 163 : 578 @ 163
|
||||
|
||||
+ eaglercraft.singleplayer.busy.killTask=Cancel Task
|
||||
+ eaglercraft.singleplayer.busy.cancelWarning=Are you sure?
|
||||
@ -594,12 +595,16 @@
|
||||
+ eaglercraft.fallbackWebViewScreen.openButton=Open
|
||||
+ eaglercraft.fallbackWebViewScreen.exitButton=Exit
|
||||
+
|
||||
+ eaglercraft.webviewPhishingWaring.title=WARNING!!!
|
||||
+ eaglercraft.webviewPhishingWaring.text0=If you see a login page, think before you enter a password
|
||||
+ eaglercraft.webviewPhishingWaring.text1=Passwords can be stolen by the owner of this server or website
|
||||
+ eaglercraft.webviewPhishingWaring.text2=Do not log in to accounts you don't want hackers to steal
|
||||
+ eaglercraft.webviewPhishingWaring.dontShowAgain=Do not show this message again
|
||||
+ eaglercraft.webviewPhishingWaring.continue=Continue
|
||||
+ eaglercraft.webviewPhishingWarning.title=WARNING!!!
|
||||
+ eaglercraft.webviewPhishingWarning.text0=If you see a login page, think before you enter a password
|
||||
+ eaglercraft.webviewPhishingWarning.text1=Passwords can be stolen by the owner of this server or website
|
||||
+ eaglercraft.webviewPhishingWarning.text2=Do not log in to accounts you don't want hackers to steal
|
||||
+ eaglercraft.webviewPhishingWarning.dontShowAgain=Do not show this message again
|
||||
+ eaglercraft.webviewPhishingWarning.continue=Continue
|
||||
+
|
||||
+ eaglercraft.webviewDisplayWarning.title=WebView Warning
|
||||
+ eaglercraft.webviewDisplayWarning.text0=This server is attempting to display HTML content
|
||||
+ eaglercraft.webviewDisplayWarning.text1=Would you like to continue?
|
||||
+
|
||||
+ eaglercraft.notifications.title=Notifications
|
||||
+ eaglercraft.notifications.priority=Priority: %s
|
||||
|
@ -40,6 +40,7 @@ class OpenGLObjects {
|
||||
static class VertexArrayGL implements IVertexArrayGL {
|
||||
|
||||
final int ptr;
|
||||
int enabled;
|
||||
|
||||
VertexArrayGL(int ptr) {
|
||||
this.ptr = ptr;
|
||||
@ -53,7 +54,22 @@ class OpenGLObjects {
|
||||
public void free() {
|
||||
PlatformOpenGL._wglDeleteVertexArrays(this);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getBits() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBit(int bit) {
|
||||
enabled |= bit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unsetBit(int bit) {
|
||||
enabled &= ~bit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TextureGL implements ITextureGL {
|
||||
|
@ -580,7 +580,7 @@ public class PlatformInput {
|
||||
}
|
||||
|
||||
public static boolean contextLost() {
|
||||
return glfwGetWindowAttrib(win, GLFW_ICONIFIED) == GLFW_TRUE;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void setFunctionKeyModifier(int key) {
|
||||
|
@ -101,7 +101,11 @@ public class PlatformRuntime {
|
||||
IEaglerFilesystem resourcePackFilesystem = Filesystem.getHandleFor(getClientConfigAdapter().getResourcePacksDB());
|
||||
VFile2.setPrimaryFilesystem(resourcePackFilesystem);
|
||||
EaglerFolderResourcePack.setSupported(true);
|
||||
|
||||
|
||||
if (glfwPlatformSupported(GLFW_PLATFORM_X11)) {
|
||||
glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_X11);
|
||||
}
|
||||
|
||||
if(requestedANGLEPlatform != EnumPlatformANGLE.DEFAULT) {
|
||||
logger.info("Setting ANGLE Platform: {}", requestedANGLEPlatform.name);
|
||||
glfwInitHint(GLFW_ANGLE_PLATFORM_TYPE, requestedANGLEPlatform.eglEnum);
|
||||
|
@ -65,6 +65,14 @@ public class PlatformVoiceClient {
|
||||
|
||||
}
|
||||
|
||||
public static void makePeerGlobal(EaglercraftUUID peerId) {
|
||||
|
||||
}
|
||||
|
||||
public static void makePeerProximity(EaglercraftUUID peerId) {
|
||||
|
||||
}
|
||||
|
||||
public static void tickVoiceClient() {
|
||||
|
||||
}
|
||||
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractByteCollection implements ByteCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final ByteLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final ByteLookupContainer c) {
|
||||
// We know c holds sub-types of byte and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(BytePredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final BytePredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public byte[] toArray() {
|
||||
|
||||
byte[] array = (new byte[size()]);
|
||||
int i = 0;
|
||||
for (ByteCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCursor;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractCharCollection implements CharCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final CharLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final CharLookupContainer c) {
|
||||
// We know c holds sub-types of char and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(CharPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final CharPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public char[] toArray() {
|
||||
|
||||
char[] array = (new char[size()]);
|
||||
int i = 0;
|
||||
for (CharCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.DoubleCursor;
|
||||
import com.carrotsearch.hppc.predicates.DoublePredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractDoubleCollection implements DoubleCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final DoubleLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final DoubleLookupContainer c) {
|
||||
// We know c holds sub-types of double and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(DoublePredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final DoublePredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public double[] toArray() {
|
||||
|
||||
double[] array = (new double[size()]);
|
||||
int i = 0;
|
||||
for (DoubleCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.FloatCursor;
|
||||
import com.carrotsearch.hppc.predicates.FloatPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractFloatCollection implements FloatCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final FloatLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final FloatLookupContainer c) {
|
||||
// We know c holds sub-types of float and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(FloatPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final FloatPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public float[] toArray() {
|
||||
|
||||
float[] array = (new float[size()]);
|
||||
int i = 0;
|
||||
for (FloatCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntCursor;
|
||||
import com.carrotsearch.hppc.predicates.IntPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractIntCollection implements IntCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final IntLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final IntLookupContainer c) {
|
||||
// We know c holds sub-types of int and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(IntPredicate)} and negates the predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final IntPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public int[] toArray() {
|
||||
|
||||
int[] array = (new int[size()]);
|
||||
int i = 0;
|
||||
for (IntCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/** Simplifies the implementation of iterators a bit. Modeled loosely after Google Guava's API. */
|
||||
public abstract class AbstractIterator<E> implements Iterator<E> {
|
||||
private static final int NOT_CACHED = 0;
|
||||
private static final int CACHED = 1;
|
||||
private static final int AT_END = 2;
|
||||
|
||||
/** Current iterator state. */
|
||||
private int state = NOT_CACHED;
|
||||
|
||||
/** The next element to be returned from {@link #next()} if fetched. */
|
||||
private E nextElement;
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
if (state == NOT_CACHED) {
|
||||
state = CACHED;
|
||||
nextElement = fetch();
|
||||
}
|
||||
return state == CACHED;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public E next() {
|
||||
if (!hasNext()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
state = NOT_CACHED;
|
||||
return nextElement;
|
||||
}
|
||||
|
||||
/** Default implementation throws {@link UnsupportedOperationException}. */
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch next element. The implementation must return {@link #done()} when all elements have been
|
||||
* fetched.
|
||||
*
|
||||
* @return Returns the next value for the iterator or chain-calls {@link #done()}.
|
||||
*/
|
||||
protected abstract E fetch();
|
||||
|
||||
/**
|
||||
* Call when done.
|
||||
*
|
||||
* @return Returns a unique sentinel value to indicate end-of-iteration.
|
||||
*/
|
||||
protected final E done() {
|
||||
state = AT_END;
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.LongCursor;
|
||||
import com.carrotsearch.hppc.predicates.LongPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractLongCollection implements LongCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final LongLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final LongLookupContainer c) {
|
||||
// We know c holds sub-types of long and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(LongPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final LongPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public long[] toArray() {
|
||||
|
||||
long[] array = (new long[size()]);
|
||||
int i = 0;
|
||||
for (LongCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ObjectCursor;
|
||||
import com.carrotsearch.hppc.predicates.ObjectPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@SuppressWarnings("unchecked")
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractObjectCollection<KType> implements ObjectCollection<KType> {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final ObjectLookupContainer<? super KType> c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final ObjectLookupContainer<? super KType> c) {
|
||||
// We know c holds sub-types of Object and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(ObjectPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final ObjectPredicate<? super KType> predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
|
||||
KType[] array = ((KType[]) new Object[size()]);
|
||||
int i = 0;
|
||||
for (ObjectCursor<KType> c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
public <T> T[] toArray(Class<T> componentClass) {
|
||||
final int size = size();
|
||||
final T[] array = (T[]) java.lang.reflect.Array.newInstance(componentClass, size);
|
||||
int i = 0;
|
||||
for (ObjectCursor<KType> c : this) {
|
||||
array[i++] = (T) c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
|
||||
protected boolean equals(Object v1, Object v2) {
|
||||
return (v1 == v2) || (v1 != null && v1.equals(v2));
|
||||
}
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ShortCursor;
|
||||
import com.carrotsearch.hppc.predicates.ShortPredicate;
|
||||
import java.util.Arrays;
|
||||
|
||||
/** Common superclass for collections. */
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "AbstractKTypeCollection.java")
|
||||
abstract class AbstractShortCollection implements ShortCollection {
|
||||
/** Default implementation uses a predicate for removal. */
|
||||
@Override
|
||||
public int removeAll(final ShortLookupContainer c) {
|
||||
return this.removeAll(c::contains);
|
||||
}
|
||||
|
||||
/** Default implementation uses a predicate for retaining. */
|
||||
@Override
|
||||
public int retainAll(final ShortLookupContainer c) {
|
||||
// We know c holds sub-types of short and we're not modifying c, so go unchecked.
|
||||
return this.removeAll(k -> !c.contains(k));
|
||||
}
|
||||
|
||||
/**
|
||||
* Default implementation redirects to {@link #removeAll(ShortPredicate)} and negates the
|
||||
* predicate.
|
||||
*/
|
||||
@Override
|
||||
public int retainAll(final ShortPredicate predicate) {
|
||||
return removeAll(value -> !predicate.apply(value));
|
||||
}
|
||||
|
||||
/** Default implementation of copying to an array. */
|
||||
@Override
|
||||
public short[] toArray() {
|
||||
|
||||
short[] array = (new short[size()]);
|
||||
int i = 0;
|
||||
for (ShortCursor c : this) {
|
||||
array[i++] = c.value;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
/** Convert the contents of this container to a human-friendly string. */
|
||||
@Override
|
||||
public String toString() {
|
||||
return Arrays.toString(this.toArray());
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Anything that could be accounted for memory usage
|
||||
*
|
||||
* <p>Partly forked from Lucene tag releases/lucene-solr/8.5.1
|
||||
*/
|
||||
public interface Accountable {
|
||||
/**
|
||||
* Allocated memory estimation
|
||||
*
|
||||
* @return Ram allocated in bytes
|
||||
*/
|
||||
long ramBytesAllocated();
|
||||
|
||||
/**
|
||||
* Bytes that is actually been used
|
||||
*
|
||||
* @return Ram used in bytes
|
||||
*/
|
||||
long ramBytesUsed();
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/** Resizing (growth) strategy for array-backed buffers. */
|
||||
public interface ArraySizingStrategy extends Accountable {
|
||||
/**
|
||||
* @param currentBufferLength Current size of the array (buffer). This number should comply with
|
||||
* the strategy's policies (it is a result of initial rounding or further growCalls). It can
|
||||
* also be zero, indicating the growth from an empty buffer.
|
||||
* @param elementsCount Number of elements stored in the buffer.
|
||||
* @param expectedAdditions Expected number of additions (resize hint).
|
||||
* @return Must return a new size at least as big as to hold <code>
|
||||
* elementsCount + expectedAdditions</code>.
|
||||
* @throws BufferAllocationException If the sizing strategy cannot grow the buffer (for example
|
||||
* due to constraints or memory limits).
|
||||
*/
|
||||
int grow(int currentBufferLength, int elementsCount, int expectedAdditions)
|
||||
throws BufferAllocationException;
|
||||
}
|
@ -1,120 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Bit mixing utilities. The purpose of these methods is to evenly distribute key space over int32
|
||||
* range.
|
||||
*/
|
||||
public final class BitMixer {
|
||||
|
||||
// Don't bother mixing very small key domains much.
|
||||
public static int mix(byte key) {
|
||||
return key * PHI_C32;
|
||||
}
|
||||
|
||||
public static int mix(short key) {
|
||||
return mixPhi(key);
|
||||
}
|
||||
|
||||
public static int mix(char key) {
|
||||
return mixPhi(key);
|
||||
}
|
||||
|
||||
// Better mix for larger key domains.
|
||||
public static int mix(int key) {
|
||||
return mix32(key);
|
||||
}
|
||||
|
||||
public static int mix(float key) {
|
||||
return mix32(Float.floatToIntBits(key));
|
||||
}
|
||||
|
||||
public static int mix(double key) {
|
||||
return (int) mix64(Double.doubleToLongBits(key));
|
||||
}
|
||||
|
||||
public static int mix(long key) {
|
||||
return (int) mix64(key);
|
||||
}
|
||||
|
||||
public static int mix(Object key) {
|
||||
return key == null ? 0 : mix32(key.hashCode());
|
||||
}
|
||||
|
||||
/** MH3's plain finalization step. */
|
||||
public static int mix32(int k) {
|
||||
k = (k ^ (k >>> 16)) * 0x85ebca6b;
|
||||
k = (k ^ (k >>> 13)) * 0xc2b2ae35;
|
||||
return k ^ (k >>> 16);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes David Stafford variant 9 of 64bit mix function (MH3 finalization step, with different
|
||||
* shifts and constants).
|
||||
*
|
||||
* <p>Variant 9 is picked because it contains two 32-bit shifts which could be possibly optimized
|
||||
* into better machine code.
|
||||
*
|
||||
* @see "http://zimbry.blogspot.com/2011/09/better-bit-mixing-improving-on.html"
|
||||
*/
|
||||
public static long mix64(long z) {
|
||||
z = (z ^ (z >>> 32)) * 0x4cd6944c5cc20b6dL;
|
||||
z = (z ^ (z >>> 29)) * 0xfc12c5b19d3259e9L;
|
||||
return z ^ (z >>> 32);
|
||||
}
|
||||
|
||||
/*
|
||||
* Golden ratio bit mixers.
|
||||
*/
|
||||
|
||||
private static final int PHI_C32 = 0x9e3779b9;
|
||||
private static final long PHI_C64 = 0x9e3779b97f4a7c15L;
|
||||
|
||||
public static int mixPhi(byte k) {
|
||||
final int h = k * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(char k) {
|
||||
final int h = k * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(short k) {
|
||||
final int h = k * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(int k) {
|
||||
final int h = k * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(float k) {
|
||||
final int h = Float.floatToIntBits(k) * PHI_C32;
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
|
||||
public static int mixPhi(double k) {
|
||||
final long h = Double.doubleToLongBits(k) * PHI_C64;
|
||||
return (int) (h ^ (h >>> 32));
|
||||
}
|
||||
|
||||
public static int mixPhi(long k) {
|
||||
final long h = k * PHI_C64;
|
||||
return (int) (h ^ (h >>> 32));
|
||||
}
|
||||
|
||||
public static int mixPhi(Object k) {
|
||||
final int h = (k == null ? 0 : k.hashCode() * PHI_C32);
|
||||
return h ^ (h >>> 16);
|
||||
}
|
||||
}
|
@ -1,952 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.IntCursor;
|
||||
import com.carrotsearch.hppc.cursors.LongCursor;
|
||||
import com.carrotsearch.hppc.predicates.IntPredicate;
|
||||
import com.carrotsearch.hppc.predicates.LongPredicate;
|
||||
import com.carrotsearch.hppc.procedures.IntProcedure;
|
||||
import com.carrotsearch.hppc.procedures.LongProcedure;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* An "open" BitSet implementation that allows direct access to the array of words storing the bits.
|
||||
*
|
||||
* <p>Unlike {@link java.util.BitSet}, the fact that bits are packed into an array of longs is part
|
||||
* of the interface. This allows efficient implementation of other algorithms by someone other than
|
||||
* the author. It also allows one to efficiently implement alternate serialization or interchange
|
||||
* formats.
|
||||
*
|
||||
* <p>The index range for a bitset can easily exceed positive <code>int</code> range in Java
|
||||
* (0x7fffffff), so many methods in this class accept or return a <code>long</code>. There are
|
||||
* adapter methods that return views compatible with {@link LongLookupContainer} and {@link
|
||||
* IntLookupContainer} interfaces.
|
||||
*
|
||||
* @see #asIntLookupContainer()
|
||||
* @see #asLongLookupContainer()
|
||||
*/
|
||||
public class BitSet implements Cloneable {
|
||||
/** The initial default number of bits. */
|
||||
private static final long DEFAULT_NUM_BITS = 64;
|
||||
|
||||
/** Internal representation of bits in this bit set. */
|
||||
public long[] bits;
|
||||
|
||||
/** The number of words (longs) used in the {@link #bits} array. */
|
||||
public int wlen;
|
||||
|
||||
/** Constructs a bit set with the default capacity. */
|
||||
public BitSet() {
|
||||
this(DEFAULT_NUM_BITS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an BitSet large enough to hold numBits.
|
||||
*
|
||||
* @param numBits Number of bits
|
||||
*/
|
||||
public BitSet(long numBits) {
|
||||
bits = new long[bits2words(numBits)];
|
||||
wlen = bits.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an BitSet from an existing long[].
|
||||
*
|
||||
* <p>The first 64 bits are in long[0], with bit index 0 at the least significant bit, and bit
|
||||
* index 63 at the most significant. Given a bit index, the word containing it is long[index/64],
|
||||
* and it is at bit number index%64 within that word.
|
||||
*
|
||||
* <p>numWords are the number of elements in the array that contain set bits (non-zero longs).
|
||||
* numWords should be <= bits.length, and any existing words in the array at position >=
|
||||
* numWords should be zero.
|
||||
*
|
||||
* @param bits underlying bits buffer
|
||||
* @param numWords the number of elements in the array that contain set bits
|
||||
*/
|
||||
public BitSet(long[] bits, int numWords) {
|
||||
this.bits = bits;
|
||||
this.wlen = numWords;
|
||||
}
|
||||
|
||||
/**
|
||||
* Static constructor-like method similar to other (generic) collections.
|
||||
*
|
||||
* @return New instance.
|
||||
*/
|
||||
public static BitSet newInstance() {
|
||||
return new BitSet();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns an iterator over all set bits of this bitset. The iterator should be faster
|
||||
* than using a loop around {@link #nextSetBit(int)}.
|
||||
*/
|
||||
public BitSetIterator iterator() {
|
||||
return new BitSetIterator(bits, wlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the current capacity in bits (1 greater than the index of the last bit).
|
||||
*/
|
||||
public long capacity() {
|
||||
return bits.length << 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #cardinality()
|
||||
* @see java.util.BitSet#size()
|
||||
* @return Returns the current capacity of this set. Included for compatibility. This is
|
||||
* <b>not</b> equal to {@link #cardinality}.
|
||||
*/
|
||||
public long size() {
|
||||
return capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.BitSet#length()
|
||||
* @return Returns the "logical size" of this {@code BitSet}: the index of the highest set bit in
|
||||
* the {@code BitSet} plus one.
|
||||
*/
|
||||
public long length() {
|
||||
trimTrailingZeros();
|
||||
if (wlen == 0) return 0;
|
||||
return (((long) wlen - 1) << 6) + (64 - Long.numberOfLeadingZeros(bits[wlen - 1]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns true if there are no set bits
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
return cardinality() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index The index.
|
||||
* @return Returns true or false for the specified bit index.
|
||||
*/
|
||||
public boolean get(int index) {
|
||||
int i = index >> 6; // div 64
|
||||
// signed shift will keep a negative index and force an
|
||||
// array-index-out-of-bounds-exception, removing the need for an explicit check.
|
||||
if (i >= bits.length) return false;
|
||||
|
||||
int bit = index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
return (bits[i] & bitmask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index The index.
|
||||
* @return Returns true or false for the specified bit index.
|
||||
*/
|
||||
public boolean get(long index) {
|
||||
int i = (int) (index >> 6); // div 64
|
||||
if (i >= bits.length) return false;
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
return (bits[i] & bitmask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a bit, expanding the set size if necessary.
|
||||
*
|
||||
* @param index the index to set
|
||||
*/
|
||||
public void set(long index) {
|
||||
int wordNum = expandingWordNum(index);
|
||||
int bit = (int) index & 0x3f;
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] |= bitmask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a range of bits, expanding the set size if necessary
|
||||
*
|
||||
* @param startIndex lower index
|
||||
* @param endIndex one-past the last bit to set
|
||||
*/
|
||||
public void set(long startIndex, long endIndex) {
|
||||
if (endIndex <= startIndex) return;
|
||||
|
||||
int startWord = (int) (startIndex >> 6);
|
||||
|
||||
// since endIndex is one past the end, this is index of the last
|
||||
// word to be changed.
|
||||
int endWord = expandingWordNum(endIndex - 1);
|
||||
|
||||
long startmask = -1L << startIndex;
|
||||
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex
|
||||
// due to wrap
|
||||
|
||||
if (startWord == endWord) {
|
||||
bits[startWord] |= (startmask & endmask);
|
||||
return;
|
||||
}
|
||||
|
||||
bits[startWord] |= startmask;
|
||||
Arrays.fill(bits, startWord + 1, endWord, -1L);
|
||||
bits[endWord] |= endmask;
|
||||
}
|
||||
|
||||
protected int expandingWordNum(long index) {
|
||||
int wordNum = (int) (index >> 6);
|
||||
if (wordNum >= wlen) {
|
||||
ensureCapacity(index + 1);
|
||||
wlen = wordNum + 1;
|
||||
}
|
||||
return wordNum;
|
||||
}
|
||||
|
||||
/** Clears all bits. */
|
||||
public void clear() {
|
||||
Arrays.fill(bits, 0);
|
||||
this.wlen = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* clears a bit, allowing access beyond the current set size without changing the size.
|
||||
*
|
||||
* @param index the index to clear
|
||||
*/
|
||||
public void clear(long index) {
|
||||
int wordNum = (int) (index >> 6); // div 64
|
||||
if (wordNum >= wlen) return;
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] &= ~bitmask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a range of bits. Clearing past the end does not change the size of the set.
|
||||
*
|
||||
* @param startIndex lower index
|
||||
* @param endIndex one-past the last bit to clear
|
||||
*/
|
||||
public void clear(int startIndex, int endIndex) {
|
||||
if (endIndex <= startIndex) return;
|
||||
|
||||
int startWord = (startIndex >> 6);
|
||||
if (startWord >= wlen) return;
|
||||
|
||||
// since endIndex is one past the end, this is index of the last
|
||||
// word to be changed.
|
||||
int endWord = ((endIndex - 1) >> 6);
|
||||
|
||||
long startmask = -1L << startIndex;
|
||||
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex
|
||||
// due to wrap
|
||||
|
||||
// invert masks since we are clearing
|
||||
startmask = ~startmask;
|
||||
endmask = ~endmask;
|
||||
|
||||
if (startWord == endWord) {
|
||||
bits[startWord] &= (startmask | endmask);
|
||||
return;
|
||||
}
|
||||
|
||||
bits[startWord] &= startmask;
|
||||
|
||||
int middle = Math.min(wlen, endWord);
|
||||
Arrays.fill(bits, startWord + 1, middle, 0L);
|
||||
if (endWord < wlen) {
|
||||
bits[endWord] &= endmask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a range of bits. Clearing past the end does not change the size of the set.
|
||||
*
|
||||
* @param startIndex lower index
|
||||
* @param endIndex one-past the last bit to clear
|
||||
*/
|
||||
public void clear(long startIndex, long endIndex) {
|
||||
if (endIndex <= startIndex) return;
|
||||
|
||||
int startWord = (int) (startIndex >> 6);
|
||||
if (startWord >= wlen) return;
|
||||
|
||||
// since endIndex is one past the end, this is index of the last
|
||||
// word to be changed.
|
||||
int endWord = (int) ((endIndex - 1) >> 6);
|
||||
|
||||
long startmask = -1L << startIndex;
|
||||
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex
|
||||
// due to wrap
|
||||
|
||||
// invert masks since we are clearing
|
||||
startmask = ~startmask;
|
||||
endmask = ~endmask;
|
||||
|
||||
if (startWord == endWord) {
|
||||
bits[startWord] &= (startmask | endmask);
|
||||
return;
|
||||
}
|
||||
|
||||
bits[startWord] &= startmask;
|
||||
|
||||
int middle = Math.min(wlen, endWord);
|
||||
Arrays.fill(bits, startWord + 1, middle, 0L);
|
||||
if (endWord < wlen) {
|
||||
bits[endWord] &= endmask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a bit and returns the previous value. The index should be less than the BitSet size.
|
||||
*
|
||||
* @param index the index to set
|
||||
* @return previous state of the index
|
||||
*/
|
||||
public boolean getAndSet(int index) {
|
||||
int wordNum = index >> 6; // div 64
|
||||
int bit = index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
boolean val = (bits[wordNum] & bitmask) != 0;
|
||||
bits[wordNum] |= bitmask;
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a bit and returns the previous value. The index should be less than the BitSet size.
|
||||
*
|
||||
* @param index the index to set
|
||||
* @return previous state of the index
|
||||
*/
|
||||
public boolean getAndSet(long index) {
|
||||
int wordNum = (int) (index >> 6); // div 64
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
boolean val = (bits[wordNum] & bitmask) != 0;
|
||||
bits[wordNum] |= bitmask;
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips a bit, expanding the set size if necessary.
|
||||
*
|
||||
* @param index the index to flip
|
||||
*/
|
||||
public void flip(long index) {
|
||||
int wordNum = expandingWordNum(index);
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] ^= bitmask;
|
||||
}
|
||||
|
||||
/**
|
||||
* flips a bit and returns the resulting bit value. The index should be less than the BitSet size.
|
||||
*
|
||||
* @param index the index to flip
|
||||
* @return previous state of the index
|
||||
*/
|
||||
public boolean flipAndGet(int index) {
|
||||
int wordNum = index >> 6; // div 64
|
||||
int bit = index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] ^= bitmask;
|
||||
return (bits[wordNum] & bitmask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* flips a bit and returns the resulting bit value. The index should be less than the BitSet size.
|
||||
*
|
||||
* @param index the index to flip
|
||||
* @return previous state of the index
|
||||
*/
|
||||
public boolean flipAndGet(long index) {
|
||||
int wordNum = (int) (index >> 6); // div 64
|
||||
int bit = (int) index & 0x3f; // mod 64
|
||||
long bitmask = 1L << bit;
|
||||
bits[wordNum] ^= bitmask;
|
||||
return (bits[wordNum] & bitmask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flips a range of bits, expanding the set size if necessary
|
||||
*
|
||||
* @param startIndex lower index
|
||||
* @param endIndex one-past the last bit to flip
|
||||
*/
|
||||
public void flip(long startIndex, long endIndex) {
|
||||
if (endIndex <= startIndex) return;
|
||||
int startWord = (int) (startIndex >> 6);
|
||||
|
||||
// since endIndex is one past the end, this is index of the last
|
||||
// word to be changed.
|
||||
int endWord = expandingWordNum(endIndex - 1);
|
||||
|
||||
long startmask = -1L << startIndex;
|
||||
long endmask = -1L >>> -endIndex; // 64-(endIndex&0x3f) is the same as -endIndex
|
||||
// due to wrap
|
||||
|
||||
if (startWord == endWord) {
|
||||
bits[startWord] ^= (startmask & endmask);
|
||||
return;
|
||||
}
|
||||
|
||||
bits[startWord] ^= startmask;
|
||||
|
||||
for (int i = startWord + 1; i < endWord; i++) {
|
||||
bits[i] = ~bits[i];
|
||||
}
|
||||
|
||||
bits[endWord] ^= endmask;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of set bits
|
||||
*/
|
||||
public long cardinality() {
|
||||
return BitUtil.pop_array(bits, 0, wlen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a The first set
|
||||
* @param b The second set
|
||||
* @return Returns the popcount or cardinality of the intersection of the two sets. Neither set is
|
||||
* modified.
|
||||
*/
|
||||
public static long intersectionCount(BitSet a, BitSet b) {
|
||||
return BitUtil.pop_intersect(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a The first set
|
||||
* @param b The second set
|
||||
* @return Returns the popcount or cardinality of the union of the two sets. Neither set is
|
||||
* modified.
|
||||
*/
|
||||
public static long unionCount(BitSet a, BitSet b) {
|
||||
long tot = BitUtil.pop_union(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen));
|
||||
if (a.wlen < b.wlen) {
|
||||
tot += BitUtil.pop_array(b.bits, a.wlen, b.wlen - a.wlen);
|
||||
} else if (a.wlen > b.wlen) {
|
||||
tot += BitUtil.pop_array(a.bits, b.wlen, a.wlen - b.wlen);
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a The first set
|
||||
* @param b The second set
|
||||
* @return Returns the popcount or cardinality of "a and not b" or "intersection(a, not(b))".
|
||||
* Neither set is modified.
|
||||
*/
|
||||
public static long andNotCount(BitSet a, BitSet b) {
|
||||
long tot = BitUtil.pop_andnot(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen));
|
||||
if (a.wlen > b.wlen) {
|
||||
tot += BitUtil.pop_array(a.bits, b.wlen, a.wlen - b.wlen);
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param a The first set
|
||||
* @param b The second set
|
||||
* @return Returns the popcount or cardinality of the exclusive-or of the two sets. Neither set is
|
||||
* modified.
|
||||
*/
|
||||
public static long xorCount(BitSet a, BitSet b) {
|
||||
long tot = BitUtil.pop_xor(a.bits, b.bits, 0, Math.min(a.wlen, b.wlen));
|
||||
if (a.wlen < b.wlen) {
|
||||
tot += BitUtil.pop_array(b.bits, a.wlen, b.wlen - a.wlen);
|
||||
} else if (a.wlen > b.wlen) {
|
||||
tot += BitUtil.pop_array(a.bits, b.wlen, a.wlen - b.wlen);
|
||||
}
|
||||
return tot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index The index to start scanning from, inclusive.
|
||||
* @return Returns the index of the first set bit starting at the index specified. -1 is returned
|
||||
* if there are no more set bits.
|
||||
*/
|
||||
public int nextSetBit(int index) {
|
||||
int i = index >> 6;
|
||||
if (i >= wlen) return -1;
|
||||
int subIndex = index & 0x3f; // index within the word
|
||||
long word = bits[i] >> subIndex; // skip all the bits to the right of index
|
||||
|
||||
if (word != 0) {
|
||||
return (i << 6) + subIndex + Long.numberOfTrailingZeros(word);
|
||||
}
|
||||
|
||||
while (++i < wlen) {
|
||||
word = bits[i];
|
||||
if (word != 0) return (i << 6) + Long.numberOfTrailingZeros(word);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param index The index to start scanning from, inclusive.
|
||||
* @return Returns the index of the first set bit starting at the index specified. -1 is returned
|
||||
* if there are no more set bits.
|
||||
*/
|
||||
public long nextSetBit(long index) {
|
||||
int i = (int) (index >>> 6);
|
||||
if (i >= wlen) return -1;
|
||||
int subIndex = (int) index & 0x3f; // index within the word
|
||||
long word = bits[i] >>> subIndex; // skip all the bits to the right of index
|
||||
|
||||
if (word != 0) {
|
||||
return (((long) i) << 6) + (subIndex + Long.numberOfTrailingZeros(word));
|
||||
}
|
||||
|
||||
while (++i < wlen) {
|
||||
word = bits[i];
|
||||
if (word != 0) return (((long) i) << 6) + Long.numberOfTrailingZeros(word);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
BitSet obs = (BitSet) super.clone();
|
||||
obs.bits = (long[]) obs.bits.clone(); // hopefully an array clone is as
|
||||
// fast(er) than arraycopy
|
||||
return obs;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this = this AND other
|
||||
*
|
||||
* @param other The bitset to intersect with.
|
||||
*/
|
||||
public void intersect(BitSet other) {
|
||||
int newLen = Math.min(this.wlen, other.wlen);
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
// testing against zero can be more efficient
|
||||
int pos = newLen;
|
||||
while (--pos >= 0) {
|
||||
thisArr[pos] &= otherArr[pos];
|
||||
}
|
||||
if (this.wlen > newLen) {
|
||||
// fill zeros from the new shorter length to the old length
|
||||
Arrays.fill(bits, newLen, this.wlen, 0);
|
||||
}
|
||||
this.wlen = newLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* this = this OR other
|
||||
*
|
||||
* @param other The bitset to union with.
|
||||
*/
|
||||
public void union(BitSet other) {
|
||||
int newLen = Math.max(wlen, other.wlen);
|
||||
ensureCapacityWords(newLen);
|
||||
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
int pos = Math.min(wlen, other.wlen);
|
||||
while (--pos >= 0) {
|
||||
thisArr[pos] |= otherArr[pos];
|
||||
}
|
||||
if (this.wlen < newLen) {
|
||||
System.arraycopy(otherArr, this.wlen, thisArr, this.wlen, newLen - this.wlen);
|
||||
}
|
||||
this.wlen = newLen;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all elements set in other: this = this AND_NOT other
|
||||
*
|
||||
* @param other The other bitset.
|
||||
*/
|
||||
public void remove(BitSet other) {
|
||||
int idx = Math.min(wlen, other.wlen);
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
while (--idx >= 0) {
|
||||
thisArr[idx] &= ~otherArr[idx];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* this = this XOR other
|
||||
*
|
||||
* @param other The other bitset.
|
||||
*/
|
||||
public void xor(BitSet other) {
|
||||
int newLen = Math.max(wlen, other.wlen);
|
||||
ensureCapacityWords(newLen);
|
||||
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
int pos = Math.min(wlen, other.wlen);
|
||||
while (--pos >= 0) {
|
||||
thisArr[pos] ^= otherArr[pos];
|
||||
}
|
||||
if (this.wlen < newLen) {
|
||||
System.arraycopy(otherArr, this.wlen, thisArr, this.wlen, newLen - this.wlen);
|
||||
}
|
||||
this.wlen = newLen;
|
||||
}
|
||||
|
||||
// some BitSet compatibility methods
|
||||
|
||||
// ** see {@link intersect} */
|
||||
public void and(BitSet other) {
|
||||
intersect(other);
|
||||
}
|
||||
|
||||
// ** see {@link union} */
|
||||
public void or(BitSet other) {
|
||||
union(other);
|
||||
}
|
||||
|
||||
// ** see {@link andNot} */
|
||||
public void andNot(BitSet other) {
|
||||
remove(other);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param other The other bitset.
|
||||
* @return true if the sets have any elements in common
|
||||
*/
|
||||
public boolean intersects(BitSet other) {
|
||||
int pos = Math.min(this.wlen, other.wlen);
|
||||
long[] thisArr = this.bits;
|
||||
long[] otherArr = other.bits;
|
||||
while (--pos >= 0) {
|
||||
if ((thisArr[pos] & otherArr[pos]) != 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expand the long[] with the size given as a number of words (64 bit longs). getNumWords() is
|
||||
* unchanged by this call.
|
||||
*
|
||||
* @param numWords The size to expand to (64-bit long words)
|
||||
*/
|
||||
public void ensureCapacityWords(int numWords) {
|
||||
if (bits.length < numWords) {
|
||||
bits = grow(bits, numWords);
|
||||
}
|
||||
}
|
||||
|
||||
public static long[] grow(long[] array, int minSize) {
|
||||
if (array.length < minSize) {
|
||||
long[] newArray = new long[getNextSize(minSize)];
|
||||
System.arraycopy(array, 0, newArray, 0, array.length);
|
||||
return newArray;
|
||||
} else return array;
|
||||
}
|
||||
|
||||
public static int getNextSize(int targetSize) {
|
||||
/*
|
||||
* This over-allocates proportional to the list size, making room for additional
|
||||
* growth. The over-allocation is mild, but is enough to give linear-time
|
||||
* amortized behavior over a long sequence of appends() in the presence of a
|
||||
* poorly-performing system realloc(). The growth pattern is: 0, 4, 8, 16, 25, 35,
|
||||
* 46, 58, 72, 88, ...
|
||||
*/
|
||||
return (targetSize >> 3) + (targetSize < 9 ? 3 : 6) + targetSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the long[] is big enough to hold numBits, expanding it if necessary. getNumWords()
|
||||
* is unchanged by this call.
|
||||
*
|
||||
* @param numBits The number of bits to expand to
|
||||
*/
|
||||
public void ensureCapacity(long numBits) {
|
||||
ensureCapacityWords(bits2words(numBits));
|
||||
}
|
||||
|
||||
/** Lowers {@link #wlen}, the number of words in use, by checking for trailing zero words. */
|
||||
public void trimTrailingZeros() {
|
||||
int idx = wlen - 1;
|
||||
while (idx >= 0 && bits[idx] == 0) idx--;
|
||||
wlen = idx + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* returns the number of 64 bit words it would take to hold numBits
|
||||
*/
|
||||
public static int bits2words(long numBits) {
|
||||
return (int) (((numBits - 1) >>> 6) + 1);
|
||||
}
|
||||
|
||||
/* returns true if both sets have the same bits set */
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof BitSet)) return false;
|
||||
|
||||
BitSet a;
|
||||
BitSet b = (BitSet) o;
|
||||
|
||||
// make a the larger set.
|
||||
if (b.wlen > this.wlen) {
|
||||
a = b;
|
||||
b = this;
|
||||
} else {
|
||||
a = this;
|
||||
}
|
||||
|
||||
// check for any set bits out of the range of b
|
||||
for (int i = a.wlen - 1; i >= b.wlen; i--) {
|
||||
if (a.bits[i] != 0) return false;
|
||||
}
|
||||
|
||||
for (int i = b.wlen - 1; i >= 0; i--) {
|
||||
if (a.bits[i] != b.bits[i]) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Start with a zero hash and use a mix that results in zero if the input is zero.
|
||||
// This effectively truncates trailing zeros without an explicit check.
|
||||
long h = 0;
|
||||
for (int i = bits.length; --i >= 0; ) {
|
||||
h ^= bits[i];
|
||||
h = (h << 1) | (h >>> 63); // rotate left
|
||||
}
|
||||
|
||||
// fold leftmost bits into right and add a constant to prevent
|
||||
// empty sets from returning 0, which is too common.
|
||||
return (int) ((h >> 32) ^ h) + 0x98761234;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
long bit = nextSetBit(0);
|
||||
if (bit < 0) {
|
||||
return "{}";
|
||||
}
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("{");
|
||||
|
||||
builder.append(Long.toString(bit));
|
||||
while ((bit = nextSetBit(bit + 1)) >= 0) {
|
||||
builder.append(", ");
|
||||
builder.append(Long.toString(bit));
|
||||
}
|
||||
builder.append("}");
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view over this bitset data compatible with {@link IntLookupContainer}. A new object
|
||||
* is always returned, but its methods reflect the current state of the bitset (the view is not a
|
||||
* snapshot).
|
||||
*
|
||||
* <p>Methods of the returned {@link IntLookupContainer} may throw a {@link RuntimeException} if
|
||||
* the cardinality of this bitset exceeds the int range.
|
||||
*
|
||||
* @return The view of this bitset as {@link IntLookupContainer}.
|
||||
*/
|
||||
public IntLookupContainer asIntLookupContainer() {
|
||||
return new IntLookupContainer() {
|
||||
@Override
|
||||
public int size() {
|
||||
return getCurrentCardinality();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return BitSet.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<IntCursor> iterator() {
|
||||
return new Iterator<IntCursor>() {
|
||||
private long nextBitSet = BitSet.this.nextSetBit(0);
|
||||
private final IntCursor cursor = new IntCursor();
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nextBitSet >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IntCursor next() {
|
||||
final long value = nextBitSet;
|
||||
if (value < 0) throw new NoSuchElementException();
|
||||
if (value > Integer.MAX_VALUE)
|
||||
throw new RuntimeException("BitSet range larger than maximum positive integer.");
|
||||
|
||||
nextBitSet = BitSet.this.nextSetBit(value + 1);
|
||||
cursor.index = cursor.value = (int) value;
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] toArray() {
|
||||
final int[] data = new int[getCurrentCardinality()];
|
||||
final BitSetIterator i = BitSet.this.iterator();
|
||||
for (int j = 0, bit = i.nextSetBit(); bit >= 0; bit = i.nextSetBit()) {
|
||||
data[j++] = bit;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IntPredicate> T forEach(T predicate) {
|
||||
final BitSetIterator i = BitSet.this.iterator();
|
||||
for (int bit = i.nextSetBit(); bit >= 0; bit = i.nextSetBit()) {
|
||||
if (predicate.apply(bit) == false) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IntProcedure> T forEach(T procedure) {
|
||||
final BitSetIterator i = BitSet.this.iterator();
|
||||
for (int bit = i.nextSetBit(); bit >= 0; bit = i.nextSetBit()) {
|
||||
procedure.apply(bit);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(int index) {
|
||||
return index < 0 || BitSet.this.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the bitset's cardinality to an integer or throws a {@link RuntimeException} if the
|
||||
* cardinality exceeds maximum int range.
|
||||
*/
|
||||
private int getCurrentCardinality() {
|
||||
long cardinality = BitSet.this.cardinality();
|
||||
if (cardinality > Integer.MAX_VALUE)
|
||||
throw new RuntimeException(
|
||||
"Bitset is larger than maximum positive integer: " + cardinality);
|
||||
return (int) cardinality;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view over this bitset data compatible with {@link LongLookupContainer}. A new object
|
||||
* is always returned, but its methods reflect the current state of the bitset (the view is not a
|
||||
* snapshot).
|
||||
*
|
||||
* @return The view of this bitset as {@link LongLookupContainer}.
|
||||
*/
|
||||
public LongLookupContainer asLongLookupContainer() {
|
||||
return new LongLookupContainer() {
|
||||
@Override
|
||||
public int size() {
|
||||
return getCurrentCardinality();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return BitSet.this.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<LongCursor> iterator() {
|
||||
return new Iterator<LongCursor>() {
|
||||
private long nextBitSet = BitSet.this.nextSetBit(0);
|
||||
private final LongCursor cursor = new LongCursor();
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return nextBitSet >= 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LongCursor next() {
|
||||
final long value = nextBitSet;
|
||||
if (value < 0) throw new NoSuchElementException();
|
||||
|
||||
nextBitSet = BitSet.this.nextSetBit(value + 1);
|
||||
cursor.index = (int) value;
|
||||
cursor.value = value;
|
||||
return cursor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] toArray() {
|
||||
final long[] data = new long[getCurrentCardinality()];
|
||||
final BitSet bset = BitSet.this;
|
||||
int j = 0;
|
||||
for (long bit = bset.nextSetBit((long) 0); bit >= 0; bit = bset.nextSetBit(bit + 1)) {
|
||||
data[j++] = bit;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends LongPredicate> T forEach(T predicate) {
|
||||
final BitSet bset = BitSet.this;
|
||||
for (long bit = bset.nextSetBit((long) 0); bit >= 0; bit = bset.nextSetBit(bit + 1)) {
|
||||
if (predicate.apply(bit) == false) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends LongProcedure> T forEach(T procedure) {
|
||||
final BitSet bset = BitSet.this;
|
||||
for (long bit = bset.nextSetBit((long) 0); bit >= 0; bit = bset.nextSetBit(bit + 1)) {
|
||||
procedure.apply(bit);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(long index) {
|
||||
return index < 0 || BitSet.this.get(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds the bitset's cardinality to an integer or throws a {@link RuntimeException} if the
|
||||
* cardinality exceeds maximum int range.
|
||||
*/
|
||||
private int getCurrentCardinality() {
|
||||
long cardinality = BitSet.this.cardinality();
|
||||
if (cardinality > Integer.MAX_VALUE)
|
||||
throw new RuntimeException(
|
||||
"Bitset is larger than maximum positive integer: " + cardinality);
|
||||
return (int) cardinality;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
@ -1,356 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* An iterator to iterate over set bits in an BitSet. This is faster than nextSetBit() for iterating
|
||||
* over the complete set of bits, especially when the density of the bits set is high.
|
||||
*/
|
||||
public class BitSetIterator {
|
||||
// The General Idea: instead of having an array per byte that has
|
||||
// the offsets of the next set bit, that array could be
|
||||
// packed inside a 32 bit integer (8 4 bit numbers). That
|
||||
// should be faster than accessing an array for each index, and
|
||||
// the total array size is kept smaller (256*sizeof(int))=1K
|
||||
static final int[] bitlist = {
|
||||
0x0,
|
||||
0x1,
|
||||
0x2,
|
||||
0x21,
|
||||
0x3,
|
||||
0x31,
|
||||
0x32,
|
||||
0x321,
|
||||
0x4,
|
||||
0x41,
|
||||
0x42,
|
||||
0x421,
|
||||
0x43,
|
||||
0x431,
|
||||
0x432,
|
||||
0x4321,
|
||||
0x5,
|
||||
0x51,
|
||||
0x52,
|
||||
0x521,
|
||||
0x53,
|
||||
0x531,
|
||||
0x532,
|
||||
0x5321,
|
||||
0x54,
|
||||
0x541,
|
||||
0x542,
|
||||
0x5421,
|
||||
0x543,
|
||||
0x5431,
|
||||
0x5432,
|
||||
0x54321,
|
||||
0x6,
|
||||
0x61,
|
||||
0x62,
|
||||
0x621,
|
||||
0x63,
|
||||
0x631,
|
||||
0x632,
|
||||
0x6321,
|
||||
0x64,
|
||||
0x641,
|
||||
0x642,
|
||||
0x6421,
|
||||
0x643,
|
||||
0x6431,
|
||||
0x6432,
|
||||
0x64321,
|
||||
0x65,
|
||||
0x651,
|
||||
0x652,
|
||||
0x6521,
|
||||
0x653,
|
||||
0x6531,
|
||||
0x6532,
|
||||
0x65321,
|
||||
0x654,
|
||||
0x6541,
|
||||
0x6542,
|
||||
0x65421,
|
||||
0x6543,
|
||||
0x65431,
|
||||
0x65432,
|
||||
0x654321,
|
||||
0x7,
|
||||
0x71,
|
||||
0x72,
|
||||
0x721,
|
||||
0x73,
|
||||
0x731,
|
||||
0x732,
|
||||
0x7321,
|
||||
0x74,
|
||||
0x741,
|
||||
0x742,
|
||||
0x7421,
|
||||
0x743,
|
||||
0x7431,
|
||||
0x7432,
|
||||
0x74321,
|
||||
0x75,
|
||||
0x751,
|
||||
0x752,
|
||||
0x7521,
|
||||
0x753,
|
||||
0x7531,
|
||||
0x7532,
|
||||
0x75321,
|
||||
0x754,
|
||||
0x7541,
|
||||
0x7542,
|
||||
0x75421,
|
||||
0x7543,
|
||||
0x75431,
|
||||
0x75432,
|
||||
0x754321,
|
||||
0x76,
|
||||
0x761,
|
||||
0x762,
|
||||
0x7621,
|
||||
0x763,
|
||||
0x7631,
|
||||
0x7632,
|
||||
0x76321,
|
||||
0x764,
|
||||
0x7641,
|
||||
0x7642,
|
||||
0x76421,
|
||||
0x7643,
|
||||
0x76431,
|
||||
0x76432,
|
||||
0x764321,
|
||||
0x765,
|
||||
0x7651,
|
||||
0x7652,
|
||||
0x76521,
|
||||
0x7653,
|
||||
0x76531,
|
||||
0x76532,
|
||||
0x765321,
|
||||
0x7654,
|
||||
0x76541,
|
||||
0x76542,
|
||||
0x765421,
|
||||
0x76543,
|
||||
0x765431,
|
||||
0x765432,
|
||||
0x7654321,
|
||||
0x8,
|
||||
0x81,
|
||||
0x82,
|
||||
0x821,
|
||||
0x83,
|
||||
0x831,
|
||||
0x832,
|
||||
0x8321,
|
||||
0x84,
|
||||
0x841,
|
||||
0x842,
|
||||
0x8421,
|
||||
0x843,
|
||||
0x8431,
|
||||
0x8432,
|
||||
0x84321,
|
||||
0x85,
|
||||
0x851,
|
||||
0x852,
|
||||
0x8521,
|
||||
0x853,
|
||||
0x8531,
|
||||
0x8532,
|
||||
0x85321,
|
||||
0x854,
|
||||
0x8541,
|
||||
0x8542,
|
||||
0x85421,
|
||||
0x8543,
|
||||
0x85431,
|
||||
0x85432,
|
||||
0x854321,
|
||||
0x86,
|
||||
0x861,
|
||||
0x862,
|
||||
0x8621,
|
||||
0x863,
|
||||
0x8631,
|
||||
0x8632,
|
||||
0x86321,
|
||||
0x864,
|
||||
0x8641,
|
||||
0x8642,
|
||||
0x86421,
|
||||
0x8643,
|
||||
0x86431,
|
||||
0x86432,
|
||||
0x864321,
|
||||
0x865,
|
||||
0x8651,
|
||||
0x8652,
|
||||
0x86521,
|
||||
0x8653,
|
||||
0x86531,
|
||||
0x86532,
|
||||
0x865321,
|
||||
0x8654,
|
||||
0x86541,
|
||||
0x86542,
|
||||
0x865421,
|
||||
0x86543,
|
||||
0x865431,
|
||||
0x865432,
|
||||
0x8654321,
|
||||
0x87,
|
||||
0x871,
|
||||
0x872,
|
||||
0x8721,
|
||||
0x873,
|
||||
0x8731,
|
||||
0x8732,
|
||||
0x87321,
|
||||
0x874,
|
||||
0x8741,
|
||||
0x8742,
|
||||
0x87421,
|
||||
0x8743,
|
||||
0x87431,
|
||||
0x87432,
|
||||
0x874321,
|
||||
0x875,
|
||||
0x8751,
|
||||
0x8752,
|
||||
0x87521,
|
||||
0x8753,
|
||||
0x87531,
|
||||
0x87532,
|
||||
0x875321,
|
||||
0x8754,
|
||||
0x87541,
|
||||
0x87542,
|
||||
0x875421,
|
||||
0x87543,
|
||||
0x875431,
|
||||
0x875432,
|
||||
0x8754321,
|
||||
0x876,
|
||||
0x8761,
|
||||
0x8762,
|
||||
0x87621,
|
||||
0x8763,
|
||||
0x87631,
|
||||
0x87632,
|
||||
0x876321,
|
||||
0x8764,
|
||||
0x87641,
|
||||
0x87642,
|
||||
0x876421,
|
||||
0x87643,
|
||||
0x876431,
|
||||
0x876432,
|
||||
0x8764321,
|
||||
0x8765,
|
||||
0x87651,
|
||||
0x87652,
|
||||
0x876521,
|
||||
0x87653,
|
||||
0x876531,
|
||||
0x876532,
|
||||
0x8765321,
|
||||
0x87654,
|
||||
0x876541,
|
||||
0x876542,
|
||||
0x8765421,
|
||||
0x876543,
|
||||
0x8765431,
|
||||
0x8765432,
|
||||
0x87654321
|
||||
};
|
||||
|
||||
/**
|
||||
* *** the python code that generated bitlist def bits2int(val): arr=0 for shift in range(8,0,-1):
|
||||
* if val & 0x80: arr = (arr << 4) | shift val = val << 1 return arr
|
||||
*
|
||||
* <p>def int_table(): tbl = [ hex(bits2int(val)).strip('L') for val in range(256) ] return
|
||||
* ','.join(tbl) ****
|
||||
*/
|
||||
|
||||
// hmmm, what about an iterator that finds zeros though,
|
||||
// or a reverse iterator... should they be separate classes
|
||||
// for efficiency, or have a common root interface? (or
|
||||
// maybe both? could ask for a SetBitsIterator, etc...
|
||||
|
||||
private final long[] arr;
|
||||
|
||||
private final int words;
|
||||
private int i = -1;
|
||||
private long word;
|
||||
private int wordShift;
|
||||
private int indexArray;
|
||||
|
||||
public BitSetIterator(BitSet obs) {
|
||||
this(obs.bits, obs.wlen);
|
||||
}
|
||||
|
||||
public BitSetIterator(long[] bits, int numWords) {
|
||||
arr = bits;
|
||||
words = numWords;
|
||||
}
|
||||
|
||||
// 64 bit shifts
|
||||
private void shift() {
|
||||
if ((int) word == 0) {
|
||||
wordShift += 32;
|
||||
word = word >>> 32;
|
||||
}
|
||||
if ((word & 0x0000FFFF) == 0) {
|
||||
wordShift += 16;
|
||||
word >>>= 16;
|
||||
}
|
||||
if ((word & 0x000000FF) == 0) {
|
||||
wordShift += 8;
|
||||
word >>>= 8;
|
||||
}
|
||||
indexArray = bitlist[(int) word & 0xff];
|
||||
}
|
||||
|
||||
public static final int NO_MORE = -1;
|
||||
|
||||
public int nextSetBit() {
|
||||
if (indexArray == 0) {
|
||||
if (word != 0) {
|
||||
word >>>= 8;
|
||||
wordShift += 8;
|
||||
}
|
||||
|
||||
while (word == 0) {
|
||||
if (++i >= words) {
|
||||
return NO_MORE;
|
||||
}
|
||||
word = arr[i];
|
||||
wordShift = -1; // loop invariant code motion should move this
|
||||
}
|
||||
|
||||
// after the first time, should I go with a linear search, or
|
||||
// stick with the binary search in shift?
|
||||
shift();
|
||||
}
|
||||
|
||||
int bitIndex = (indexArray & 0x0f) + wordShift;
|
||||
indexArray >>>= 4;
|
||||
// should i<<6 be cached as a separate variable?
|
||||
// it would only save one cycle in the best circumstances.
|
||||
return (i << 6) + bitIndex;
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/** A variety of high efficiency bit twiddling routines. */
|
||||
final class BitUtil {
|
||||
private BitUtil() {} // no instance
|
||||
|
||||
// The pop methods used to rely on bit-manipulation tricks for speed but it
|
||||
// turns out that it is faster to use the Long.bitCount method (which is an
|
||||
// intrinsic since Java 6u18) in a naive loop, see LUCENE-2221
|
||||
|
||||
/** Returns the number of set bits in an array of longs. */
|
||||
public static long pop_array(long[] arr, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the popcount or cardinality of the two sets after an intersection. Neither array is
|
||||
* modified.
|
||||
*/
|
||||
public static long pop_intersect(long[] arr1, long[] arr2, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr1[i] & arr2[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/** Returns the popcount or cardinality of the union of two sets. Neither array is modified. */
|
||||
public static long pop_union(long[] arr1, long[] arr2, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr1[i] | arr2[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/** Returns the popcount or cardinality of A & ~B. Neither array is modified. */
|
||||
public static long pop_andnot(long[] arr1, long[] arr2, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr1[i] & ~arr2[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/** Returns the popcount or cardinality of A ^ B Neither array is modified. */
|
||||
public static long pop_xor(long[] arr1, long[] arr2, int wordOffset, int numWords) {
|
||||
long popCount = 0;
|
||||
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
|
||||
popCount += Long.bitCount(arr1[i] ^ arr2[i]);
|
||||
}
|
||||
return popCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the next highest power of two, or the current value if it's already a power of two or
|
||||
* zero
|
||||
*/
|
||||
public static int nextHighestPowerOfTwo(int v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the next highest power of two, or the current value if it's already a power of two or
|
||||
* zero
|
||||
*/
|
||||
public static long nextHighestPowerOfTwo(long v) {
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v |= v >> 32;
|
||||
v++;
|
||||
return v;
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Array resizing proportional to the current buffer size, optionally kept within the given minimum
|
||||
* and maximum growth limits. Java's {@link ArrayList} uses:
|
||||
*
|
||||
* <pre>
|
||||
* minGrow = 1
|
||||
* maxGrow = Integer.MAX_VALUE (unbounded)
|
||||
* growRatio = 1.5f
|
||||
* </pre>
|
||||
*/
|
||||
public final class BoundedProportionalArraySizingStrategy implements ArraySizingStrategy {
|
||||
|
||||
/** Instance of {@link BoundedProportionalArraySizingStrategy} with default values. */
|
||||
public static final BoundedProportionalArraySizingStrategy DEFAULT_INSTANCE =
|
||||
new BoundedProportionalArraySizingStrategy();
|
||||
|
||||
/**
|
||||
* Maximum allocable array length (approximately the largest positive integer decreased by the
|
||||
* array's object header).
|
||||
*/
|
||||
public static final int MAX_ARRAY_LENGTH =
|
||||
Integer.MAX_VALUE - /* aligned array header + slack */ 32;
|
||||
|
||||
/** Minimum grow count. */
|
||||
public static final int DEFAULT_MIN_GROW_COUNT = 10;
|
||||
|
||||
/** Maximum grow count (unbounded). */
|
||||
public static final int DEFAULT_MAX_GROW_COUNT = MAX_ARRAY_LENGTH;
|
||||
|
||||
/** Default resize is by half the current buffer's size. */
|
||||
public static final float DEFAULT_GROW_RATIO = 1.5f;
|
||||
|
||||
/** Minimum number of elements to grow, if limit exceeded. */
|
||||
public final int minGrowCount;
|
||||
|
||||
/** Maximum number of elements to grow, if limit exceeded. */
|
||||
public final int maxGrowCount;
|
||||
|
||||
/**
|
||||
* The current buffer length is multiplied by this ratio to get the first estimate for the new
|
||||
* size. To double the size of the current buffer, for example, set to <code>2</code>.
|
||||
*/
|
||||
public final float growRatio;
|
||||
|
||||
/** Create the default sizing strategy. */
|
||||
public BoundedProportionalArraySizingStrategy() {
|
||||
this(DEFAULT_MIN_GROW_COUNT, DEFAULT_MAX_GROW_COUNT, DEFAULT_GROW_RATIO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the sizing strategy with custom policies.
|
||||
*
|
||||
* @param minGrow Minimum number of elements to grow by when expanding.
|
||||
* @param maxGrow Maximum number of elements to grow by when expanding.
|
||||
* @param ratio The ratio of expansion compared to the previous buffer size.
|
||||
*/
|
||||
public BoundedProportionalArraySizingStrategy(int minGrow, int maxGrow, float ratio) {
|
||||
assert minGrow >= 1 : "Min grow must be >= 1.";
|
||||
assert maxGrow >= minGrow : "Max grow must be >= min grow.";
|
||||
assert ratio >= 1f : "Growth ratio must be >= 1 (was " + ratio + ").";
|
||||
|
||||
this.minGrowCount = minGrow;
|
||||
this.maxGrowCount = maxGrow;
|
||||
this.growRatio = ratio - 1.0f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow according to {@link #growRatio}, {@link #minGrowCount} and {@link #maxGrowCount}.
|
||||
*
|
||||
* @param currentBufferLength The current length of the buffer.
|
||||
* @param elementsCount The number of elements stored in the buffer.
|
||||
* @param expectedAdditions The number of expected additions to the buffer.
|
||||
* @return New buffer size.
|
||||
*/
|
||||
public int grow(int currentBufferLength, int elementsCount, int expectedAdditions) {
|
||||
long growBy = (long) ((long) currentBufferLength * growRatio);
|
||||
growBy = Math.max(growBy, minGrowCount);
|
||||
growBy = Math.min(growBy, maxGrowCount);
|
||||
long growTo = Math.min(MAX_ARRAY_LENGTH, growBy + currentBufferLength);
|
||||
long newSize = Math.max((long) elementsCount + expectedAdditions, growTo);
|
||||
|
||||
if (newSize > MAX_ARRAY_LENGTH) {
|
||||
throw new BufferAllocationException(
|
||||
"Java array size exceeded (current length: %d, elements: %d, expected additions: %d)",
|
||||
currentBufferLength, elementsCount, expectedAdditions);
|
||||
}
|
||||
|
||||
return (int) newSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: minGrowCount, maxGrowCount
|
||||
// float: growRatio
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER + Integer.BYTES * 2 + Float.BYTES;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
return ramBytesAllocated();
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* HPPC
|
||||
*
|
||||
* Copyright (C) 2010-2024 Carrot Search s.c. and contributors
|
||||
* All rights reserved.
|
||||
*
|
||||
* Refer to the full license file "LICENSE.txt":
|
||||
* https://github.com/carrotsearch/hppc/blob/master/LICENSE.txt
|
||||
*/
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.IllegalFormatException;
|
||||
import java.util.Locale;
|
||||
|
||||
public class BufferAllocationException extends RuntimeException {
|
||||
public BufferAllocationException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public BufferAllocationException(String message, Object... args) {
|
||||
this(message, null, args);
|
||||
}
|
||||
|
||||
public BufferAllocationException(String message, Throwable t, Object... args) {
|
||||
super(formatMessage(message, t, args), t);
|
||||
}
|
||||
|
||||
private static String formatMessage(String message, Throwable t, Object... args) {
|
||||
try {
|
||||
return String.format(Locale.ROOT, message, args);
|
||||
} catch (IllegalFormatException e) {
|
||||
BufferAllocationException substitute =
|
||||
new BufferAllocationException(message + " [ILLEGAL FORMAT, ARGS SUPPRESSED]");
|
||||
if (t != null) {
|
||||
substitute.addSuppressed(t);
|
||||
}
|
||||
substitute.addSuppressed(e);
|
||||
throw substitute;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,776 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import com.carrotsearch.hppc.procedures.ByteProcedure;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed {@link ByteDeque}. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayDeque.java")
|
||||
public class ByteArrayDeque extends AbstractByteCollection
|
||||
implements ByteDeque, Preallocable, Cloneable, Accountable {
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/** Internal array for storing elements of the deque. */
|
||||
public byte[] buffer = ByteArrayList.EMPTY_ARRAY;
|
||||
|
||||
/**
|
||||
* The index of the element at the head of the deque or an arbitrary number equal to tail if the
|
||||
* deque is empty.
|
||||
*/
|
||||
public int head;
|
||||
|
||||
/** The index at which the next element would be added to the tail of the deque. */
|
||||
public int tail;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public ByteArrayDeque() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public ByteArrayDeque(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public ByteArrayDeque(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
ensureCapacity(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deque from elements of another container, appending elements at the end of the
|
||||
* deque in the iteration order.
|
||||
*/
|
||||
public ByteArrayDeque(ByteContainer container) {
|
||||
this(container.size());
|
||||
addLast(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addFirst(byte e1) {
|
||||
int h = oneLeft(head, buffer.length);
|
||||
if (h == tail) {
|
||||
ensureBufferSpace(1);
|
||||
h = oneLeft(head, buffer.length);
|
||||
}
|
||||
buffer[head = h] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the front of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to add.
|
||||
*/
|
||||
public final void addFirst(byte... elements) {
|
||||
ensureBufferSpace(elements.length);
|
||||
for (byte k : elements) {
|
||||
addFirst(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the front of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(ByteContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (ByteCursor cursor : container) {
|
||||
addFirst(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the front of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(Iterable<? extends ByteCursor> iterable) {
|
||||
int size = 0;
|
||||
for (ByteCursor cursor : iterable) {
|
||||
addFirst(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addLast(byte e1) {
|
||||
int t = oneRight(tail, buffer.length);
|
||||
if (head == t) {
|
||||
ensureBufferSpace(1);
|
||||
t = oneRight(tail, buffer.length);
|
||||
}
|
||||
buffer[tail] = e1;
|
||||
tail = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to iterate over.
|
||||
*/
|
||||
public final void addLast(byte... elements) {
|
||||
ensureBufferSpace(1);
|
||||
for (byte k : elements) {
|
||||
addLast(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the end of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(ByteContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (ByteCursor cursor : container) {
|
||||
addLast(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the end of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(Iterable<? extends ByteCursor> iterable) {
|
||||
int size = 0;
|
||||
for (ByteCursor cursor : iterable) {
|
||||
addLast(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte removeFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
final byte result = buffer[head];
|
||||
buffer[head] = ((byte) 0);
|
||||
head = oneRight(head, buffer.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte removeLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
tail = oneLeft(tail, buffer.length);
|
||||
final byte result = buffer[tail];
|
||||
buffer[tail] = ((byte) 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte getFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[head];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte getLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[oneLeft(tail, buffer.length)];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(byte e1) {
|
||||
final int index = bufferIndexOf(e1);
|
||||
if (index >= 0) removeAtBufferIndex(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the first (counting from head) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int bufferIndexOf(byte e1) {
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
for (int i = head; i != last; i = oneRight(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(byte e1) {
|
||||
final int index = lastBufferIndexOf(e1);
|
||||
if (index >= 0) {
|
||||
removeAtBufferIndex(index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the last (counting from tail) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int lastBufferIndexOf(byte e1) {
|
||||
final int bufLen = buffer.length;
|
||||
final int last = oneLeft(head, bufLen);
|
||||
for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(byte e1) {
|
||||
int removed = 0;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int from, to;
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
buffer[from] = ((byte) 0);
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
|
||||
tail = to;
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at <code>index</code> in the internal {#link {@link #buffer} array,
|
||||
* returning its value.
|
||||
*
|
||||
* @param index Index of the element to remove. The index must be located between {@link #head}
|
||||
* and {@link #tail} in modulo {@link #buffer} arithmetic.
|
||||
*/
|
||||
public void removeAtBufferIndex(int index) {
|
||||
assert (head <= tail ? index >= head && index < tail : index >= head || index < tail)
|
||||
: "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ").";
|
||||
|
||||
// Cache fields in locals (hopefully moved to registers).
|
||||
final byte[] buffer = this.buffer;
|
||||
final int bufLen = buffer.length;
|
||||
final int lastIndex = bufLen - 1;
|
||||
final int head = this.head;
|
||||
final int tail = this.tail;
|
||||
|
||||
final int leftChunk = Math.abs(index - head) % bufLen;
|
||||
final int rightChunk = Math.abs(tail - index) % bufLen;
|
||||
|
||||
if (leftChunk < rightChunk) {
|
||||
if (index >= head) {
|
||||
System.arraycopy(buffer, head, buffer, head + 1, leftChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, 0, buffer, 1, index);
|
||||
buffer[0] = buffer[lastIndex];
|
||||
System.arraycopy(buffer, head, buffer, head + 1, lastIndex - head);
|
||||
}
|
||||
buffer[head] = ((byte) 0);
|
||||
this.head = oneRight(head, bufLen);
|
||||
} else {
|
||||
if (index < tail) {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, rightChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, lastIndex - index);
|
||||
buffer[lastIndex] = buffer[0];
|
||||
System.arraycopy(buffer, 1, buffer, 0, tail);
|
||||
}
|
||||
buffer[tail] = ((byte) 0);
|
||||
this.tail = oneLeft(tail, bufLen);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
if (head <= tail) return tail - head;
|
||||
else return (tail - head + buffer.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The internal array buffers are not released as a result of this call.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
if (head < tail) {
|
||||
Arrays.fill(buffer, head, tail, ((byte) 0));
|
||||
} else {
|
||||
Arrays.fill(buffer, 0, tail, ((byte) 0));
|
||||
Arrays.fill(buffer, head, buffer.length, ((byte) 0));
|
||||
}
|
||||
this.head = tail = 0;
|
||||
}
|
||||
|
||||
/** Release internal buffers of this deque and reallocate with the default buffer. */
|
||||
public void release() {
|
||||
this.head = tail = 0;
|
||||
buffer = ByteArrayList.EMPTY_ARRAY;
|
||||
ensureBufferSpace(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = buffer.length;
|
||||
final int elementsCount = size();
|
||||
|
||||
if (elementsCount + expectedAdditions >= bufferLen) {
|
||||
final int emptySlot = 1; // deque invariant: always an empty slot.
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount + emptySlot, expectedAdditions);
|
||||
assert newSize >= (elementsCount + expectedAdditions + emptySlot)
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
try {
|
||||
final byte[] newBuffer = (new byte[newSize]);
|
||||
if (bufferLen > 0) {
|
||||
toArray(newBuffer);
|
||||
tail = elementsCount;
|
||||
head = 0;
|
||||
}
|
||||
this.buffer = newBuffer;
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new BufferAllocationException(
|
||||
"Not enough memory to allocate new buffers: %,d -> %,d", e, bufferLen, newSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte[] toArray() {
|
||||
|
||||
final int size = size();
|
||||
return toArray((new byte[size]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies elements of this deque to an array. The content of the <code>target</code> array is
|
||||
* filled from index 0 (head of the queue) to index <code>size() - 1</code> (tail of the queue).
|
||||
*
|
||||
* @param target The target array must be large enough to hold all elements.
|
||||
* @return Returns the target argument for chaining.
|
||||
*/
|
||||
public byte[] toArray(byte[] target) {
|
||||
assert target.length >= size() : "Target array must be >= " + size();
|
||||
|
||||
if (head < tail) {
|
||||
// The contents is not wrapped around. Just copy.
|
||||
System.arraycopy(buffer, head, target, 0, size());
|
||||
} else if (head > tail) {
|
||||
// The contents is split. Merge elements from the following indexes:
|
||||
// [head...buffer.length - 1][0, tail - 1]
|
||||
final int rightCount = buffer.length - head;
|
||||
System.arraycopy(buffer, head, target, 0, rightCount);
|
||||
System.arraycopy(buffer, 0, target, rightCount, tail);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public ByteArrayDeque clone() {
|
||||
try {
|
||||
|
||||
ByteArrayDeque cloned = (ByteArrayDeque) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Move one index to the left, wrapping around buffer. */
|
||||
protected static int oneLeft(int index, int modulus) {
|
||||
if (index >= 1) {
|
||||
return index - 1;
|
||||
}
|
||||
return modulus - 1;
|
||||
}
|
||||
|
||||
/** Move one index to the right, wrapping around buffer. */
|
||||
protected static int oneRight(int index, int modulus) {
|
||||
if (index + 1 == modulus) {
|
||||
return 0;
|
||||
}
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, size());
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#iterator}. */
|
||||
private final class ValueIterator extends AbstractIterator<ByteCursor> {
|
||||
private final ByteCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public ValueIterator() {
|
||||
cursor = new ByteCursor();
|
||||
cursor.index = oneLeft(head, buffer.length);
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteCursor fetch() {
|
||||
if (remaining == 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneRight(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}. */
|
||||
private final class DescendingValueIterator extends AbstractIterator<ByteCursor> {
|
||||
private final ByteCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public DescendingValueIterator() {
|
||||
cursor = new ByteCursor();
|
||||
cursor.index = tail;
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteCursor fetch() {
|
||||
if (remaining == 0) return done();
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneLeft(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in head to tail order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntValueCursor c : intDeque) {
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<ByteCursor> iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in tail to head order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (Iterator<IntCursor> i = intDeque.descendingIterator(); i.hasNext();) {
|
||||
* final IntCursor c = i.next();
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<ByteCursor> descendingIterator() {
|
||||
return new DescendingValueIterator();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends ByteProcedure> T forEach(T procedure) {
|
||||
forEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
private void forEach(ByteProcedure procedure, int fromIndex, final int toIndex) {
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends BytePredicate> T forEach(T predicate) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/** Applies <code>procedure</code> to all elements of this deque, tail to head. */
|
||||
@Override
|
||||
public <T extends ByteProcedure> T descendingForEach(T procedure) {
|
||||
descendingForEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive.
|
||||
*/
|
||||
private void descendingForEach(ByteProcedure procedure, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
procedure.apply(buffer[i]);
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends BytePredicate> T descendingForEach(T predicate) {
|
||||
descendingForEach(predicate, head, tail);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive or until the predicate returns <code>false</code>.
|
||||
*/
|
||||
private void descendingForEach(BytePredicate predicate, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(BytePredicate predicate) {
|
||||
final byte[] buffer = this.buffer;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int removed = 0;
|
||||
int from, to;
|
||||
from = to = head;
|
||||
try {
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = ((byte) 0);
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
} finally {
|
||||
// Keep the deque in consistent state even if the predicate throws an exception.
|
||||
for (; from != last; from = oneRight(from, bufLen)) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
tail = to;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(byte e) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (((e) == (buffer[i]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1;
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare order-aligned elements against another {@link ByteDeque}. */
|
||||
protected boolean equalElements(ByteArrayDeque other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<ByteCursor> i1 = this.iterator();
|
||||
Iterator<? extends ByteCursor> i2 = other.iterator();
|
||||
|
||||
while (i1.hasNext() && i2.hasNext()) {
|
||||
if (!((i1.next().value) == (i2.next().value))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !i1.hasNext() && !i2.hasNext();
|
||||
}
|
||||
|
||||
/** Create a new deque by pushing a variable number of arguments to the end of it. */
|
||||
public static ByteArrayDeque from(byte... elements) {
|
||||
final ByteArrayDeque coll = new ByteArrayDeque(elements.length);
|
||||
coll.addLast(elements);
|
||||
return coll;
|
||||
}
|
||||
}
|
@ -1,579 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed list of bytes. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayList.java")
|
||||
public class ByteArrayList extends AbstractByteCollection
|
||||
implements ByteIndexedContainer, Preallocable, Cloneable, Accountable {
|
||||
/** An immutable empty buffer (array). */
|
||||
public static final byte[] EMPTY_ARRAY = new byte[0];
|
||||
|
||||
;
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/**
|
||||
* Internal array for storing the list. The array may be larger than the current size ({@link
|
||||
* #size()}).
|
||||
*/
|
||||
public byte[] buffer = EMPTY_ARRAY;
|
||||
|
||||
/** Current number of elements stored in {@link #buffer}. */
|
||||
public int elementsCount;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public ByteArrayList() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public ByteArrayList(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public ByteArrayList(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
buffer = Arrays.copyOf(buffer, expectedElements);
|
||||
}
|
||||
|
||||
/** Creates a new list from the elements of another container in its iteration order. */
|
||||
public ByteArrayList(ByteContainer container) {
|
||||
this(container.size());
|
||||
addAll(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void add(byte e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends two elements at the end of the list. To add more than two elements, use <code>add
|
||||
* </code> (vararg-version) or access the buffer directly (tight loop).
|
||||
*/
|
||||
public void add(byte e1, byte e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Add all elements from a range of given array to the list. */
|
||||
public void add(byte[] elements, int start, int length) {
|
||||
assert length >= 0 : "Length must be >= 0";
|
||||
|
||||
ensureBufferSpace(length);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, length);
|
||||
elementsCount += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of the list.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void add(byte... elements) {
|
||||
add(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Adds all elements from another container. */
|
||||
public int addAll(ByteContainer container) {
|
||||
final int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (ByteCursor cursor : container) {
|
||||
add(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Adds all elements from another iterable. */
|
||||
public int addAll(Iterable<? extends ByteCursor> iterable) {
|
||||
int size = 0;
|
||||
for (ByteCursor cursor : iterable) {
|
||||
add(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void insert(int index, byte e1) {
|
||||
assert (index >= 0 && index <= size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
ensureBufferSpace(1);
|
||||
System.arraycopy(buffer, index, buffer, index + 1, elementsCount - index);
|
||||
buffer[index] = e1;
|
||||
elementsCount++;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte get(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte set(int index, byte e1) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final byte v = buffer[index];
|
||||
buffer[index] = e1;
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte removeAt(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final byte v = buffer[index];
|
||||
System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public byte removeLast() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
final byte v = buffer[--elementsCount];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void removeRange(int fromIndex, int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
|
||||
final int count = toIndex - fromIndex;
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean removeElement(byte e1) {
|
||||
return removeFirst(e1) != -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(byte e1) {
|
||||
final int index = indexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(byte e1) {
|
||||
final int index = lastIndexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(byte e1) {
|
||||
int to = 0;
|
||||
for (int from = 0; from < elementsCount; from++) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
continue;
|
||||
}
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
}
|
||||
to++;
|
||||
}
|
||||
final int deleted = elementsCount - to;
|
||||
this.elementsCount = to;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(byte e1) {
|
||||
return indexOf(e1) >= 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int indexOf(byte e1) {
|
||||
for (int i = 0; i < elementsCount; i++) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int lastIndexOf(byte e1) {
|
||||
for (int i = elementsCount - 1; i >= 0; i--) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return elementsCount == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (expectedElements > bufferLen) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (elementsCount + expectedAdditions > bufferLen) {
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions);
|
||||
assert newSize >= elementsCount + expectedAdditions
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
this.buffer = Arrays.copyOf(buffer, newSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate or expand the list to the new size. If the list is truncated, the buffer will not be
|
||||
* reallocated (use {@link #trimToSize()} if you need a truncated buffer), but the truncated
|
||||
* values will be reset to the default value (zero). If the list is expanded, the elements beyond
|
||||
* the current size are initialized with JVM-defaults (zero or <code>null</code> values).
|
||||
*/
|
||||
public void resize(int newSize) {
|
||||
if (newSize <= buffer.length) {
|
||||
if (newSize < elementsCount) {
|
||||
Arrays.fill(buffer, newSize, elementsCount, ((byte) 0));
|
||||
} else {
|
||||
Arrays.fill(buffer, elementsCount, newSize, ((byte) 0));
|
||||
}
|
||||
} else {
|
||||
ensureCapacity(newSize);
|
||||
}
|
||||
this.elementsCount = newSize;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
return elementsCount;
|
||||
}
|
||||
|
||||
/** Trim the internal buffer to the current size. */
|
||||
public void trimToSize() {
|
||||
if (size() != this.buffer.length) {
|
||||
this.buffer = toArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of stored elements to zero. Releases and initializes the internal storage array
|
||||
* to default values. To clear the list without cleaning the buffer, simply set the {@link
|
||||
* #elementsCount} field to zero.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(buffer, 0, elementsCount, ((byte) 0));
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/** Sets the number of stored elements to zero and releases the internal storage array. */
|
||||
@Override
|
||||
public void release() {
|
||||
this.buffer = EMPTY_ARRAY;
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The returned array is sized to match exactly the number of elements of the stack.
|
||||
*/
|
||||
@Override
|
||||
public byte[] toArray() {
|
||||
|
||||
return Arrays.copyOf(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public ByteIndexedContainer sort() {
|
||||
Arrays.sort(buffer, 0, elementsCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public ByteIndexedContainer reverse() {
|
||||
for (int i = 0, mid = elementsCount >> 1, j = elementsCount - 1; i < mid; i++, j--) {
|
||||
byte tmp = buffer[i];
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = tmp;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public ByteArrayList clone() {
|
||||
try {
|
||||
|
||||
final ByteArrayList cloned = (ByteArrayList) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1, max = elementsCount;
|
||||
for (int i = 0; i < max; i++) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare index-aligned elements against another {@link ByteIndexedContainer}. */
|
||||
protected boolean equalElements(ByteArrayList other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < max; i++) {
|
||||
if (!((get(i)) == (other.get(i)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ByteArrayList#iterator}. */
|
||||
static final class ValueIterator extends AbstractIterator<ByteCursor> {
|
||||
private final ByteCursor cursor;
|
||||
|
||||
private final byte[] buffer;
|
||||
private final int size;
|
||||
|
||||
public ValueIterator(byte[] buffer, int size) {
|
||||
this.cursor = new ByteCursor();
|
||||
this.cursor.index = -1;
|
||||
this.size = size;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ByteCursor fetch() {
|
||||
if (cursor.index + 1 == size) return done();
|
||||
|
||||
cursor.value = buffer[++cursor.index];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Iterator<ByteCursor> iterator() {
|
||||
return new ValueIterator(buffer, size());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends ByteProcedure> T forEach(T procedure) {
|
||||
return forEach(procedure, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public <T extends ByteProcedure> T forEach(T procedure, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(BytePredicate predicate) {
|
||||
final byte[] buffer = this.buffer;
|
||||
final int elementsCount = this.elementsCount;
|
||||
int to = 0;
|
||||
int from = 0;
|
||||
try {
|
||||
for (; from < elementsCount; from++) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = ((byte) 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
to++;
|
||||
}
|
||||
} finally {
|
||||
// Keep the list in a consistent state, even if the predicate throws an exception.
|
||||
for (; from < elementsCount; from++) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((byte) 0);
|
||||
}
|
||||
to++;
|
||||
}
|
||||
|
||||
this.elementsCount = to;
|
||||
}
|
||||
|
||||
return elementsCount - to;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends BytePredicate> T forEach(T predicate) {
|
||||
return forEach(predicate, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive, or until predicate returns <code>false</code>.
|
||||
*/
|
||||
public <T extends BytePredicate> T forEach(T predicate, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final byte[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
if (!predicate.apply(buffer[i])) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list from a variable number of arguments or an array of <code>byte</code>. The
|
||||
* elements are copied from the argument to the internal buffer.
|
||||
*/
|
||||
public static ByteArrayList from(byte... elements) {
|
||||
final ByteArrayList list = new ByteArrayList(elements.length);
|
||||
list.add(elements);
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Reused buffer visualization routines.
|
||||
*
|
||||
* @see ByteSet#visualizeKeyDistribution(int)
|
||||
* @see ByteVTypeMap#visualizeKeyDistribution(int)
|
||||
*/
|
||||
class ByteBufferVisualizer {
|
||||
static String visualizeKeyDistribution(byte[] buffer, int max, int characters) {
|
||||
final StringBuilder b = new StringBuilder();
|
||||
final char[] chars = ".123456789X".toCharArray();
|
||||
for (int i = 1, start = -1; i <= characters; i++) {
|
||||
int end = (int) ((long) i * max / characters);
|
||||
|
||||
if (start + 1 <= end) {
|
||||
int taken = 0;
|
||||
int slots = 0;
|
||||
for (int slot = start + 1; slot <= end; slot++, slots++) {
|
||||
if (!((buffer[slot]) == 0)) {
|
||||
taken++;
|
||||
}
|
||||
}
|
||||
b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
while (b.length() < characters) {
|
||||
b.append(' ');
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
|
||||
/**
|
||||
* A collection allows basic, efficient operations on sets of elements (difference and
|
||||
* intersection).
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeCollection.java")
|
||||
public interface ByteCollection extends ByteContainer {
|
||||
/**
|
||||
* Removes all occurrences of <code>e</code> from this collection.
|
||||
*
|
||||
* @param e Element to be removed from this collection, if present.
|
||||
* @return The number of removed elements as a result of this call.
|
||||
*/
|
||||
public int removeAll(byte e);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection that are present in <code>c</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(ByteLookupContainer c);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection for which the given predicate returns <code>true</code>
|
||||
* .
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(BytePredicate predicate);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection that are present in <code>c</code>. Runs in time
|
||||
* proportional to the number of elements in this collection. Equivalent of sets intersection.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(ByteLookupContainer c);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection for which the given predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(BytePredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all elements from this collection.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import com.carrotsearch.hppc.procedures.ByteProcedure;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** A generic container holding <code>byte</code>s. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeContainer.java")
|
||||
public interface ByteContainer extends Iterable<ByteCursor> {
|
||||
/**
|
||||
* Returns an iterator to a cursor traversing the collection. The order of traversal is not
|
||||
* defined. More than one cursor may be active at a time. The behavior of iterators is undefined
|
||||
* if structural changes are made to the underlying collection.
|
||||
*
|
||||
* <p>The iterator is implemented as a cursor and it returns <b>the same cursor instance</b> on
|
||||
* every call to {@link Iterator#next()} (to avoid boxing of primitive types). To read the current
|
||||
* list's value (or index in the list) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (ByteCursor<byte> c : container) {
|
||||
* System.out.println("index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<ByteCursor> iterator();
|
||||
|
||||
/**
|
||||
* Lookup a given element in the container. This operation has no speed guarantees (may be linear
|
||||
* with respect to the size of this container).
|
||||
*
|
||||
* @return Returns <code>true</code> if this container has an element equal to <code>e</code>.
|
||||
*/
|
||||
public boolean contains(byte e);
|
||||
|
||||
/**
|
||||
* Return the current number of elements in this container. The time for calculating the
|
||||
* container's size may take <code>O(n)</code> time, although implementing classes should try to
|
||||
* maintain the current size and return in constant time.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/** Shortcut for <code>size() == 0</code>. */
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Copies all elements of this container to an array.
|
||||
*
|
||||
* <p>The returned array is always a copy, regardless of the storage used by the container.
|
||||
*/
|
||||
public byte[] toArray();
|
||||
|
||||
/**
|
||||
* Applies a <code>procedure</code> to all container elements. Returns the argument (any subclass
|
||||
* of {@link ByteProcedure}. This lets the caller to call methods of the argument by chaining the
|
||||
* call (even if the argument is an anonymous type) to retrieve computed values, for example
|
||||
* (IntContainer):
|
||||
*
|
||||
* <pre>
|
||||
* int count = container.forEach(new IntProcedure() {
|
||||
* int count; // this is a field declaration in an anonymous class.
|
||||
*
|
||||
* public void apply(int value) {
|
||||
* count++;
|
||||
* }
|
||||
* }).count;
|
||||
* </pre>
|
||||
*/
|
||||
public <T extends ByteProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends BytePredicate> T forEach(T predicate);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
import com.carrotsearch.hppc.predicates.BytePredicate;
|
||||
import com.carrotsearch.hppc.procedures.ByteProcedure;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A linear collection that supports element insertion and removal at both ends.
|
||||
*
|
||||
* @see Deque
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeDeque.java")
|
||||
public interface ByteDeque extends ByteCollection {
|
||||
/**
|
||||
* Removes the first element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(byte e);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(byte e);
|
||||
|
||||
/** Inserts the specified element at the front of this deque. */
|
||||
public void addFirst(byte e);
|
||||
|
||||
/** Inserts the specified element at the end of this deque. */
|
||||
public void addLast(byte e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque.
|
||||
*
|
||||
* @return the head (first) element of this deque.
|
||||
*/
|
||||
public byte removeFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque.
|
||||
*
|
||||
* @return the tail of this deque.
|
||||
*/
|
||||
public byte removeLast();
|
||||
|
||||
/**
|
||||
* Retrieves the first element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public byte getFirst();
|
||||
|
||||
/**
|
||||
* Retrieves the last element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public byte getLast();
|
||||
|
||||
/**
|
||||
* @return An iterator over elements in this deque in tail-to-head order.
|
||||
*/
|
||||
public Iterator<ByteCursor> descendingIterator();
|
||||
|
||||
/** Applies a <code>procedure</code> to all elements in tail-to-head order. */
|
||||
public <T extends ByteProcedure> T descendingForEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends BytePredicate> T descendingForEach(T predicate);
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.RandomAccess;
|
||||
|
||||
/**
|
||||
* An indexed container provides random access to elements based on an <code>index</code>. Indexes
|
||||
* are zero-based.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeIndexedContainer.java")
|
||||
public interface ByteIndexedContainer extends ByteCollection, RandomAccess {
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning whether an element has been
|
||||
* removed.
|
||||
*/
|
||||
public boolean removeElement(byte e1);
|
||||
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(byte e1);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(byte e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int indexOf(byte e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int lastIndexOf(byte e1);
|
||||
|
||||
/** Adds an element to the end of this container (the last index is incremented by one). */
|
||||
public void add(byte e1);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the specified position in this list.
|
||||
*
|
||||
* @param index The index at which the element should be inserted, shifting any existing and
|
||||
* subsequent elements to the right.
|
||||
*/
|
||||
public void insert(int index, byte e1);
|
||||
|
||||
/**
|
||||
* Replaces the element at the specified position in this list with the specified element.
|
||||
*
|
||||
* @return Returns the previous value in the list.
|
||||
*/
|
||||
public byte set(int index, byte e1);
|
||||
|
||||
/**
|
||||
* @return Returns the element at index <code>index</code> from the list.
|
||||
*/
|
||||
public byte get(int index);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this container and returns it.
|
||||
*
|
||||
* @see #removeFirst
|
||||
* @see #removeLast
|
||||
* @see #removeAll
|
||||
*/
|
||||
public byte removeAt(int index);
|
||||
|
||||
/** Removes and returns the last element of this container. This container must not be empty. */
|
||||
public byte removeLast();
|
||||
|
||||
/**
|
||||
* Removes from this container all of the elements with indexes between <code>fromIndex</code>,
|
||||
* inclusive, and <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public void removeRange(int fromIndex, int toIndex);
|
||||
|
||||
/** Returns this container elements as a stream. */
|
||||
|
||||
/** Sorts the elements in this container and returns this container. */
|
||||
public ByteIndexedContainer sort();
|
||||
|
||||
/** Reverses the elements in this container and returns this container. */
|
||||
public ByteIndexedContainer reverse();
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Marker interface for containers that can check if they contain a given object in at least time
|
||||
* <code>O(log n)</code> and ideally in amortized constant time <code>O(1)</code>.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeLookupContainer.java")
|
||||
public interface ByteLookupContainer extends ByteContainer {
|
||||
public boolean contains(byte e);
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.ByteCursor;
|
||||
|
||||
/**
|
||||
* A subclass of {@link ByteArrayList} adding stack-related utility methods. The top of the stack is
|
||||
* at the <code>{@link #size()} - 1</code> element.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeStack.java")
|
||||
public class ByteStack extends ByteArrayList {
|
||||
/** New instance with sane defaults. */
|
||||
public ByteStack() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public ByteStack(int expectedElements) {
|
||||
super(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public ByteStack(int expectedElements, ArraySizingStrategy resizer) {
|
||||
super(expectedElements, resizer);
|
||||
}
|
||||
|
||||
/** Create a stack by pushing all elements of another container to it. */
|
||||
public ByteStack(ByteContainer container) {
|
||||
super(container);
|
||||
}
|
||||
|
||||
/** Adds one byte to the stack. */
|
||||
public void push(byte e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/** Adds two bytes to the stack. */
|
||||
public void push(byte e1, byte e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Adds three bytes to the stack. */
|
||||
public void push(byte e1, byte e2, byte e3) {
|
||||
ensureBufferSpace(3);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
}
|
||||
|
||||
/** Adds four bytes to the stack. */
|
||||
public void push(byte e1, byte e2, byte e3, byte e4) {
|
||||
ensureBufferSpace(4);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
buffer[elementsCount++] = e3;
|
||||
buffer[elementsCount++] = e4;
|
||||
}
|
||||
|
||||
/** Add a range of array elements to the stack. */
|
||||
public void push(byte[] elements, int start, int len) {
|
||||
assert start >= 0 && len >= 0;
|
||||
|
||||
ensureBufferSpace(len);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, len);
|
||||
elementsCount += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for pushing elements at the top of the stack.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void push(byte... elements) {
|
||||
push(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another container to the top of the stack. */
|
||||
public int pushAll(ByteContainer container) {
|
||||
return addAll(container);
|
||||
}
|
||||
|
||||
/** Pushes all elements from another iterable to the top of the stack. */
|
||||
public int pushAll(Iterable<? extends ByteCursor> iterable) {
|
||||
return addAll(iterable);
|
||||
}
|
||||
|
||||
/** Discard an arbitrary number of elements from the top of the stack. */
|
||||
public void discard(int count) {
|
||||
assert elementsCount >= count;
|
||||
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** Discard the top element from the stack. */
|
||||
public void discard() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
elementsCount--;
|
||||
}
|
||||
|
||||
/** Remove the top element from the stack and return it. */
|
||||
public byte pop() {
|
||||
return removeLast();
|
||||
}
|
||||
|
||||
/** Peek at the top element on the stack. */
|
||||
public byte peek() {
|
||||
assert elementsCount > 0;
|
||||
return buffer[elementsCount - 1];
|
||||
}
|
||||
|
||||
/** Create a stack by pushing a variable number of arguments to it. */
|
||||
public static ByteStack from(byte... elements) {
|
||||
final ByteStack stack = new ByteStack(elements.length);
|
||||
stack.push(elements);
|
||||
return stack;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public ByteStack clone() {
|
||||
return (ByteStack) super.clone();
|
||||
}
|
||||
}
|
@ -1,776 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCursor;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import com.carrotsearch.hppc.procedures.CharProcedure;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed {@link CharDeque}. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayDeque.java")
|
||||
public class CharArrayDeque extends AbstractCharCollection
|
||||
implements CharDeque, Preallocable, Cloneable, Accountable {
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/** Internal array for storing elements of the deque. */
|
||||
public char[] buffer = CharArrayList.EMPTY_ARRAY;
|
||||
|
||||
/**
|
||||
* The index of the element at the head of the deque or an arbitrary number equal to tail if the
|
||||
* deque is empty.
|
||||
*/
|
||||
public int head;
|
||||
|
||||
/** The index at which the next element would be added to the tail of the deque. */
|
||||
public int tail;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public CharArrayDeque() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public CharArrayDeque(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public CharArrayDeque(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
ensureCapacity(expectedElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new deque from elements of another container, appending elements at the end of the
|
||||
* deque in the iteration order.
|
||||
*/
|
||||
public CharArrayDeque(CharContainer container) {
|
||||
this(container.size());
|
||||
addLast(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addFirst(char e1) {
|
||||
int h = oneLeft(head, buffer.length);
|
||||
if (h == tail) {
|
||||
ensureBufferSpace(1);
|
||||
h = oneLeft(head, buffer.length);
|
||||
}
|
||||
buffer[head = h] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the front of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to add.
|
||||
*/
|
||||
public final void addFirst(char... elements) {
|
||||
ensureBufferSpace(elements.length);
|
||||
for (char k : elements) {
|
||||
addFirst(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the front of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(CharContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (CharCursor cursor : container) {
|
||||
addFirst(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the front of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addFirst(Iterable<? extends CharCursor> iterable) {
|
||||
int size = 0;
|
||||
for (CharCursor cursor : iterable) {
|
||||
addFirst(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void addLast(char e1) {
|
||||
int t = oneRight(tail, buffer.length);
|
||||
if (head == t) {
|
||||
ensureBufferSpace(1);
|
||||
t = oneRight(tail, buffer.length);
|
||||
}
|
||||
buffer[tail] = e1;
|
||||
tail = t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of this deque.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*
|
||||
* @param elements The elements to iterate over.
|
||||
*/
|
||||
public final void addLast(char... elements) {
|
||||
ensureBufferSpace(1);
|
||||
for (char k : elements) {
|
||||
addLast(k);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given container to the end of this deque.
|
||||
*
|
||||
* @param container The container to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(CharContainer container) {
|
||||
int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (CharCursor cursor : container) {
|
||||
addLast(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts all elements from the given iterable to the end of this deque.
|
||||
*
|
||||
* @param iterable The iterable to iterate over.
|
||||
* @return Returns the number of elements actually added as a result of this call.
|
||||
*/
|
||||
public int addLast(Iterable<? extends CharCursor> iterable) {
|
||||
int size = 0;
|
||||
for (CharCursor cursor : iterable) {
|
||||
addLast(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char removeFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
final char result = buffer[head];
|
||||
buffer[head] = ((char) 0);
|
||||
head = oneRight(head, buffer.length);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char removeLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
tail = oneLeft(tail, buffer.length);
|
||||
final char result = buffer[tail];
|
||||
buffer[tail] = ((char) 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char getFirst() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[head];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char getLast() {
|
||||
assert size() > 0 : "The deque is empty.";
|
||||
|
||||
return buffer[oneLeft(tail, buffer.length)];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(char e1) {
|
||||
final int index = bufferIndexOf(e1);
|
||||
if (index >= 0) removeAtBufferIndex(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the first (counting from head) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int bufferIndexOf(char e1) {
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
for (int i = head; i != last; i = oneRight(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(char e1) {
|
||||
final int index = lastBufferIndexOf(e1);
|
||||
if (index >= 0) {
|
||||
removeAtBufferIndex(index);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the index of the last (counting from tail) element equal to <code>e1</code>. The index
|
||||
* points to the {@link #buffer} array.
|
||||
*
|
||||
* @param e1 The element to look for.
|
||||
* @return Returns the index of the first element equal to <code>e1</code> or <code>-1</code> if
|
||||
* not found.
|
||||
*/
|
||||
public int lastBufferIndexOf(char e1) {
|
||||
final int bufLen = buffer.length;
|
||||
final int last = oneLeft(head, bufLen);
|
||||
for (int i = oneLeft(tail, bufLen); i != last; i = oneLeft(i, bufLen)) {
|
||||
if (((e1) == (buffer[i]))) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(char e1) {
|
||||
int removed = 0;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int from, to;
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
buffer[from] = ((char) 0);
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
|
||||
tail = to;
|
||||
return removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the element at <code>index</code> in the internal {#link {@link #buffer} array,
|
||||
* returning its value.
|
||||
*
|
||||
* @param index Index of the element to remove. The index must be located between {@link #head}
|
||||
* and {@link #tail} in modulo {@link #buffer} arithmetic.
|
||||
*/
|
||||
public void removeAtBufferIndex(int index) {
|
||||
assert (head <= tail ? index >= head && index < tail : index >= head || index < tail)
|
||||
: "Index out of range (head=" + head + ", tail=" + tail + ", index=" + index + ").";
|
||||
|
||||
// Cache fields in locals (hopefully moved to registers).
|
||||
final char[] buffer = this.buffer;
|
||||
final int bufLen = buffer.length;
|
||||
final int lastIndex = bufLen - 1;
|
||||
final int head = this.head;
|
||||
final int tail = this.tail;
|
||||
|
||||
final int leftChunk = Math.abs(index - head) % bufLen;
|
||||
final int rightChunk = Math.abs(tail - index) % bufLen;
|
||||
|
||||
if (leftChunk < rightChunk) {
|
||||
if (index >= head) {
|
||||
System.arraycopy(buffer, head, buffer, head + 1, leftChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, 0, buffer, 1, index);
|
||||
buffer[0] = buffer[lastIndex];
|
||||
System.arraycopy(buffer, head, buffer, head + 1, lastIndex - head);
|
||||
}
|
||||
buffer[head] = ((char) 0);
|
||||
this.head = oneRight(head, bufLen);
|
||||
} else {
|
||||
if (index < tail) {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, rightChunk);
|
||||
} else {
|
||||
System.arraycopy(buffer, index + 1, buffer, index, lastIndex - index);
|
||||
buffer[lastIndex] = buffer[0];
|
||||
System.arraycopy(buffer, 1, buffer, 0, tail);
|
||||
}
|
||||
buffer[tail] = ((char) 0);
|
||||
this.tail = oneLeft(tail, bufLen);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
if (head <= tail) return tail - head;
|
||||
else return (tail - head + buffer.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The internal array buffers are not released as a result of this call.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
if (head < tail) {
|
||||
Arrays.fill(buffer, head, tail, ((char) 0));
|
||||
} else {
|
||||
Arrays.fill(buffer, 0, tail, ((char) 0));
|
||||
Arrays.fill(buffer, head, buffer.length, ((char) 0));
|
||||
}
|
||||
this.head = tail = 0;
|
||||
}
|
||||
|
||||
/** Release internal buffers of this deque and reallocate with the default buffer. */
|
||||
public void release() {
|
||||
this.head = tail = 0;
|
||||
buffer = CharArrayList.EMPTY_ARRAY;
|
||||
ensureBufferSpace(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = buffer.length;
|
||||
final int elementsCount = size();
|
||||
|
||||
if (elementsCount + expectedAdditions >= bufferLen) {
|
||||
final int emptySlot = 1; // deque invariant: always an empty slot.
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount + emptySlot, expectedAdditions);
|
||||
assert newSize >= (elementsCount + expectedAdditions + emptySlot)
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
try {
|
||||
final char[] newBuffer = (new char[newSize]);
|
||||
if (bufferLen > 0) {
|
||||
toArray(newBuffer);
|
||||
tail = elementsCount;
|
||||
head = 0;
|
||||
}
|
||||
this.buffer = newBuffer;
|
||||
} catch (OutOfMemoryError e) {
|
||||
throw new BufferAllocationException(
|
||||
"Not enough memory to allocate new buffers: %,d -> %,d", e, bufferLen, newSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char[] toArray() {
|
||||
|
||||
final int size = size();
|
||||
return toArray((new char[size]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies elements of this deque to an array. The content of the <code>target</code> array is
|
||||
* filled from index 0 (head of the queue) to index <code>size() - 1</code> (tail of the queue).
|
||||
*
|
||||
* @param target The target array must be large enough to hold all elements.
|
||||
* @return Returns the target argument for chaining.
|
||||
*/
|
||||
public char[] toArray(char[] target) {
|
||||
assert target.length >= size() : "Target array must be >= " + size();
|
||||
|
||||
if (head < tail) {
|
||||
// The contents is not wrapped around. Just copy.
|
||||
System.arraycopy(buffer, head, target, 0, size());
|
||||
} else if (head > tail) {
|
||||
// The contents is split. Merge elements from the following indexes:
|
||||
// [head...buffer.length - 1][0, tail - 1]
|
||||
final int rightCount = buffer.length - head;
|
||||
System.arraycopy(buffer, head, target, 0, rightCount);
|
||||
System.arraycopy(buffer, 0, target, rightCount, tail);
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public CharArrayDeque clone() {
|
||||
try {
|
||||
|
||||
CharArrayDeque cloned = (CharArrayDeque) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Move one index to the left, wrapping around buffer. */
|
||||
protected static int oneLeft(int index, int modulus) {
|
||||
if (index >= 1) {
|
||||
return index - 1;
|
||||
}
|
||||
return modulus - 1;
|
||||
}
|
||||
|
||||
/** Move one index to the right, wrapping around buffer. */
|
||||
protected static int oneRight(int index, int modulus) {
|
||||
if (index + 1 == modulus) {
|
||||
return 0;
|
||||
}
|
||||
return index + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: head, tail
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES * 2
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, size());
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#iterator}. */
|
||||
private final class ValueIterator extends AbstractIterator<CharCursor> {
|
||||
private final CharCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public ValueIterator() {
|
||||
cursor = new CharCursor();
|
||||
cursor.index = oneLeft(head, buffer.length);
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharCursor fetch() {
|
||||
if (remaining == 0) {
|
||||
return done();
|
||||
}
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneRight(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link ObjectArrayDeque#descendingIterator()}. */
|
||||
private final class DescendingValueIterator extends AbstractIterator<CharCursor> {
|
||||
private final CharCursor cursor;
|
||||
private int remaining;
|
||||
|
||||
public DescendingValueIterator() {
|
||||
cursor = new CharCursor();
|
||||
cursor.index = tail;
|
||||
this.remaining = size();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharCursor fetch() {
|
||||
if (remaining == 0) return done();
|
||||
|
||||
remaining--;
|
||||
cursor.value = buffer[cursor.index = oneLeft(cursor.index, buffer.length)];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in head to tail order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntValueCursor c : intDeque) {
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<CharCursor> iterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a cursor over the values of this deque (in tail to head order). The iterator is
|
||||
* implemented as a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()} (to avoid boxing of primitive types). To read the current value (or index in
|
||||
* the deque's buffer) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (Iterator<IntCursor> i = intDeque.descendingIterator(); i.hasNext();) {
|
||||
* final IntCursor c = i.next();
|
||||
* System.out.println("buffer index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<CharCursor> descendingIterator() {
|
||||
return new DescendingValueIterator();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharProcedure> T forEach(T procedure) {
|
||||
forEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
private void forEach(CharProcedure procedure, int fromIndex, final int toIndex) {
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharPredicate> T forEach(T predicate) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/** Applies <code>procedure</code> to all elements of this deque, tail to head. */
|
||||
@Override
|
||||
public <T extends CharProcedure> T descendingForEach(T procedure) {
|
||||
descendingForEach(procedure, head, tail);
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive.
|
||||
*/
|
||||
private void descendingForEach(CharProcedure procedure, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
procedure.apply(buffer[i]);
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharPredicate> T descendingForEach(T predicate) {
|
||||
descendingForEach(predicate, head, tail);
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the deque, <code>toIndex</code>, exclusive, down
|
||||
* to <code>fromIndex</code>, inclusive or until the predicate returns <code>false</code>.
|
||||
*/
|
||||
private void descendingForEach(CharPredicate predicate, int fromIndex, final int toIndex) {
|
||||
if (fromIndex == toIndex) return;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
int i = toIndex;
|
||||
do {
|
||||
i = oneLeft(i, buffer.length);
|
||||
if (!predicate.apply(buffer[i])) {
|
||||
break;
|
||||
}
|
||||
} while (i != fromIndex);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(CharPredicate predicate) {
|
||||
final char[] buffer = this.buffer;
|
||||
final int last = tail;
|
||||
final int bufLen = buffer.length;
|
||||
int removed = 0;
|
||||
int from, to;
|
||||
from = to = head;
|
||||
try {
|
||||
for (from = to = head; from != last; from = oneRight(from, bufLen)) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = ((char) 0);
|
||||
removed++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
} finally {
|
||||
// Keep the deque in consistent state even if the predicate throws an exception.
|
||||
for (; from != last; from = oneRight(from, bufLen)) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
|
||||
to = oneRight(to, bufLen);
|
||||
}
|
||||
tail = to;
|
||||
}
|
||||
|
||||
return removed;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(char e) {
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
if (((e) == (buffer[i]))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1;
|
||||
int fromIndex = head;
|
||||
int toIndex = tail;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i != toIndex; i = oneRight(i, buffer.length)) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare order-aligned elements against another {@link CharDeque}. */
|
||||
protected boolean equalElements(CharArrayDeque other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<CharCursor> i1 = this.iterator();
|
||||
Iterator<? extends CharCursor> i2 = other.iterator();
|
||||
|
||||
while (i1.hasNext() && i2.hasNext()) {
|
||||
if (!((i1.next().value) == (i2.next().value))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return !i1.hasNext() && !i2.hasNext();
|
||||
}
|
||||
|
||||
/** Create a new deque by pushing a variable number of arguments to the end of it. */
|
||||
public static CharArrayDeque from(char... elements) {
|
||||
final CharArrayDeque coll = new CharArrayDeque(elements.length);
|
||||
coll.addLast(elements);
|
||||
return coll;
|
||||
}
|
||||
}
|
@ -1,579 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.*;
|
||||
|
||||
/** An array-backed list of chars. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeArrayList.java")
|
||||
public class CharArrayList extends AbstractCharCollection
|
||||
implements CharIndexedContainer, Preallocable, Cloneable, Accountable {
|
||||
/** An immutable empty buffer (array). */
|
||||
public static final char[] EMPTY_ARRAY = new char[0];
|
||||
|
||||
;
|
||||
|
||||
/** Reuse the same strategy instance. */
|
||||
private static final BoundedProportionalArraySizingStrategy DEFAULT_SIZING_STRATEGY =
|
||||
BoundedProportionalArraySizingStrategy.DEFAULT_INSTANCE;
|
||||
|
||||
/**
|
||||
* Internal array for storing the list. The array may be larger than the current size ({@link
|
||||
* #size()}).
|
||||
*/
|
||||
public char[] buffer = EMPTY_ARRAY;
|
||||
|
||||
/** Current number of elements stored in {@link #buffer}. */
|
||||
public int elementsCount;
|
||||
|
||||
/** Buffer resizing strategy. */
|
||||
protected final ArraySizingStrategy resizer;
|
||||
|
||||
/** New instance with sane defaults. */
|
||||
public CharArrayList() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
*/
|
||||
public CharArrayList(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_SIZING_STRATEGY);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause buffer
|
||||
* expansion (inclusive).
|
||||
* @param resizer Underlying buffer sizing strategy.
|
||||
*/
|
||||
public CharArrayList(int expectedElements, ArraySizingStrategy resizer) {
|
||||
assert resizer != null;
|
||||
this.resizer = resizer;
|
||||
buffer = Arrays.copyOf(buffer, expectedElements);
|
||||
}
|
||||
|
||||
/** Creates a new list from the elements of another container in its iteration order. */
|
||||
public CharArrayList(CharContainer container) {
|
||||
this(container.size());
|
||||
addAll(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void add(char e1) {
|
||||
ensureBufferSpace(1);
|
||||
buffer[elementsCount++] = e1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends two elements at the end of the list. To add more than two elements, use <code>add
|
||||
* </code> (vararg-version) or access the buffer directly (tight loop).
|
||||
*/
|
||||
public void add(char e1, char e2) {
|
||||
ensureBufferSpace(2);
|
||||
buffer[elementsCount++] = e1;
|
||||
buffer[elementsCount++] = e2;
|
||||
}
|
||||
|
||||
/** Add all elements from a range of given array to the list. */
|
||||
public void add(char[] elements, int start, int length) {
|
||||
assert length >= 0 : "Length must be >= 0";
|
||||
|
||||
ensureBufferSpace(length);
|
||||
System.arraycopy(elements, start, buffer, elementsCount, length);
|
||||
elementsCount += length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vararg-signature method for adding elements at the end of the list.
|
||||
*
|
||||
* <p><b>This method is handy, but costly if used in tight loops (anonymous array passing)</b>
|
||||
*/
|
||||
public final void add(char... elements) {
|
||||
add(elements, 0, elements.length);
|
||||
}
|
||||
|
||||
/** Adds all elements from another container. */
|
||||
public int addAll(CharContainer container) {
|
||||
final int size = container.size();
|
||||
ensureBufferSpace(size);
|
||||
|
||||
for (CharCursor cursor : container) {
|
||||
add(cursor.value);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/** Adds all elements from another iterable. */
|
||||
public int addAll(Iterable<? extends CharCursor> iterable) {
|
||||
int size = 0;
|
||||
for (CharCursor cursor : iterable) {
|
||||
add(cursor.value);
|
||||
size++;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void insert(int index, char e1) {
|
||||
assert (index >= 0 && index <= size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
ensureBufferSpace(1);
|
||||
System.arraycopy(buffer, index, buffer, index + 1, elementsCount - index);
|
||||
buffer[index] = e1;
|
||||
elementsCount++;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char get(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char set(int index, char e1) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final char v = buffer[index];
|
||||
buffer[index] = e1;
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char removeAt(int index) {
|
||||
assert (index >= 0 && index < size())
|
||||
: "Index " + index + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
final char v = buffer[index];
|
||||
System.arraycopy(buffer, index + 1, buffer, index, --elementsCount - index);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char removeLast() {
|
||||
assert elementsCount > 0;
|
||||
|
||||
final char v = buffer[--elementsCount];
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void removeRange(int fromIndex, int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
System.arraycopy(buffer, toIndex, buffer, fromIndex, elementsCount - toIndex);
|
||||
final int count = toIndex - fromIndex;
|
||||
elementsCount -= count;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean removeElement(char e1) {
|
||||
return removeFirst(e1) != -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeFirst(char e1) {
|
||||
final int index = indexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeLast(char e1) {
|
||||
final int index = lastIndexOf(e1);
|
||||
if (index >= 0) removeAt(index);
|
||||
return index;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(char e1) {
|
||||
int to = 0;
|
||||
for (int from = 0; from < elementsCount; from++) {
|
||||
if (((e1) == (buffer[from]))) {
|
||||
continue;
|
||||
}
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
}
|
||||
to++;
|
||||
}
|
||||
final int deleted = elementsCount - to;
|
||||
this.elementsCount = to;
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(char e1) {
|
||||
return indexOf(e1) >= 0;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int indexOf(char e1) {
|
||||
for (int i = 0; i < elementsCount; i++) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int lastIndexOf(char e1) {
|
||||
for (int i = elementsCount - 1; i >= 0; i--) {
|
||||
if (((e1) == (buffer[i]))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return elementsCount == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (expectedElements > bufferLen) {
|
||||
ensureBufferSpace(expectedElements - size());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensures the internal buffer has enough free slots to store <code>expectedAdditions</code>.
|
||||
* Increases internal buffer size if needed.
|
||||
*/
|
||||
protected void ensureBufferSpace(int expectedAdditions) {
|
||||
final int bufferLen = (buffer == null ? 0 : buffer.length);
|
||||
if (elementsCount + expectedAdditions > bufferLen) {
|
||||
final int newSize = resizer.grow(bufferLen, elementsCount, expectedAdditions);
|
||||
assert newSize >= elementsCount + expectedAdditions
|
||||
: "Resizer failed to"
|
||||
+ " return sensible new size: "
|
||||
+ newSize
|
||||
+ " <= "
|
||||
+ (elementsCount + expectedAdditions);
|
||||
|
||||
this.buffer = Arrays.copyOf(buffer, newSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate or expand the list to the new size. If the list is truncated, the buffer will not be
|
||||
* reallocated (use {@link #trimToSize()} if you need a truncated buffer), but the truncated
|
||||
* values will be reset to the default value (zero). If the list is expanded, the elements beyond
|
||||
* the current size are initialized with JVM-defaults (zero or <code>null</code> values).
|
||||
*/
|
||||
public void resize(int newSize) {
|
||||
if (newSize <= buffer.length) {
|
||||
if (newSize < elementsCount) {
|
||||
Arrays.fill(buffer, newSize, elementsCount, ((char) 0));
|
||||
} else {
|
||||
Arrays.fill(buffer, elementsCount, newSize, ((char) 0));
|
||||
}
|
||||
} else {
|
||||
ensureCapacity(newSize);
|
||||
}
|
||||
this.elementsCount = newSize;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
return elementsCount;
|
||||
}
|
||||
|
||||
/** Trim the internal buffer to the current size. */
|
||||
public void trimToSize() {
|
||||
if (size() != this.buffer.length) {
|
||||
this.buffer = toArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of stored elements to zero. Releases and initializes the internal storage array
|
||||
* to default values. To clear the list without cleaning the buffer, simply set the {@link
|
||||
* #elementsCount} field to zero.
|
||||
*/
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(buffer, 0, elementsCount, ((char) 0));
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/** Sets the number of stored elements to zero and releases the internal storage array. */
|
||||
@Override
|
||||
public void release() {
|
||||
this.buffer = EMPTY_ARRAY;
|
||||
this.elementsCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The returned array is sized to match exactly the number of elements of the stack.
|
||||
*/
|
||||
@Override
|
||||
public char[] toArray() {
|
||||
|
||||
return Arrays.copyOf(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public CharIndexedContainer sort() {
|
||||
Arrays.sort(buffer, 0, elementsCount);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public CharIndexedContainer reverse() {
|
||||
for (int i = 0, mid = elementsCount >> 1, j = elementsCount - 1; i < mid; i++, j--) {
|
||||
char tmp = buffer[i];
|
||||
buffer[i] = buffer[j];
|
||||
buffer[j] = tmp;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this object. The returned clone will reuse the same hash function and array resizing
|
||||
* strategy.
|
||||
*/
|
||||
@Override
|
||||
public CharArrayList clone() {
|
||||
try {
|
||||
|
||||
final CharArrayList cloned = (CharArrayList) super.clone();
|
||||
cloned.buffer = buffer.clone();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = 1, max = elementsCount;
|
||||
for (int i = 0; i < max; i++) {
|
||||
h = 31 * h + BitMixer.mix(this.buffer[i]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> only if the other object is an instance of the same class and with
|
||||
* the same elements.
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && equalElements(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Compare index-aligned elements against another {@link CharIndexedContainer}. */
|
||||
protected boolean equalElements(CharArrayList other) {
|
||||
int max = size();
|
||||
if (other.size() != max) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < max; i++) {
|
||||
if (!((get(i)) == (other.get(i)))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesAllocated()
|
||||
+ RamUsageEstimator.shallowSizeOfArray(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: elementsCount
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ Integer.BYTES
|
||||
+ resizer.ramBytesUsed()
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(buffer, elementsCount);
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link CharArrayList#iterator}. */
|
||||
static final class ValueIterator extends AbstractIterator<CharCursor> {
|
||||
private final CharCursor cursor;
|
||||
|
||||
private final char[] buffer;
|
||||
private final int size;
|
||||
|
||||
public ValueIterator(char[] buffer, int size) {
|
||||
this.cursor = new CharCursor();
|
||||
this.cursor.index = -1;
|
||||
this.size = size;
|
||||
this.buffer = buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharCursor fetch() {
|
||||
if (cursor.index + 1 == size) return done();
|
||||
|
||||
cursor.value = buffer[++cursor.index];
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Iterator<CharCursor> iterator() {
|
||||
return new ValueIterator(buffer, size());
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharProcedure> T forEach(T procedure) {
|
||||
return forEach(procedure, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>procedure</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public <T extends CharProcedure> T forEach(T procedure, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
procedure.apply(buffer[i]);
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(CharPredicate predicate) {
|
||||
final char[] buffer = this.buffer;
|
||||
final int elementsCount = this.elementsCount;
|
||||
int to = 0;
|
||||
int from = 0;
|
||||
try {
|
||||
for (; from < elementsCount; from++) {
|
||||
if (predicate.apply(buffer[from])) {
|
||||
buffer[from] = ((char) 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
to++;
|
||||
}
|
||||
} finally {
|
||||
// Keep the list in a consistent state, even if the predicate throws an exception.
|
||||
for (; from < elementsCount; from++) {
|
||||
if (to != from) {
|
||||
buffer[to] = buffer[from];
|
||||
buffer[from] = ((char) 0);
|
||||
}
|
||||
to++;
|
||||
}
|
||||
|
||||
this.elementsCount = to;
|
||||
}
|
||||
|
||||
return elementsCount - to;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharPredicate> T forEach(T predicate) {
|
||||
return forEach(predicate, 0, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies <code>predicate</code> to a slice of the list, <code>fromIndex</code>, inclusive, to
|
||||
* <code>toIndex</code>, exclusive, or until predicate returns <code>false</code>.
|
||||
*/
|
||||
public <T extends CharPredicate> T forEach(T predicate, int fromIndex, final int toIndex) {
|
||||
assert (fromIndex >= 0 && fromIndex <= size())
|
||||
: "Index " + fromIndex + " out of bounds [" + 0 + ", " + size() + ").";
|
||||
assert (toIndex >= 0 && toIndex <= size())
|
||||
: "Index " + toIndex + " out of bounds [" + 0 + ", " + size() + "].";
|
||||
assert fromIndex <= toIndex : "fromIndex must be <= toIndex: " + fromIndex + ", " + toIndex;
|
||||
|
||||
final char[] buffer = this.buffer;
|
||||
for (int i = fromIndex; i < toIndex; i++) {
|
||||
if (!predicate.apply(buffer[i])) break;
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a list from a variable number of arguments or an array of <code>char</code>. The
|
||||
* elements are copied from the argument to the internal buffer.
|
||||
*/
|
||||
public static CharArrayList from(char... elements) {
|
||||
final CharArrayList list = new CharArrayList(elements.length);
|
||||
list.add(elements);
|
||||
return list;
|
||||
}
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Reused buffer visualization routines.
|
||||
*
|
||||
* @see CharSet#visualizeKeyDistribution(int)
|
||||
* @see CharVTypeMap#visualizeKeyDistribution(int)
|
||||
*/
|
||||
class CharBufferVisualizer {
|
||||
static String visualizeKeyDistribution(char[] buffer, int max, int characters) {
|
||||
final StringBuilder b = new StringBuilder();
|
||||
final char[] chars = ".123456789X".toCharArray();
|
||||
for (int i = 1, start = -1; i <= characters; i++) {
|
||||
int end = (int) ((long) i * max / characters);
|
||||
|
||||
if (start + 1 <= end) {
|
||||
int taken = 0;
|
||||
int slots = 0;
|
||||
for (int slot = start + 1; slot <= end; slot++, slots++) {
|
||||
if (!((buffer[slot]) == 0)) {
|
||||
taken++;
|
||||
}
|
||||
}
|
||||
b.append(chars[Math.min(chars.length - 1, taken * chars.length / slots)]);
|
||||
start = end;
|
||||
}
|
||||
}
|
||||
while (b.length() < characters) {
|
||||
b.append(' ');
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharByteAssociativeContainer extends Iterable<CharByteCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharByteCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharBytePredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharByteProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharByteProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharBytePredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharBytePredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public ByteContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharByteCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharByteMap extends CharByteAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public byte get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public byte getOrDefault(char key, byte defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public byte put(char key, byte value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, byte value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharByteAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharByteCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public byte putOrAdd(char key, byte putValue, byte incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public byte addTo(char key, byte additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public byte remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharByteMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public byte indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public byte indexReplace(int index, byte newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, byte value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public byte indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharCharAssociativeContainer extends Iterable<CharCharCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharCharCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharCharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharCharProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharCharProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharCharPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharCharPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public CharContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCharCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharCharMap extends CharCharAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public char get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public char getOrDefault(char key, char defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public char put(char key, char value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, char value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharCharAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharCharCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public char putOrAdd(char key, char putValue, char incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public char addTo(char key, char additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public char remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharCharMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexReplace(int index, char newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, char value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
|
||||
/**
|
||||
* A collection allows basic, efficient operations on sets of elements (difference and
|
||||
* intersection).
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeCollection.java")
|
||||
public interface CharCollection extends CharContainer {
|
||||
/**
|
||||
* Removes all occurrences of <code>e</code> from this collection.
|
||||
*
|
||||
* @param e Element to be removed from this collection, if present.
|
||||
* @return The number of removed elements as a result of this call.
|
||||
*/
|
||||
public int removeAll(char e);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection that are present in <code>c</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(CharLookupContainer c);
|
||||
|
||||
/**
|
||||
* Removes all elements in this collection for which the given predicate returns <code>true</code>
|
||||
* .
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection that are present in <code>c</code>. Runs in time
|
||||
* proportional to the number of elements in this collection. Equivalent of sets intersection.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(CharLookupContainer c);
|
||||
|
||||
/**
|
||||
* Keeps all elements in this collection for which the given predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of removed elements.
|
||||
*/
|
||||
public int retainAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all elements from this collection.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
}
|
@ -1,76 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCursor;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import com.carrotsearch.hppc.procedures.CharProcedure;
|
||||
import java.util.Iterator;
|
||||
|
||||
/** A generic container holding <code>char</code>s. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeContainer.java")
|
||||
public interface CharContainer extends Iterable<CharCursor> {
|
||||
/**
|
||||
* Returns an iterator to a cursor traversing the collection. The order of traversal is not
|
||||
* defined. More than one cursor may be active at a time. The behavior of iterators is undefined
|
||||
* if structural changes are made to the underlying collection.
|
||||
*
|
||||
* <p>The iterator is implemented as a cursor and it returns <b>the same cursor instance</b> on
|
||||
* every call to {@link Iterator#next()} (to avoid boxing of primitive types). To read the current
|
||||
* list's value (or index in the list) use the cursor's public fields. An example is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (CharCursor<char> c : container) {
|
||||
* System.out.println("index=" + c.index + " value=" + c.value);
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
public Iterator<CharCursor> iterator();
|
||||
|
||||
/**
|
||||
* Lookup a given element in the container. This operation has no speed guarantees (may be linear
|
||||
* with respect to the size of this container).
|
||||
*
|
||||
* @return Returns <code>true</code> if this container has an element equal to <code>e</code>.
|
||||
*/
|
||||
public boolean contains(char e);
|
||||
|
||||
/**
|
||||
* Return the current number of elements in this container. The time for calculating the
|
||||
* container's size may take <code>O(n)</code> time, although implementing classes should try to
|
||||
* maintain the current size and return in constant time.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/** Shortcut for <code>size() == 0</code>. */
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Copies all elements of this container to an array.
|
||||
*
|
||||
* <p>The returned array is always a copy, regardless of the storage used by the container.
|
||||
*/
|
||||
public char[] toArray();
|
||||
|
||||
/**
|
||||
* Applies a <code>procedure</code> to all container elements. Returns the argument (any subclass
|
||||
* of {@link CharProcedure}. This lets the caller to call methods of the argument by chaining the
|
||||
* call (even if the argument is an anonymous type) to retrieve computed values, for example
|
||||
* (IntContainer):
|
||||
*
|
||||
* <pre>
|
||||
* int count = container.forEach(new IntProcedure() {
|
||||
* int count; // this is a field declaration in an anonymous class.
|
||||
*
|
||||
* public void apply(int value) {
|
||||
* count++;
|
||||
* }
|
||||
* }).count;
|
||||
* </pre>
|
||||
*/
|
||||
public <T extends CharProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends CharPredicate> T forEach(T predicate);
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharCursor;
|
||||
import com.carrotsearch.hppc.predicates.CharPredicate;
|
||||
import com.carrotsearch.hppc.procedures.CharProcedure;
|
||||
import java.util.Deque;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A linear collection that supports element insertion and removal at both ends.
|
||||
*
|
||||
* @see Deque
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeDeque.java")
|
||||
public interface CharDeque extends CharCollection {
|
||||
/**
|
||||
* Removes the first element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(char e);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e</code>.
|
||||
*
|
||||
* @return The deleted element's index or <code>-1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(char e);
|
||||
|
||||
/** Inserts the specified element at the front of this deque. */
|
||||
public void addFirst(char e);
|
||||
|
||||
/** Inserts the specified element at the end of this deque. */
|
||||
public void addLast(char e);
|
||||
|
||||
/**
|
||||
* Retrieves and removes the first element of this deque.
|
||||
*
|
||||
* @return the head (first) element of this deque.
|
||||
*/
|
||||
public char removeFirst();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the last element of this deque.
|
||||
*
|
||||
* @return the tail of this deque.
|
||||
*/
|
||||
public char removeLast();
|
||||
|
||||
/**
|
||||
* Retrieves the first element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public char getFirst();
|
||||
|
||||
/**
|
||||
* Retrieves the last element of this deque but does not remove it.
|
||||
*
|
||||
* @return the head of this deque.
|
||||
*/
|
||||
public char getLast();
|
||||
|
||||
/**
|
||||
* @return An iterator over elements in this deque in tail-to-head order.
|
||||
*/
|
||||
public Iterator<CharCursor> descendingIterator();
|
||||
|
||||
/** Applies a <code>procedure</code> to all elements in tail-to-head order. */
|
||||
public <T extends CharProcedure> T descendingForEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a <code>predicate</code> to container elements as long, as the predicate returns <code>
|
||||
* true</code>. The iteration is interrupted otherwise.
|
||||
*/
|
||||
public <T extends CharPredicate> T descendingForEach(T predicate);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharDoubleAssociativeContainer extends Iterable<CharDoubleCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharDoubleCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharDoublePredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharDoubleProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharDoubleProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharDoublePredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharDoublePredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public DoubleContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharDoubleCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharDoubleMap extends CharDoubleAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public double get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public double getOrDefault(char key, double defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public double put(char key, double value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, double value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharDoubleAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharDoubleCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public double putOrAdd(char key, double putValue, double incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public double addTo(char key, double additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public double remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharDoubleMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public double indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public double indexReplace(int index, double newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, double value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public double indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharFloatAssociativeContainer extends Iterable<CharFloatCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharFloatCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharFloatPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharFloatProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharFloatProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharFloatPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharFloatPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public FloatContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharFloatCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharFloatMap extends CharFloatAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public float get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public float getOrDefault(char key, float defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public float put(char key, float value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, float value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharFloatAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharFloatCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public float putOrAdd(char key, float putValue, float incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public float addTo(char key, float additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public float remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharFloatMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public float indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public float indexReplace(int index, float newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, float value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public float indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,787 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import static com.carrotsearch.hppc.Containers.*;
|
||||
import static com.carrotsearch.hppc.HashContainers.*;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A hash set of <code>char</code>s, implemented using open addressing with linear probing for
|
||||
* collision resolution.
|
||||
*
|
||||
* @see <a href="{@docRoot}/overview-summary.html#interfaces">HPPC interfaces diagram</a>
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:16+0200", value = "KTypeHashSet.java")
|
||||
public class CharHashSet extends AbstractCharCollection
|
||||
implements CharLookupContainer, CharSet, Preallocable, Cloneable, Accountable {
|
||||
/** The hash array holding keys. */
|
||||
public char[] keys;
|
||||
|
||||
/**
|
||||
* The number of stored keys (assigned key slots), excluding the special "empty" key, if any.
|
||||
*
|
||||
* @see #size()
|
||||
* @see #hasEmptyKey
|
||||
*/
|
||||
protected int assigned;
|
||||
|
||||
/** Mask for slot scans in {@link #keys}. */
|
||||
protected int mask;
|
||||
|
||||
/** Expand (rehash) {@link #keys} when {@link #assigned} hits this value. */
|
||||
protected int resizeAt;
|
||||
|
||||
/** Special treatment for the "empty slot" key marker. */
|
||||
protected boolean hasEmptyKey;
|
||||
|
||||
/** The load factor for {@link #keys}. */
|
||||
protected double loadFactor;
|
||||
|
||||
/** Seed used to ensure the hash iteration order is different from an iteration to another. */
|
||||
protected int iterationSeed;
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @see #CharHashSet(int, double)
|
||||
*/
|
||||
public CharHashSet() {
|
||||
this(DEFAULT_EXPECTED_ELEMENTS, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with sane defaults.
|
||||
*
|
||||
* @see #CharHashSet(int, double)
|
||||
*/
|
||||
public CharHashSet(int expectedElements) {
|
||||
this(expectedElements, DEFAULT_LOAD_FACTOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* New instance with the provided defaults.
|
||||
*
|
||||
* @param expectedElements The expected number of elements guaranteed not to cause a rehash
|
||||
* (inclusive).
|
||||
* @param loadFactor The load factor for internal buffers. Insane load factors (zero, full
|
||||
* capacity) are rejected by {@link #verifyLoadFactor(double)}.
|
||||
*/
|
||||
public CharHashSet(int expectedElements, double loadFactor) {
|
||||
this.loadFactor = verifyLoadFactor(loadFactor);
|
||||
iterationSeed = HashContainers.nextIterationSeed();
|
||||
ensureCapacity(expectedElements);
|
||||
}
|
||||
|
||||
/** New instance copying elements from another {@link CharContainer}. */
|
||||
public CharHashSet(CharContainer container) {
|
||||
this(container.size());
|
||||
addAll(container);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean add(char key) {
|
||||
if (((key) == 0)) {
|
||||
assert ((keys[mask + 1]) == 0);
|
||||
boolean added = !hasEmptyKey;
|
||||
hasEmptyKey = true;
|
||||
return added;
|
||||
} else {
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
int slot = hashKey(key) & mask;
|
||||
|
||||
char existing;
|
||||
while (!((existing = keys[slot]) == 0)) {
|
||||
if (((key) == (existing))) {
|
||||
return false;
|
||||
}
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
|
||||
if (assigned == resizeAt) {
|
||||
allocateThenInsertThenRehash(slot, key);
|
||||
} else {
|
||||
keys[slot] = key;
|
||||
}
|
||||
|
||||
assigned++;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements from the given list (vararg) to this set.
|
||||
*
|
||||
* @return Returns the number of elements actually added as a result of this call (not previously
|
||||
* present in the set).
|
||||
*/
|
||||
public final int addAll(char... elements) {
|
||||
ensureCapacity(elements.length);
|
||||
int count = 0;
|
||||
for (char e : elements) {
|
||||
if (add(e)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements from the given {@link CharContainer} to this set.
|
||||
*
|
||||
* @return Returns the number of elements actually added as a result of this call (not previously
|
||||
* present in the set).
|
||||
*/
|
||||
public int addAll(CharContainer container) {
|
||||
ensureCapacity(container.size());
|
||||
return addAll((Iterable<? extends CharCursor>) container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all elements from the given iterable to this set.
|
||||
*
|
||||
* @return Returns the number of elements actually added as a result of this call (not previously
|
||||
* present in the set).
|
||||
*/
|
||||
public int addAll(Iterable<? extends CharCursor> iterable) {
|
||||
int count = 0;
|
||||
for (CharCursor cursor : iterable) {
|
||||
if (add(cursor.value)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public char[] toArray() {
|
||||
|
||||
final char[] cloned = (new char[size()]);
|
||||
int j = 0;
|
||||
if (hasEmptyKey) {
|
||||
cloned[j++] = ((char) 0);
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
int seed = nextIterationSeed();
|
||||
int inc = iterationIncrement(seed);
|
||||
for (int i = 0, mask = this.mask, slot = seed & mask;
|
||||
i <= mask;
|
||||
i++, slot = (slot + inc) & mask) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
cloned[j++] = existing;
|
||||
}
|
||||
}
|
||||
|
||||
return cloned;
|
||||
}
|
||||
|
||||
/** An alias for the (preferred) {@link #removeAll}. */
|
||||
public boolean remove(char key) {
|
||||
if (((key) == 0)) {
|
||||
boolean hadEmptyKey = hasEmptyKey;
|
||||
hasEmptyKey = false;
|
||||
return hadEmptyKey;
|
||||
} else {
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
int slot = hashKey(key) & mask;
|
||||
|
||||
char existing;
|
||||
while (!((existing = keys[slot]) == 0)) {
|
||||
if (((key) == (existing))) {
|
||||
shiftConflictingKeys(slot);
|
||||
return true;
|
||||
}
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(char key) {
|
||||
return remove(key) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all keys present in a given container.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer other) {
|
||||
final int before = size();
|
||||
|
||||
// Try to iterate over the smaller set or over the container that isn't implementing
|
||||
// efficient contains() lookup.
|
||||
|
||||
if (other.size() >= size() && other instanceof CharLookupContainer) {
|
||||
if (hasEmptyKey && other.contains(((char) 0))) {
|
||||
hasEmptyKey = false;
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
for (int slot = 0, max = this.mask; slot <= max; ) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0) && other.contains(existing)) {
|
||||
// Shift, do not increment slot.
|
||||
shiftConflictingKeys(slot);
|
||||
} else {
|
||||
slot++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (CharCursor c : other) {
|
||||
remove(c.value);
|
||||
}
|
||||
}
|
||||
|
||||
return before - size();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int removeAll(CharPredicate predicate) {
|
||||
int before = size();
|
||||
|
||||
if (hasEmptyKey) {
|
||||
if (predicate.apply(((char) 0))) {
|
||||
hasEmptyKey = false;
|
||||
}
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
for (int slot = 0, max = this.mask; slot <= max; ) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
if (predicate.apply(existing)) {
|
||||
shiftConflictingKeys(slot);
|
||||
continue; // Repeat the check for the same slot i (shifted).
|
||||
}
|
||||
}
|
||||
slot++;
|
||||
}
|
||||
|
||||
return before - size();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean contains(char key) {
|
||||
if (((key) == 0)) {
|
||||
return hasEmptyKey;
|
||||
} else {
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
int slot = hashKey(key) & mask;
|
||||
char existing;
|
||||
while (!((existing = keys[slot]) == 0)) {
|
||||
if (((key) == (existing))) {
|
||||
return true;
|
||||
}
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void clear() {
|
||||
assigned = 0;
|
||||
hasEmptyKey = false;
|
||||
Arrays.fill(keys, ((char) 0));
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public void release() {
|
||||
assigned = 0;
|
||||
hasEmptyKey = false;
|
||||
keys = null;
|
||||
ensureCapacity(Containers.DEFAULT_EXPECTED_ELEMENTS);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure this container can hold at least the given number of elements without resizing its
|
||||
* buffers.
|
||||
*
|
||||
* @param expectedElements The total number of elements, inclusive.
|
||||
*/
|
||||
@Override
|
||||
public void ensureCapacity(int expectedElements) {
|
||||
if (expectedElements > resizeAt || keys == null) {
|
||||
final char[] prevKeys = this.keys;
|
||||
allocateBuffers(minBufferSize(expectedElements, loadFactor));
|
||||
if (prevKeys != null && !isEmpty()) {
|
||||
rehash(prevKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int size() {
|
||||
return assigned + (hasEmptyKey ? 1 : 0);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int h = hasEmptyKey ? 0xDEADBEEF : 0;
|
||||
final char[] keys = this.keys;
|
||||
for (int slot = mask; slot >= 0; slot--) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
h += BitMixer.mix(existing);
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return (this == obj)
|
||||
|| (obj != null && getClass() == obj.getClass() && sameKeys(getClass().cast(obj)));
|
||||
}
|
||||
|
||||
/** Return true if all keys of some other container exist in this container. */
|
||||
private boolean sameKeys(CharSet other) {
|
||||
if (other.size() != size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (CharCursor c : other) {
|
||||
if (!contains(c.value)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public CharHashSet clone() {
|
||||
try {
|
||||
|
||||
CharHashSet cloned = (CharHashSet) super.clone();
|
||||
cloned.keys = keys.clone();
|
||||
cloned.hasEmptyKey = hasEmptyKey;
|
||||
cloned.iterationSeed = HashContainers.nextIterationSeed();
|
||||
return cloned;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public Iterator<CharCursor> iterator() {
|
||||
return new EntryIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesAllocated() {
|
||||
// int: assigned, mask, keyMixer, resizeAt
|
||||
// double: loadFactor
|
||||
// boolean: hasEmptyKey
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 4 * Integer.BYTES
|
||||
+ Double.BYTES
|
||||
+ 1
|
||||
+ RamUsageEstimator.shallowSizeOfArray(keys);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long ramBytesUsed() {
|
||||
// int: assigned, mask, keyMixer, resizeAt
|
||||
// double: loadFactor
|
||||
// boolean: hasEmptyKey
|
||||
return RamUsageEstimator.NUM_BYTES_OBJECT_HEADER
|
||||
+ 4 * Integer.BYTES
|
||||
+ Double.BYTES
|
||||
+ 1
|
||||
+ RamUsageEstimator.shallowUsedSizeOfArray(keys, size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the next iteration seed used to build the iteration starting slot and offset
|
||||
* increment. This method does not need to be synchronized, what matters is that each thread gets
|
||||
* a sequence of varying seeds.
|
||||
*/
|
||||
protected int nextIterationSeed() {
|
||||
return iterationSeed = BitMixer.mixPhi(iterationSeed);
|
||||
}
|
||||
|
||||
/** An iterator implementation for {@link #iterator}. */
|
||||
protected final class EntryIterator extends AbstractIterator<CharCursor> {
|
||||
private final CharCursor cursor;
|
||||
private final int increment;
|
||||
private int index;
|
||||
private int slot;
|
||||
|
||||
public EntryIterator() {
|
||||
cursor = new CharCursor();
|
||||
int seed = nextIterationSeed();
|
||||
increment = iterationIncrement(seed);
|
||||
slot = seed & mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CharCursor fetch() {
|
||||
final int mask = CharHashSet.this.mask;
|
||||
while (index <= mask) {
|
||||
char existing;
|
||||
index++;
|
||||
slot = (slot + increment) & mask;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
cursor.index = slot;
|
||||
cursor.value = existing;
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
|
||||
if (index == mask + 1 && hasEmptyKey) {
|
||||
cursor.index = index++;
|
||||
cursor.value = ((char) 0);
|
||||
return cursor;
|
||||
}
|
||||
|
||||
return done();
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharProcedure> T forEach(T procedure) {
|
||||
if (hasEmptyKey) {
|
||||
procedure.apply(((char) 0));
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
int seed = nextIterationSeed();
|
||||
int inc = iterationIncrement(seed);
|
||||
for (int i = 0, mask = this.mask, slot = seed & mask;
|
||||
i <= mask;
|
||||
i++, slot = (slot + inc) & mask) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
procedure.apply(existing);
|
||||
}
|
||||
}
|
||||
|
||||
return procedure;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public <T extends CharPredicate> T forEach(T predicate) {
|
||||
if (hasEmptyKey) {
|
||||
if (!predicate.apply(((char) 0))) {
|
||||
return predicate;
|
||||
}
|
||||
}
|
||||
|
||||
final char[] keys = this.keys;
|
||||
int seed = nextIterationSeed();
|
||||
int inc = iterationIncrement(seed);
|
||||
for (int i = 0, mask = this.mask, slot = seed & mask;
|
||||
i <= mask;
|
||||
i++, slot = (slot + inc) & mask) {
|
||||
char existing;
|
||||
if (!((existing = keys[slot]) == 0)) {
|
||||
if (!predicate.apply(existing)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return predicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a set from a variable number of arguments or an array of <code>char</code>. The elements
|
||||
* are copied from the argument to the internal buffer.
|
||||
*/
|
||||
public static CharHashSet from(char... elements) {
|
||||
final CharHashSet set = new CharHashSet(elements.length);
|
||||
set.addAll(elements);
|
||||
return set;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a hash code for the given key.
|
||||
*
|
||||
* <p>The output from this function should evenly distribute keys across the entire integer range.
|
||||
*/
|
||||
protected int hashKey(char key) {
|
||||
assert !((key) == 0); // Handled as a special case (empty slot marker).
|
||||
return BitMixer.mixPhi(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up logic in
|
||||
* certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between modifications (it will not be affected by read-only
|
||||
* operations).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the set.
|
||||
* @return A non-negative value of the logical "index" of the key in the set or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key) {
|
||||
final int mask = this.mask;
|
||||
if (((key) == 0)) {
|
||||
return hasEmptyKey ? mask + 1 : ~(mask + 1);
|
||||
} else {
|
||||
final char[] keys = this.keys;
|
||||
int slot = hashKey(key) & mask;
|
||||
|
||||
char existing;
|
||||
while (!((existing = keys[slot]) == 0)) {
|
||||
if (((key) == (existing))) {
|
||||
return slot;
|
||||
}
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
|
||||
return ~slot;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index) {
|
||||
assert index < 0 || index <= mask || (index == mask + 1 && hasEmptyKey);
|
||||
|
||||
return index >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the exact value of the existing key. This method makes sense for sets of objects which
|
||||
* define custom key-equality relationship.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the equivalent key currently stored in the set.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexGet(int index) {
|
||||
assert index >= 0 : "The index must point at an existing key.";
|
||||
assert index <= mask || (index == mask + 1 && hasEmptyKey);
|
||||
|
||||
return keys[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the existing equivalent key with the given one and returns any previous value stored
|
||||
* for that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @param equivalentKey The key to put in the set as a replacement. Must be equivalent to the key
|
||||
* currently stored at the provided index.
|
||||
* @return Returns the previous key stored in the set.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public char indexReplace(int index, char equivalentKey) {
|
||||
assert index >= 0 : "The index must point at an existing key.";
|
||||
assert index <= mask || (index == mask + 1 && hasEmptyKey);
|
||||
assert ((keys[index]) == (equivalentKey));
|
||||
|
||||
char previousValue = keys[index];
|
||||
keys[index] = equivalentKey;
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a key for an index that is not present in the set. This method may help in avoiding
|
||||
* double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key) {
|
||||
assert index < 0 : "The index must not point at an existing key.";
|
||||
|
||||
index = ~index;
|
||||
if (((key) == 0)) {
|
||||
assert index == mask + 1;
|
||||
assert ((keys[index]) == 0);
|
||||
hasEmptyKey = true;
|
||||
} else {
|
||||
assert ((keys[index]) == 0);
|
||||
|
||||
if (assigned == resizeAt) {
|
||||
allocateThenInsertThenRehash(index, key);
|
||||
} else {
|
||||
keys[index] = key;
|
||||
}
|
||||
|
||||
assigned++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a key at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public void indexRemove(int index) {
|
||||
assert index >= 0 : "The index must point at an existing key.";
|
||||
assert index <= mask || (index == mask + 1 && hasEmptyKey);
|
||||
|
||||
if (index > mask) {
|
||||
hasEmptyKey = false;
|
||||
} else {
|
||||
shiftConflictingKeys(index);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String visualizeKeyDistribution(int characters) {
|
||||
return CharBufferVisualizer.visualizeKeyDistribution(keys, mask, characters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate load factor range and return it. Override and suppress if you need insane load
|
||||
* factors.
|
||||
*/
|
||||
protected double verifyLoadFactor(double loadFactor) {
|
||||
checkLoadFactor(loadFactor, MIN_LOAD_FACTOR, MAX_LOAD_FACTOR);
|
||||
return loadFactor;
|
||||
}
|
||||
|
||||
/** Rehash from old buffers to new buffers. */
|
||||
protected void rehash(char[] fromKeys) {
|
||||
assert HashContainers.checkPowerOfTwo(fromKeys.length - 1);
|
||||
|
||||
// Rehash all stored keys into the new buffers.
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
char existing;
|
||||
for (int i = fromKeys.length - 1; --i >= 0; ) {
|
||||
if (!((existing = fromKeys[i]) == 0)) {
|
||||
int slot = hashKey(existing) & mask;
|
||||
while (!((keys[slot]) == 0)) {
|
||||
slot = (slot + 1) & mask;
|
||||
}
|
||||
keys[slot] = existing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate new internal buffers. This method attempts to allocate and assign internal buffers
|
||||
* atomically (either allocations succeed or not).
|
||||
*/
|
||||
protected void allocateBuffers(int arraySize) {
|
||||
assert Integer.bitCount(arraySize) == 1;
|
||||
|
||||
// Ensure no change is done if we hit an OOM.
|
||||
char[] prevKeys = this.keys;
|
||||
try {
|
||||
int emptyElementSlot = 1;
|
||||
this.keys = (new char[arraySize + emptyElementSlot]);
|
||||
} catch (OutOfMemoryError e) {
|
||||
this.keys = prevKeys;
|
||||
throw new BufferAllocationException(
|
||||
"Not enough memory to allocate buffers for rehashing: %,d -> %,d",
|
||||
e, this.keys == null ? 0 : size(), arraySize);
|
||||
}
|
||||
|
||||
this.resizeAt = expandAtCount(arraySize, loadFactor);
|
||||
this.mask = arraySize - 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is invoked when there is a new key to be inserted into the buffer but there is not
|
||||
* enough empty slots to do so.
|
||||
*
|
||||
* <p>New buffers are allocated. If this succeeds, we know we can proceed with rehashing so we
|
||||
* assign the pending element to the previous buffer (possibly violating the invariant of having
|
||||
* at least one empty slot) and rehash all keys, substituting new buffers at the end.
|
||||
*/
|
||||
protected void allocateThenInsertThenRehash(int slot, char pendingKey) {
|
||||
assert assigned == resizeAt && ((keys[slot]) == 0) && !((pendingKey) == 0);
|
||||
|
||||
// Try to allocate new buffers first. If we OOM, we leave in a consistent state.
|
||||
final char[] prevKeys = this.keys;
|
||||
allocateBuffers(nextBufferSize(mask + 1, size(), loadFactor));
|
||||
assert this.keys.length > prevKeys.length;
|
||||
|
||||
// We have succeeded at allocating new data so insert the pending key/value at
|
||||
// the free slot in the old arrays before rehashing.
|
||||
prevKeys[slot] = pendingKey;
|
||||
|
||||
// Rehash old keys, including the pending key.
|
||||
rehash(prevKeys);
|
||||
}
|
||||
|
||||
/** Shift all the slot-conflicting keys allocated to (and including) <code>slot</code>. */
|
||||
protected void shiftConflictingKeys(int gapSlot) {
|
||||
final char[] keys = this.keys;
|
||||
final int mask = this.mask;
|
||||
|
||||
// Perform shifts of conflicting keys to fill in the gap.
|
||||
int distance = 0;
|
||||
while (true) {
|
||||
final int slot = (gapSlot + (++distance)) & mask;
|
||||
final char existing = keys[slot];
|
||||
if (((existing) == 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
final int idealSlot = hashKey(existing);
|
||||
final int shift = (slot - idealSlot) & mask;
|
||||
if (shift >= distance) {
|
||||
// Entry at this position was originally at or before the gap slot.
|
||||
// Move the conflict-shifted entry to the gap's position and repeat the procedure
|
||||
// for any entries to the right of the current position, treating it
|
||||
// as the new gap.
|
||||
keys[gapSlot] = existing;
|
||||
gapSlot = slot;
|
||||
distance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark the last found gap slot without a conflict as empty.
|
||||
keys[gapSlot] = ((char) 0);
|
||||
assigned--;
|
||||
}
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import java.util.RandomAccess;
|
||||
|
||||
/**
|
||||
* An indexed container provides random access to elements based on an <code>index</code>. Indexes
|
||||
* are zero-based.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeIndexedContainer.java")
|
||||
public interface CharIndexedContainer extends CharCollection, RandomAccess {
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning whether an element has been
|
||||
* removed.
|
||||
*/
|
||||
public boolean removeElement(char e1);
|
||||
|
||||
/**
|
||||
* Removes the first element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeFirst(char e1);
|
||||
|
||||
/**
|
||||
* Removes the last element that equals <code>e1</code>, returning its deleted position or <code>
|
||||
* -1</code> if the element was not found.
|
||||
*/
|
||||
public int removeLast(char e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the first occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int indexOf(char e1);
|
||||
|
||||
/**
|
||||
* Returns the index of the last occurrence of the specified element in this list, or -1 if this
|
||||
* list does not contain the element.
|
||||
*/
|
||||
public int lastIndexOf(char e1);
|
||||
|
||||
/** Adds an element to the end of this container (the last index is incremented by one). */
|
||||
public void add(char e1);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the specified position in this list.
|
||||
*
|
||||
* @param index The index at which the element should be inserted, shifting any existing and
|
||||
* subsequent elements to the right.
|
||||
*/
|
||||
public void insert(int index, char e1);
|
||||
|
||||
/**
|
||||
* Replaces the element at the specified position in this list with the specified element.
|
||||
*
|
||||
* @return Returns the previous value in the list.
|
||||
*/
|
||||
public char set(int index, char e1);
|
||||
|
||||
/**
|
||||
* @return Returns the element at index <code>index</code> from the list.
|
||||
*/
|
||||
public char get(int index);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in this container and returns it.
|
||||
*
|
||||
* @see #removeFirst
|
||||
* @see #removeLast
|
||||
* @see #removeAll
|
||||
*/
|
||||
public char removeAt(int index);
|
||||
|
||||
/** Removes and returns the last element of this container. This container must not be empty. */
|
||||
public char removeLast();
|
||||
|
||||
/**
|
||||
* Removes from this container all of the elements with indexes between <code>fromIndex</code>,
|
||||
* inclusive, and <code>toIndex</code>, exclusive.
|
||||
*/
|
||||
public void removeRange(int fromIndex, int toIndex);
|
||||
|
||||
/** Returns this container elements as a stream. */
|
||||
|
||||
/** Sorts the elements in this container and returns this container. */
|
||||
public CharIndexedContainer sort();
|
||||
|
||||
/** Reverses the elements in this container and returns this container. */
|
||||
public CharIndexedContainer reverse();
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharIntAssociativeContainer extends Iterable<CharIntCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharIntCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharIntPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharIntProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharIntProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharIntPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharIntPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public IntContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharIntCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharIntMap extends CharIntAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public int get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public int getOrDefault(char key, int defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public int put(char key, int value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, int value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharIntAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharIntCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public int putOrAdd(char key, int putValue, int incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public int addTo(char key, int additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public int remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharIntMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public int indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public int indexReplace(int index, int newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, int value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public int indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharLongAssociativeContainer extends Iterable<CharLongCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharLongCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharLongPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharLongProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharLongProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharLongPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharLongPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public LongContainer values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,205 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharLongCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharLongMap extends CharLongAssociativeContainer {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public long get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public long getOrDefault(char key, long defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public long put(char key, long value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, long value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharLongAssociativeContainer container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharLongCursor> iterable);
|
||||
|
||||
/**
|
||||
* If <code>key</code> exists, <code>putValue</code> is inserted into the map, otherwise any
|
||||
* existing value is incremented by <code>additionValue</code>.
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param putValue The value to put if <code>key</code> does not exist.
|
||||
* @param incrementValue The value to add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public long putOrAdd(char key, long putValue, long incrementValue);
|
||||
|
||||
/**
|
||||
* An equivalent of calling
|
||||
*
|
||||
* <pre>
|
||||
* putOrAdd(key, additionValue, additionValue);
|
||||
* </pre>
|
||||
*
|
||||
* @param key The key of the value to adjust.
|
||||
* @param additionValue The value to put or add to the existing value if <code>key</code> exists.
|
||||
* @return Returns the current value associated with <code>key</code> (after changes).
|
||||
*/
|
||||
public long addTo(char key, long additionValue);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public long remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharLongMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public long indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public long indexReplace(int index, long newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, long value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public long indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/**
|
||||
* Marker interface for containers that can check if they contain a given object in at least time
|
||||
* <code>O(log n)</code> and ideally in amortized constant time <code>O(1)</code>.
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeLookupContainer.java")
|
||||
public interface CharLookupContainer extends CharContainer {
|
||||
public boolean contains(char e);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharObjectAssociativeContainer<VType> extends Iterable<CharObjectCursor<VType>> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharObjectCursor<VType>> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharObjectPredicate<? super VType> predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharObjectProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharObjectProcedure<? super VType>> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharObjectPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharObjectPredicate<? super VType>> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public ObjectContainer<VType> values();
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,181 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.CharObjectCursor;
|
||||
|
||||
/** An associative container with unique binding from keys to a single value. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeVTypeMap.java")
|
||||
public interface CharObjectMap<VType> extends CharObjectAssociativeContainer<VType> {
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the default value for the value
|
||||
* type, if the key is not associated with any value. For numeric value types, this default
|
||||
* value is 0, for object types it is {@code null}.
|
||||
*/
|
||||
public VType get(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the value associated with the given key or the provided default value if the
|
||||
* key is not associated with any value.
|
||||
*/
|
||||
public VType getOrDefault(char key, VType defaultValue);
|
||||
|
||||
/**
|
||||
* Place a given key and value in the container.
|
||||
*
|
||||
* @return The value previously stored under the given key in the map is returned.
|
||||
*/
|
||||
public VType put(char key, VType value);
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a value, associates it with the given
|
||||
* value.
|
||||
*
|
||||
* @return {@code true} if {@code key} did not exist and {@code value} was placed in the map,
|
||||
* {@code false} otherwise.
|
||||
*/
|
||||
public default boolean putIfAbsent(char key, VType value) {
|
||||
int keyIndex = indexOf(key);
|
||||
if (indexExists(keyIndex)) {
|
||||
return false;
|
||||
} else {
|
||||
indexInsert(keyIndex, key, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts all keys from another container to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(CharObjectAssociativeContainer<? extends VType> container);
|
||||
|
||||
/**
|
||||
* Puts all keys from an iterable cursor to this map, replacing the values of existing keys, if
|
||||
* such keys are present.
|
||||
*
|
||||
* @return Returns the number of keys added to the map as a result of this call (not previously
|
||||
* present in the map). Values of existing keys are overwritten.
|
||||
*/
|
||||
public int putAll(Iterable<? extends CharObjectCursor<? extends VType>> iterable);
|
||||
|
||||
/**
|
||||
* Remove all values at the given key. The default value for the key type is returned if the value
|
||||
* does not exist in the map.
|
||||
*/
|
||||
public VType remove(char key);
|
||||
|
||||
/**
|
||||
* Compares the specified object with this set for equality. Returns {@code true} if and only if
|
||||
* the specified object is also a {@link CharObjectMap} and both objects contains exactly the same
|
||||
* key-value pairs.
|
||||
*/
|
||||
public boolean equals(Object obj);
|
||||
|
||||
/**
|
||||
* @return A hash code of elements stored in the map. The hash code is defined as a sum of hash
|
||||
* codes of keys and values stored within the set). Because sum is commutative, this ensures
|
||||
* that different order of elements in a set does not affect the hash code.
|
||||
*/
|
||||
public int hashCode();
|
||||
|
||||
/**
|
||||
* Returns a logical "index" of a given key that can be used to speed up follow-up value setters
|
||||
* or getters in certain scenarios (conditional logic).
|
||||
*
|
||||
* <p>The semantics of "indexes" are not strictly defined. Indexes may (and typically won't be)
|
||||
* contiguous.
|
||||
*
|
||||
* <p>The index is valid only between map modifications (it will not be affected by read-only
|
||||
* operations like iteration or value retrievals).
|
||||
*
|
||||
* @see #indexExists
|
||||
* @see #indexGet
|
||||
* @see #indexInsert
|
||||
* @see #indexReplace
|
||||
* @param key The key to locate in the map.
|
||||
* @return A non-negative value of the logical "index" of the key in the map or a negative value
|
||||
* if the key did not exist.
|
||||
*/
|
||||
public int indexOf(char key);
|
||||
|
||||
/**
|
||||
* @see #indexOf
|
||||
* @param index The index of a given key, as returned from {@link #indexOf}.
|
||||
* @return Returns <code>true</code> if the index corresponds to an existing key or false
|
||||
* otherwise. This is equivalent to checking whether the index is a positive value (existing
|
||||
* keys) or a negative value (non-existing keys).
|
||||
*/
|
||||
public boolean indexExists(int index);
|
||||
|
||||
/**
|
||||
* Returns the value associated with an existing key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the value currently associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public VType indexGet(int index);
|
||||
|
||||
/**
|
||||
* Replaces the value associated with an existing key and returns any previous value stored for
|
||||
* that key.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of an existing key.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public VType indexReplace(int index, VType newValue);
|
||||
|
||||
/**
|
||||
* Inserts a key-value pair for a key that is not present in the map. This method may help in
|
||||
* avoiding double recalculation of the key's hash.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of a previously non-existing key, as returned from {@link #indexOf}.
|
||||
* @throws AssertionError If assertions are enabled and the index corresponds to an existing key.
|
||||
*/
|
||||
public void indexInsert(int index, char key, VType value);
|
||||
|
||||
/**
|
||||
* Removes a key-value pair at an index previously acquired from {@link #indexOf}.
|
||||
*
|
||||
* @see #indexOf
|
||||
* @param index The index of the key to remove, as returned from {@link #indexOf}.
|
||||
* @return Returns the previous value associated with the key.
|
||||
* @throws AssertionError If assertions are enabled and the index does not correspond to an
|
||||
* existing key.
|
||||
*/
|
||||
public VType indexRemove(int index);
|
||||
|
||||
/**
|
||||
* Clear all keys and values in the container.
|
||||
*
|
||||
* @see #release()
|
||||
*/
|
||||
public void clear();
|
||||
|
||||
/**
|
||||
* Removes all elements from the collection and additionally releases any internal buffers.
|
||||
* Typically, if the object is to be reused, a simple {@link #clear()} should be a better
|
||||
* alternative since it'll avoid reallocation.
|
||||
*
|
||||
* @see #clear()
|
||||
*/
|
||||
public void release();
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
}
|
@ -1,33 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
/** A set of <code>char</code>s. */
|
||||
@com.carrotsearch.hppc.Generated(date = "2024-06-04T15:20:17+0200", value = "KTypeSet.java")
|
||||
public interface CharSet extends CharCollection {
|
||||
/**
|
||||
* Adds <code>k</code> to the set.
|
||||
*
|
||||
* @return Returns <code>true</code> if this element was not part of the set before. Returns
|
||||
* <code>false</code> if an equal element is already part of the set, <b>does not replace the
|
||||
* existing element</b> with the argument.
|
||||
*/
|
||||
public boolean add(char k);
|
||||
|
||||
/**
|
||||
* Visually depict the distribution of keys.
|
||||
*
|
||||
* @param characters The number of characters to "squeeze" the entire buffer into.
|
||||
* @return Returns a sequence of characters where '.' depicts an empty fragment of the internal
|
||||
* buffer and 'X' depicts full or nearly full capacity within the buffer's range and anything
|
||||
* between 1 and 9 is between.
|
||||
*/
|
||||
public String visualizeKeyDistribution(int characters);
|
||||
|
||||
/**
|
||||
* Adds all elements from the given {@link CharContainer} to this set.
|
||||
*
|
||||
* @return Returns the number of elements actually added as a result of this call (not previously
|
||||
* present in the set).
|
||||
* @since 0.9.1
|
||||
*/
|
||||
public int addAll(CharContainer container);
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package com.carrotsearch.hppc;
|
||||
|
||||
import com.carrotsearch.hppc.cursors.*;
|
||||
import com.carrotsearch.hppc.predicates.*;
|
||||
import com.carrotsearch.hppc.procedures.*;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* An associative container from keys to (one or possibly more) values.
|
||||
*
|
||||
* @see CharContainer
|
||||
*/
|
||||
@com.carrotsearch.hppc.Generated(
|
||||
date = "2024-06-04T15:20:17+0200",
|
||||
value = "KTypeVTypeAssociativeContainer.java")
|
||||
public interface CharShortAssociativeContainer extends Iterable<CharShortCursor> {
|
||||
/**
|
||||
* Returns a cursor over the entries (key-value pairs) in this map. The iterator is implemented as
|
||||
* a cursor and it returns <b>the same cursor instance</b> on every call to {@link
|
||||
* Iterator#next()}. To read the current key and value use the cursor's public fields. An example
|
||||
* is shown below.
|
||||
*
|
||||
* <pre>
|
||||
* for (IntShortCursor c : intShortMap) {
|
||||
* System.out.println("index=" + c.index + " key=" + c.key + " value=" + c.value);
|
||||
* }</pre>
|
||||
*
|
||||
* <p>The <code>index</code> field inside the cursor gives the internal index inside the
|
||||
* container's implementation. The interpretation of this index depends on to the container.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<CharShortCursor> iterator();
|
||||
|
||||
/**
|
||||
* Returns <code>true</code> if this container has an association to a value for the given key.
|
||||
*/
|
||||
public boolean containsKey(char key);
|
||||
|
||||
/**
|
||||
* @return Returns the current size (number of assigned keys) in the container.
|
||||
*/
|
||||
public int size();
|
||||
|
||||
/**
|
||||
* @return Return <code>true</code> if this hash map contains no assigned keys.
|
||||
*/
|
||||
public boolean isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) present in a given container. An alias to:
|
||||
*
|
||||
* <pre>
|
||||
* keys().removeAll(container)
|
||||
* </pre>
|
||||
*
|
||||
* but with no additional overhead.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharContainer container);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharPredicate predicate);
|
||||
|
||||
/**
|
||||
* Removes all keys (and associated values) for which the predicate returns <code>true</code>.
|
||||
*
|
||||
* @return Returns the number of elements actually removed as a result of this call.
|
||||
*/
|
||||
public int removeAll(CharShortPredicate predicate);
|
||||
|
||||
/**
|
||||
* Applies a given procedure to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharShortProcedure}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*/
|
||||
public <T extends CharShortProcedure> T forEach(T procedure);
|
||||
|
||||
/**
|
||||
* Applies a given predicate to all keys-value pairs in this container. Returns the argument (any
|
||||
* subclass of {@link CharShortPredicate}. This lets the caller call methods of the argument by
|
||||
* chaining the call (even if the argument is an anonymous type) to retrieve computed values.
|
||||
*
|
||||
* <p>The iteration is continued as long as the predicate returns <code>true</code>.
|
||||
*/
|
||||
public <T extends CharShortPredicate> T forEach(T predicate);
|
||||
|
||||
/**
|
||||
* Returns a collection of keys of this container. The returned collection is a view over the key
|
||||
* set and any modifications (if allowed) introduced to the collection will propagate to the
|
||||
* associative container immediately.
|
||||
*/
|
||||
public CharCollection keys();
|
||||
|
||||
/**
|
||||
* Returns a container view of all values present in this container. The returned collection is a
|
||||
* view over the key set and any modifications (if allowed) introduced to the collection will
|
||||
* propagate to the associative container immediately.
|
||||
*/
|
||||
public ShortContainer values();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user