This repository has been archived by the owner on Feb 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit de07c29
Showing
7 changed files
with
319 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
|
||
# Created by https://www.toptal.com/developers/gitignore/api/java,intellij,maven | ||
# Edit at https://www.toptal.com/developers/gitignore?templates=java,intellij,maven | ||
|
||
### Intellij ### | ||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider | ||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 | ||
|
||
# User-specific stuff | ||
.idea/**/workspace.xml | ||
.idea/**/tasks.xml | ||
.idea/**/usage.statistics.xml | ||
.idea/**/dictionaries | ||
.idea/**/shelf | ||
|
||
# Generated files | ||
.idea/**/contentModel.xml | ||
|
||
# Sensitive or high-churn files | ||
.idea/**/dataSources/ | ||
.idea/**/dataSources.ids | ||
.idea/**/dataSources.local.xml | ||
.idea/**/sqlDataSources.xml | ||
.idea/**/dynamic.xml | ||
.idea/**/uiDesigner.xml | ||
.idea/**/dbnavigator.xml | ||
|
||
# Gradle | ||
.idea/**/gradle.xml | ||
.idea/**/libraries | ||
|
||
# Gradle and Maven with auto-import | ||
# When using Gradle or Maven with auto-import, you should exclude module files, | ||
# since they will be recreated, and may cause churn. Uncomment if using | ||
# auto-import. | ||
# .idea/artifacts | ||
# .idea/compiler.xml | ||
# .idea/jarRepositories.xml | ||
# .idea/modules.xml | ||
# .idea/*.iml | ||
# .idea/modules | ||
# *.iml | ||
# *.ipr | ||
|
||
# CMake | ||
cmake-build-*/ | ||
|
||
# Mongo Explorer plugin | ||
.idea/**/mongoSettings.xml | ||
|
||
# File-based project format | ||
*.iws | ||
|
||
# IntelliJ | ||
out/ | ||
|
||
# mpeltonen/sbt-idea plugin | ||
.idea_modules/ | ||
|
||
# JIRA plugin | ||
atlassian-ide-plugin.xml | ||
|
||
# Cursive Clojure plugin | ||
.idea/replstate.xml | ||
|
||
# Crashlytics plugin (for Android Studio and IntelliJ) | ||
com_crashlytics_export_strings.xml | ||
crashlytics.properties | ||
crashlytics-build.properties | ||
fabric.properties | ||
|
||
# Editor-based Rest Client | ||
.idea/httpRequests | ||
|
||
# Android studio 3.1+ serialized cache file | ||
.idea/caches/build_file_checksums.ser | ||
|
||
### Intellij Patch ### | ||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 | ||
|
||
# *.iml | ||
# modules.xml | ||
# .idea/misc.xml | ||
# *.ipr | ||
|
||
# Sonarlint plugin | ||
# https://plugins.jetbrains.com/plugin/7973-sonarlint | ||
.idea/**/sonarlint/ | ||
|
||
# SonarQube Plugin | ||
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin | ||
.idea/**/sonarIssues.xml | ||
|
||
# Markdown Navigator plugin | ||
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced | ||
.idea/**/markdown-navigator.xml | ||
.idea/**/markdown-navigator-enh.xml | ||
.idea/**/markdown-navigator/ | ||
|
||
# Cache file creation bug | ||
# See https://youtrack.jetbrains.com/issue/JBR-2257 | ||
.idea/$CACHE_FILE$ | ||
|
||
# CodeStream plugin | ||
# https://plugins.jetbrains.com/plugin/12206-codestream | ||
.idea/codestream.xml | ||
|
||
### Java ### | ||
# Compiled class file | ||
*.class | ||
|
||
# Log file | ||
*.log | ||
|
||
# BlueJ files | ||
*.ctxt | ||
|
||
# Mobile Tools for Java (J2ME) | ||
.mtj.tmp/ | ||
|
||
# Package Files # | ||
*.jar | ||
*.war | ||
*.nar | ||
*.ear | ||
*.zip | ||
*.tar.gz | ||
*.rar | ||
|
||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | ||
hs_err_pid* | ||
|
||
### Maven ### | ||
target/ | ||
pom.xml.tag | ||
pom.xml.releaseBackup | ||
pom.xml.versionsBackup | ||
pom.xml.next | ||
release.properties | ||
dependency-reduced-pom.xml | ||
buildNumber.properties | ||
.mvn/timing.properties | ||
# https://github.com/takari/maven-wrapper#usage-without-binary-jar | ||
.mvn/wrapper/maven-wrapper.jar | ||
|
||
# End of https://www.toptal.com/developers/gitignore/api/java,intellij,maven |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<module type="JAVA_MODULE" version="4"> | ||
<component name="NewModuleRootManager" inherit-compiler-output="true"> | ||
<exclude-output /> | ||
<content url="file://$MODULE_DIR$"> | ||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> | ||
</content> | ||
<orderEntry type="inheritedJdk" /> | ||
<orderEntry type="sourceFolder" forTests="false" /> | ||
</component> | ||
</module> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import java.math.BigInteger; | ||
import java.util.ArrayList; | ||
|
||
public class Main { | ||
public static void main(String[] args) { | ||
if (args.length != 2) { | ||
System.err.println("Usage: java -jar <jar file> (encode|decode) <value>"); | ||
System.exit(-1); | ||
} | ||
|
||
switch (args[0]) { | ||
case "encode" -> encode(args[1]); | ||
case "decode" -> decode(args[1]); | ||
default -> System.err.printf("invalid command %s. Expected either \"encode\" or \"decode\".%n", args[0]); | ||
} | ||
|
||
final var namespace = args[0]; | ||
} | ||
|
||
private static void encode(final String namespace) { | ||
if (!namespace.matches("^[a-z0-9_.-]+$")) { | ||
System.err.printf("invalid namespace %s%n", namespace); | ||
System.exit(-1); | ||
} | ||
|
||
final boolean fullCharSet = !namespace.matches("^[a-z_]+$"); | ||
|
||
BigInteger value = BigInteger.ZERO; | ||
final int base = fullCharSet ? 39 : 27; | ||
final BigInteger multiplier = BigInteger.valueOf(base); | ||
|
||
for (char curChar : namespace.toCharArray()) { | ||
//The add one is here to create a consistent offset. In case a namespace starts with 'a', we don't want | ||
// the first digit as 0. | ||
value = value.multiply(multiplier) | ||
.add(BigInteger.valueOf(getCharValue(curChar) + 1)); | ||
} | ||
|
||
// ceil((value.bitLength() + 1) / 31) | ||
// Int division always floors, but ceil can be expressed with ((n - 1) / m) +1 | ||
// Since n = value.bitLength() + 1, the + 1 with the - 1 cancel each other out. | ||
// The + 1 is needed because we use an additional bit to store the value of fullCharSet | ||
final int length = value.bitLength() / 31 + 1; | ||
|
||
final int[] placeholders = new int[length]; | ||
final BigInteger twoPow31 = BigInteger.valueOf(0x80_00_00_00L); | ||
|
||
for (int i = length -1; i >= 0; i--) { | ||
final var divMod = value.divideAndRemainder(twoPow31); | ||
|
||
placeholders[i] = divMod[1].intValueExact(); | ||
value = divMod[0]; | ||
|
||
if (i == 0 && fullCharSet) { | ||
placeholders[0] |= 0x40_00_00_00; | ||
} | ||
} | ||
|
||
final var result = new StringBuilder(); | ||
for (int placeholder : placeholders) { | ||
result.append("%") | ||
.append(Integer.toUnsignedString(placeholder)) | ||
.append("$s"); | ||
} | ||
|
||
System.out.println(result); | ||
} | ||
|
||
private static int getCharValue(char c) { | ||
if (c >= 'a') { | ||
return c - 'a'; | ||
} else if (c == '_') { | ||
return 26; | ||
} else if (c >= '0') { | ||
return c - '0' + 27; | ||
} else if (c == '-') { | ||
return 37; | ||
} else { | ||
return 38; | ||
} | ||
} | ||
|
||
private static void decode(final String encodedNamespace) { | ||
if (!encodedNamespace.matches("^(?:%[1-9][0-9]+\\$s)+$")) { | ||
System.err.printf("invalid encoded namespace %s%n", encodedNamespace); | ||
System.exit(-1); | ||
} | ||
|
||
final String trimmed = encodedNamespace.substring(1, encodedNamespace.length() - 2); | ||
final String[] placeholderStrings = trimmed.split("\\$s%"); | ||
final int[] placeholders = new int[placeholderStrings.length]; | ||
|
||
for (int i = 0; i < placeholders.length; i++) { | ||
placeholders[i] = Integer.parseInt(placeholderStrings[i]); | ||
} | ||
boolean fullCharSet = (placeholders[0] & 0x40_00_00_00) > 0; | ||
placeholders[0] &= 0xBF_FF_FF_FF; | ||
|
||
final BigInteger twoPow31 = BigInteger.valueOf(0x80_00_00_00L); | ||
BigInteger value = BigInteger.ZERO; | ||
|
||
for (int placeholder : placeholders) { | ||
value = value.multiply(twoPow31); | ||
value = value.add(BigInteger.valueOf(placeholder)); | ||
} | ||
|
||
final int base = fullCharSet ? 39 : 27; | ||
final BigInteger divisor = BigInteger.valueOf(base); | ||
final var characters = new ArrayList<Character>(); | ||
|
||
while (value.compareTo(BigInteger.ZERO) > 0) { | ||
value = value.subtract(BigInteger.ONE); | ||
final BigInteger[] divMod = value.divideAndRemainder(divisor); | ||
|
||
value = divMod[0]; | ||
characters.add(getCharFromValue(divMod[1].intValueExact())); | ||
} | ||
|
||
final var chars = new char[characters.size()]; | ||
for(int i = 0; i < chars.length; i++) { | ||
chars[i] = characters.get(chars.length - i - 1); | ||
} | ||
|
||
System.out.println(new String(chars)); | ||
} | ||
|
||
private static char getCharFromValue(int value) { | ||
if (value < 26) { | ||
return (char) ('a' + value); | ||
} else if (value == 26) { | ||
return '_'; | ||
} else if (value < 37) { | ||
return (char) ('0' + value - 27); | ||
} else if (value == 37) { | ||
return '-'; | ||
} else { | ||
return '.'; | ||
} | ||
} | ||
} |