├── .gitignore
├── README.md
├── base64
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ ├── com
│ │ └── joad
│ │ │ └── jdz
│ │ │ └── base64
│ │ │ ├── Base64Decoder.java
│ │ │ ├── Base64Encoder.java
│ │ │ ├── Base64Tables.java
│ │ │ ├── scalar
│ │ │ ├── Base64Scalar.java
│ │ │ ├── RFC2045ScalarDecoder.java
│ │ │ ├── RFC2045ScalarEncoder.java
│ │ │ ├── RFC4648ScalarDecoder.java
│ │ │ ├── RFC4648ScalarEncoder.java
│ │ │ ├── RFC4648URLScalarDecoder.java
│ │ │ ├── RFC4648URLScalarEncoder.java
│ │ │ ├── ScalarDecoderVars.java
│ │ │ └── ScalarUtils.java
│ │ │ └── vector
│ │ │ ├── Base64Vector.java
│ │ │ ├── RFC2045VectorDecoder.java
│ │ │ ├── RFC2045VectorEncoder.java
│ │ │ ├── RFC4648URLVectorDecoder.java
│ │ │ ├── RFC4648URLVectorEncoder.java
│ │ │ ├── RFC4648VectorDecoder.java
│ │ │ ├── RFC4648VectorEncoder.java
│ │ │ ├── ScalarUtils.java
│ │ │ ├── VectorDecoderVars.java
│ │ │ ├── VectorEncoderVars.java
│ │ │ ├── VectorSpeciesSelection.java
│ │ │ └── VectorUtils.java
│ │ └── module-info.java
│ └── test
│ └── java
│ └── com
│ └── joad
│ └── jdz
│ └── base64
│ ├── dev
│ └── LengthFuzzTest.java
│ ├── scalar
│ ├── RFC2045FastScalarDecodeTest.java
│ ├── RFC2045ScalarDecodeTest.java
│ ├── RFC2045ScalarEncodeTest.java
│ ├── RFC4648FastScalarDecodeTest.java
│ ├── RFC4648ScalarDecodeTest.java
│ ├── RFC4648ScalarEncodeTest.java
│ ├── RFC4648URLFastScalarDecodeTest.java
│ ├── RFC4648URLScalarDecodeTest.java
│ └── RFC4648URLScalarEncodeTest.java
│ └── vector
│ ├── RFC2045FastVectorDecodeTest.java
│ ├── RFC2045VectorDecodeTest.java
│ ├── RFC2045VectorEncodeTest.java
│ ├── RFC4648FastVectorDecodeTest.java
│ ├── RFC4648URLFastVectorDecodeTest.java
│ ├── RFC4648URLVectorDecodeTest.java
│ ├── RFC4648URLVectorEncodeTest.java
│ ├── RFC4648VectorDecodeTest.java
│ └── RFC4648VectorEncodeTest.java
├── bench
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── joad
│ └── jdz
│ └── bench
│ ├── BenchmarkBase.java
│ └── base64
│ ├── Base64DecodeBenchmark.java
│ ├── Base64EncodeBenchmark.java
│ ├── Base64MimeDecodeBenchmark.java
│ └── Base64MimeEncodeBenchmark.java
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | */target
2 | *.flattened-pom.xml
3 | *.jar
4 | .vscode
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This library contains Base64 encoders and decoders implemented using the incubator Vector API, as well as (slower) scalar implementations. This is the fastest Java-written Base64 library, with both the vector-based and scalar methods outperforming any other Java written library. These methods are faster than intrinsified java.util for RFC2045/MIME encoding/decoding, but slower for RFC4648 (see "java.util Intrinsification" and "Benchmark" sections). Requires Java 16 or higher.
2 |
3 | The encoding and decoding methods used for the Vector implementation, which can be found in VectorUtils.java, were heavily inspired by Wojciech Mula's articles, available here:
4 |
5 | http://0x80.pl/notesen/2016-01-12-sse-base64-encoding.html
6 |
7 | http://0x80.pl/notesen/2016-01-17-sse-base64-decoding.html
8 |
9 | # Usage
10 | As the Vector API is currently an incubator project, you will need to add the flag `--add-modules jdk.incubator.vector` to your java run command in order to use this library's vector methods.
11 |
12 | This library will be hosted on the central Maven repository once the Vector API is officially released. In the meanwhile this may only be used via local installation.
13 |
14 | ## Decoder/Encoder Instantiation
15 | For convenience, statically instantiated encoders/decoders can be accessed via the Base64Vector and Base64Scalar classes. You may also instantiate the indidual encoders/decoders yourself.
16 |
17 | ## Fast vs Normal Decode
18 | The fast decode methods assume that input is valid Base64 encoded according to the relevant spec. The normal decode methods do not, and handle invalid input explicitly.
19 |
20 | For RFC4648 decoding, the normal decode methods will throw an IllegalArgumentException in the case that an invalid byte is detected, with an exception message that includes the position of the first invalid byte. With RFC2045 decoding, the invalid input bytes are simply ignored (as long as total valid input length is divisible by 4).
21 |
22 | Using the fast decoding methods on invalid Base64 input will likely result in either an ArrayOutOfBoundsException due to invalid lookup table indices/invalid encoded input length, or in silently erroneous output.
23 |
24 | ## Vector Sizing
25 | Java should select the optimal vector size thanks to the use of the Vector API's SPECIES_PREFERRED. However, this may not select the optimal vector size on certain systems.
26 |
27 | The automated vector length selection can be overriden with the `jdz.vector.size` system property, which may be set to values 128, 256 or 512, representing the vector bit size. Selecting a value greater than what your CPU supports will make encoding/decoding 100-1000x slower. Experiment with this value if the library appears suspiciously slow.
28 |
29 | # java.util Intrinsification
30 |
31 | The java.util `encode` and `decode` methods rely on the use of an `encodeBlock` and `decodeBlock` method. These methods are both intrinsinc candidates since Java 11 and 16 respectively, meaning that the JVM can replace them with [an extremely fast SIMD method](https://github.com/openjdk/jdk/blob/a59c9b2ac277d6ff6be1700d91ff389f137e61ca/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp#L6063). From my testing, these methods get intrinsifed after around 5000 calls in a JMH benchmark. So how many bytes need to be decoded in order to hit 5000 calls to these methods?
32 |
33 | If you're encoding or decoding according the RFC4648/RFC4648_URL spec, the intrinsic methods get called once for each call to `encode` or `decode`, which obviously allows for the fastest speeds as this minimizes callbacks into Java. Unfortunately, this means that the high level methods must be called ~5000 times before users benefit from intrinsification (*). If you are working with large arrays, this can take a while: 33 seconds of continuous encoding of 10MB arrays were required for the java.util encoding to intrinsify on my M1 mac. Similarly, if your application does not encode/decode 5000+ times in its lifetime, you will never benefit from this. If your application is encoding/decoding base64 sparsely rather than continuously, this might also impede intrinsification.
34 |
35 | The java.util RFC2045 methods are more consistent in their intrinsification and unaffected by input size. The encoding method will encode data in 76 byte blocks, before return to Java to write linebreak characters, while the decoding method will return to Java on each invalid base64 character (which includes linebreak characters every 76 bytes). Although this guarantees faster intrinsification due to the IntrinsicCandidate methods being called at least once per 76 bytes of input, this slows down the methods considerably, allowing the jdz vector implementation to be faster.
36 |
37 | Intrinsification also does not necessarily occur on every system or JVM. For example, the java.util methods were not intrinsified on an AWS m4.large or on my VMWare Ubuntu VM. As a result, jdz methods strongly outperform java.util on any such system, as java.util will be performing scalar encoding/decoding.
38 |
39 | # Benchmarks
40 | Benchmarks were all ran on Java 20 (Temurin), using non byte array allocating methods for all libraries supporting this. These are JMH benchmarks consisting of 3 forks of 5 warmups and 5 iterations. All benchmarks were measured for size of unencoded data, input size for encoding and output size for decoding.
41 |
42 | The overall theme in these benchmarks is that it is hard to predict relative performance of jdz vs java.util across different architectures. If your application is dependent on efficient base64 encoding, make sure to test your system yourself to determine what is fastest.
43 |
44 | jdz scalar methods are generally the best performing scalar methods for both specs and all architectures - however, these were mostly implemented for reference, and are only worth using over the vector/java.util methods if your cpu does not support 128+ bit vector sizes/does not intrinsify java.util.
45 |
46 | As a quick summary, the following table presents the generally fastest library for each spec/method combo. The overall benchmarks assume that java.util is intrinsified - if this is not the case, the jdz vector methods will always be fastest.
47 |
48 | | Spec/Method | Overall Encoding | Overall Fast Decoding | Overall Decoding | Scalar Encoding | Scalar Decoding | Scalar Fast Decoding |
49 | |-------------|----------------------|-----------------------|------------------|-----------------|-----------------|----------------------|
50 | | RFC4648 | java.util | java.util | java.util | jdz scalar | jdz scalar | jdz scalar |
51 | | RFC2045 | jdz vector/java.util | jdz vector | jdz vector | jdz scalar | jdz scalar/java.util | jdz scalar |
52 |
53 | ## Throughput
54 | These benchmarks represent MB/s throughput of encoding/decoding methods given 1MB inputs. java.util scalar throughput was meansured by disabling intrinsification.
55 |
56 | ### RFC4648
57 | #### RFC4648 Encoding
58 | | | java.util scalar | java.util intrinsic | jdz vector | jdz scalar | migBase64 | iharder | Apache Commons |
59 | |---------------------------------|------------------|---------------------|------------|------------|-----------|----------|----------------|
60 | | Apple M1 (128 bits) | 1707MB/s | 16126MB/s | 6277MB/s | 2845MB/s | 1793MB/s | 1560MB/s | 165MB/s |
61 | | Vs Java Scalar | 1.00x | 9.45x | 3.68x | 1.67x | 1.05x | 0.91x | 0.10x |
62 | | vs Java Intrinsic | 0.11x | 1.00x | 0.39x | 0.18x | 0.11x | 0.10x | 0.01x |
63 | | m4.large (256 bits) | 886MB/s | N/A | 1515MB/s | 1171MB/s | 609MB/s | 567MB/s | 133MB/s |
64 | | vs Java Scalar | 1.0x | N/A | 1.70x | 1.32x | 0.69x | 0.64x | 0.15x |
65 | | vs Java Intrinsic | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
66 | | m6i.large | 1441MB/s | 12644MB/s | 10891MB/s | 2018MB/s | 954MB/s | 984MB/s | 178MB/s |
67 | | vs Java Scalar | 1.0x | 8.77x | 7.56x | 1.40x | 0.66x | 0.68x | 0.12x |
68 | | vs Java Intrinsic | 0.11x | 1.0x | 0.86x | 0.16x | 0.06x | 0.08x | 0.01x |
69 |
70 | ### RFC4648 Decoding
71 | | | java.util scalar | java.util intrinsic | jdz vector | jdz vector fast | jdz scalar | jdz scalar fast | migBase64 | migBase64 fast | iharder | Apache Commons |
72 | |---------------------------------|------------------|---------------------|------------|-----------------|------------|-----------------|-----------|----------------|---------|----------------|
73 | | Apple M1 (128 bits) | 1478MB/s | 9149MB/s | 4613MB/s | 6801MB/s | 2503MB/s | 2777MB/s | 637MB/s | 1096MB/s | 323MB/s | 266MB/s |
74 | | Vs Java Scalar | 1.00x | 6.19x | 3.12x | 4.60x | 1.69x | 1.88x | 0.43x | 0.74x | 0.22x | 0.18x |
75 | | vs Java Intrinsic | 0.17x | 1.00x | 0.50x | 0.74x | 0.27x | 0.30x | 0.07x | 0.12x | 0.04x | 0.03x |
76 | | m4.large (256 bits) | 799MB/s | N/A | 1453MB/s | 2434MB/s | 1105MB/s | 1066MB/s | 289MB/s | 479MB/s | 139MB/s | 120MB/s |
77 | | vs Java Scalar | 1.00x | N/A | 1.82x | 0.30x | 1.38x | 1.33x | 0.36x | 0.60x | 0.17x | 0.20x |
78 | | vs Java Intrinsic | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
79 | | m6i.large | 1360MB/s | 14884MB/s | 6585MB/s | 9258MB/s | 1270MB/s | 1351MB/s | 363MB/s | 791MB/s | 218MB/s | 194MB/s |
80 | | vs Java Scalar | 1.00x | 10.20x | 4.85x | 6.80x | 0.93x | 0.99x | 0.26x | 0.58x | 0.16x | 0.14x |
81 | | vs Java Intrinsic | 0.09x | 1.00x | 0.44x | 0.62x | 0.09x | 0.09x | 0.02x | 0.05x | 0.01x | 0.01x |
82 |
83 | ### RFC2045
84 | #### RFC2045 Encoding
85 | | | java.util scalar | java.util intrinsic | jdz vector | jdz scalar | migBase64 | iharder | Apache Commons |
86 | |---------------------------------|------------------|---------------------|------------|------------|-----------|----------|----------------|
87 | | Apple M1 (128 bits) | 1466MB/s | 5721MB/s | 5814MB/s | 2704MB/s | 1572MB/s | 1540MB/s | 171MB/s |
88 | | Vs Java Scalar | 1.0x | 3.90x | 3.97x | 1.84x | 1.07x | 1.05x | 0.12x |
89 | | vs Java Intrinsic | 0.26x | 1.0x | 1.03x | 0.48x | 0.28x | 0.27x | 0.03x |
90 | | m4.large (256 bits) | 686MB/s | N/A | 1192MB/s | 1087MB/s | 464MB/s | 494MB/s | 125MB/s |
91 | | vs Java Scalar | 1.0x | N/A | 1.74x | 1.58x | 0.67x | 0.72x | 0.18x |
92 | | vs Java Intrinsic | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
93 | | m6i.large | 1129MB/s | 3526MB/s | 5722MB/s | 1859MB/s | 861MB/s | 872MB/s | 178MB/s |
94 | | vs Java Scalar | 1.0x | 3.12x | 5.07x | 1.65x | 0.76x | 0.77x | 0.16x |
95 | | vs Java Intrinsic | 0.32x | 1.0x | 1.622x | 0.52x | 0.24x | 0.25 | 0.05x |
96 |
97 | #### RFC2045 Decoding
98 | | | java.util scalar | java.util intrinsic | jdz vector | jdz vector fast | jdz scalar | jdz scalar fast | migBase64 | migBase64 fast | iharder | Apache Commons |
99 | |---------------------------------|------------------|---------------------|------------|-----------------|------------|-----------------|-----------|----------------|---------|----------------|
100 | | Apple M1 (128 bits) | 716MB/s | 919MB/s | 1805MB/s | 6685MB/s | 757MB/s | 2728MB/s | 390MB/s | 928MB/s | 305MB/s | 255MB/s |
101 | | Vs Java Scalar | 1.00x | 1.28x | 2.52x | 9.33x | 1.06x | 3.81x | 0.54x | 1.29x | 0.42x | 0.35x |
102 | | vs Java Intrinsic | 0.78x | 1.00x | 1.96x | 7.27x | 0.82x | 2.97x | 0.42x | 1.01x | 0.33x | 0.28x |
103 | | m4.large (256 bits) | 433MB/s | N/A | 731MB/s | 1809MB/s | 412MB/s | 1157MB/s | 197MB/s | 479MB/s | 138MB/s | 120MB/s |
104 | | vs Java Scalar | 1.00x | N/A | 1.67x | 4.17x | 0.95x | 2.67x | 0.45x | 1.10x | 0.32x | 0.28x |
105 | | vs Java Intrinsic | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A | N/A |
106 | | m6i.large | 652MB/s | 761MB/s | 1729MB/s | 5077MB/s | 583MB/s | 1351/MB/s | 393MB/s | 791MB/s | 218MB/s | 195MB/s |
107 | | vs Java Scalar | 1.00x | 1.17x | 2.65x | 7.79x | 0.89x | 2.07x | 0.60x | 1.21x | 0.33x | 0.30x |
108 | | vs Java Intrinsic | 0.86x | 1.00x | 2.27x | 6.77x | 0.77x | 1.77x | 0.52x | 1.04x | 0.29x | 0.26x |
109 |
110 | ## Vector Sizing
111 | This benchmark measures different vector sizes on a system supporting up to 512 bits (m6i.large). As expected, the largest supported vector size is fastest, and this is naturally the one automatically selected via use of SPECIES_PREFERRED.
112 |
113 | | Method/Vector Size | 128 bits | 256 bits | 512 bits |
114 | |--------------------|----------|----------|-----------|
115 | | RFC4648 encode | 4000MB/s | 6733MB/s | 11157MB/s |
116 | | RFC4648 decode | 2457MB/s | 3945MB/s | 5491MB/s |
117 | | RFC4648 decodeFast | 3517MB/s | 5646MB/s | 9128MB/s |
118 | | RFC2045 encode | 3099MB/s | 4926MB/s | 5724MB/s |
119 | | RFC2045 decode | 1150MB/s | 1482MB/s | 1730MB/s |
120 | | RFC2045 decodeFast | 2965MB/s | 4224MB/s | 6733MB/s |
121 |
122 | ## Unencoded Length Benchmarks
123 | The following benchmarks measure the time per operation to encode/decode a certain unencoded length - lower is better. These were all carried out on an M1 mac using 128 bit vectors.
124 |
125 | ### RFC4648
126 |
127 | #### RFC4648 Encoding
128 |
129 | | Method/Unencoded Length | 10B | 100B | 1KB | 1MB | 10MB | 100MB |
130 | |-------------------|------|------|-------|-------|--------|---------|
131 | | jdz-scalar encode | 11ns | 48ns | 343ns | 346µs | 3486µs | 34.88ms |
132 | | jdz-vector encode | 11ns | 40ns | 195ns | 142µs | 1447µs | 14.31ms |
133 | | java.util encode | 11ns | 15ns | 73ns | 60µs | 5784µs | 57.81ms |
134 | | migBase64 encode | 22ns | 64ns | 562ns | 545µs | 5498µs | 55.12ms |
135 |
136 | #### RFC4648 Decoding
137 | | Method/Unencoded Length | 10B | 100B | 1KB | 1MB | 10MB | 100MB
138 | |-----------------------|------|-------|--------|--------|---------|---------
139 | | jdz-scalar decode | 11ns | 55ns | 409ns | 405µs | 4079µs | 40.76ms |
140 | | jdz-scalar decodeFast | 11ns | 52ns | 371ns | 364µs | 3673µs | 36.79ms |
141 | | jdz-vector decode | 12ns | 52ns | 299ns | 205µs | 2088µs | 20.90ms |
142 | | jdz-vector decodeFast | 11ns | 43ns | 170ns | 139µs | 1409µs | 14.02ms |
143 | | java.util decode | 14ns | 49ns | 138ns | 109µs | 6727µs | 66.92ms |
144 | | migBase64 decode | 30ns | 157ns | 1472ns | 1554µs | 15673µs | 171.8ms |
145 | | migBase64 decodeFast | 28ns | 104ns | 955ns | 894µs | 9000µs | 98.96ms |
146 |
147 | As only 5 warmups were performed, we can see java.util methods cease to be intrinsified for 10MB+ data (see "java.util Intrinsification").
148 |
149 | ### RFC2045 (MIME)
150 |
151 | #### RFC2045 Encoding
152 | | Method/Unencoded Length | 10B | 100B | 1KB | 1MB | 10MB | 100MB |
153 | |-------------------|------|------|-------|-------|--------|---------|
154 | | jdz-scalar encode | 10ns | 50ns | 349ns | 358µs | 3799us | 39.80ms |
155 | | jdz-vector encode | 10ns | 38ns | 179ns | 169µs | 1887µs | 20.78ms |
156 | | java.util encode | 12ns | 28ns | 181ns | 171µs | 1767µs | 17.30ms |
157 | | migBase64 encode | 16ns | 72ns | 644ns | 620µs | 6239µs | 62.39ms |
158 |
159 | #### RFC2045 Decoding
160 | | Method/Unencoded Length | 10B | 100B | 1KB | 1MB | 10MB | 100MB |
161 | |-----------------------|-------|-------|---------|--------|---------|-------|
162 | | jdz-scalar decode | 29ns | 247ns | 2.64µs | 1608µs | 16.12ms | 133.60ms |
163 | | jdz-scalar decodeFast | 22ns | 49ns | 376ns | 358µs | 3.569ms | 36.06ms |
164 | | jdz-vector decode | 29ns | 61ns | 575ns | 564µs | 5.698ms | 57.258ms |
165 | | jdz-vector decodeFast | 23ns | 38ns | 167ns | 151µs | 1.528ms | 14.77ms |
166 | | java.util decode | 29ns | 132ns | 1284ns | 1087µs | 10.92ms | 135.35ms |
167 | | migBase64 decode | 408ns | 306ns | 2.89µs | 2383µs | 24.11ms | 286.59ms |
168 | | migBase64 decodeFast | 29ns | 105ns | 987ns | 1052µs | 10.72ms | 125.53ms |
169 |
170 |
--------------------------------------------------------------------------------
/base64/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 4.0.0
5 |
6 | com.joad.jdz
7 | jdz-parent
8 | 1.0
9 | ../pom.xml
10 |
11 |
12 | jdz-base64
13 |
14 | jdz base64
15 |
16 |
17 |
18 | junit
19 | junit
20 | ${junit.version}
21 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/Base64Decoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64;
2 |
3 | import java.nio.charset.StandardCharsets;
4 |
5 | public abstract class Base64Decoder {
6 |
7 | /**
8 | * Returns a newly allocated byte[] representing base64 decoded source.
9 | *
10 | * @param src the data to be decoded
11 | *
12 | * @return the decoded data
13 | */
14 | public byte[] decode(byte[] src) {
15 | int pad = getPadLength(src);
16 | int dl = getDecodedLength(src, pad);
17 |
18 | int sl = src.length - pad;
19 |
20 | byte[] dst = new byte[dl];
21 |
22 | decode(src, dst, sl, dl);
23 |
24 | return dst;
25 | }
26 |
27 | /**
28 | * Decodes base64 data from src to dst.
29 | *
30 | * @param src the data to be decoded
31 | * @param dst the byte array to write to
32 | *
33 | * @return the decoded data
34 | */
35 | public int decode(byte[] src, byte[] dst) {
36 | int pad = getPadLength(src);
37 | int dl = getDecodedLength(src, pad);
38 |
39 | int sl = src.length - pad;
40 |
41 | return decode(src, dst, sl, dl);
42 | }
43 |
44 | /**
45 | * Returns a newly allocated byte[] representing base64 decoded source.
46 | * Assumes that input is valid.
47 | *
48 | * @param src the data to be decoded
49 | *
50 | * @return the decoded data
51 | */
52 | public byte[] decodeFast(byte[] src) {
53 | int pad = getPadLength(src);
54 | int dl = getDecodedLengthFast(src, pad);
55 |
56 | int sl = src.length - pad;
57 |
58 | byte[] dst = new byte[dl];
59 |
60 | decodeFast(src, dst, sl, dl);
61 |
62 | return dst;
63 | }
64 |
65 | /**
66 | * Decodes base64 data from src to dst.
67 | * Assumes that input is valid.
68 | *
69 | * @param src the data to be decoded
70 | * @param dst the byte array to write to
71 | *
72 | * @return the decoded data
73 | */
74 | public int decodeFast(byte[] src, byte[] dst) {
75 | int pad = getPadLength(src);
76 | int dl = getDecodedLengthFast(src, pad);
77 |
78 | int sl = src.length - pad;
79 |
80 | return decodeFast(src, dst, sl, dl);
81 | }
82 |
83 | /**
84 | * Calculates decoded length for src
85 | *
86 | * @param src the data to be decoded
87 | *
88 | * @return the decoded length
89 | */
90 | public int getDecodedLength(byte[] src) {
91 | int pad = getPadLength(src);
92 |
93 | return getDecodedLength(src, pad);
94 | }
95 |
96 | protected abstract int getDecodedLength(byte[] src, int pad);
97 |
98 | /**
99 | * Calculates decoded length for src
100 | * Assumes that input is valid - works for standard and url encoding
101 | *
102 | * @param src the data to be decoded
103 | *
104 | * @return the decoded length
105 | */
106 | public int getDecodedLengthFast(byte[] src) {
107 | int pad = getPadLength(src);
108 |
109 | return getDecodedLengthFast(src, pad);
110 | }
111 |
112 | protected abstract int getDecodedLengthFast(byte[] src, int pad);
113 |
114 | /**
115 | * Returns a newly allocated byte[] representing base64 decoded source.
116 | *
117 | * @param src the data to be decoded
118 | *
119 | * @return the decoded data
120 | */
121 | public byte[] decode(String src) {
122 | return decode(src.getBytes(StandardCharsets.ISO_8859_1));
123 | }
124 |
125 | /**
126 | * Decodes base64 data from src to dst.
127 | *
128 | * @param src the data to be decoded
129 | * @param dst the byte array to write to
130 | *
131 | * @return the decoded data
132 | */
133 | public int decode(String src, byte[] dst) {
134 | return decode(src.getBytes(StandardCharsets.ISO_8859_1), dst);
135 | }
136 |
137 | private int getPadLength(byte[] src) {
138 | int sl = src.length;
139 |
140 | return sl > 0 && src[sl - 1] == '=' ? (src[sl - 2] == '=' ? 2 : 1) : 0;
141 | }
142 |
143 | protected abstract int decode(byte[] src, byte[] dst, int sl, int dl);
144 |
145 | protected abstract int decodeFast(byte[] src, byte[] dst, int sl, int dl);
146 | }
147 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/Base64Encoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64;
2 |
3 | import java.nio.charset.StandardCharsets;
4 |
5 | public abstract class Base64Encoder {
6 |
7 | /**
8 | * Returns a newly allocated byte[] representing base64 encoded source.
9 | *
10 | * @param src the data to be encoded
11 | *
12 | * @return the base64 encoded data
13 | */
14 | public byte[] encode(byte[] src) {
15 | int dl = getEncodedLength(src);
16 |
17 | byte[] dst = new byte[dl];
18 |
19 | encode(src, dst);
20 |
21 | return dst;
22 | }
23 |
24 | /**
25 | * Writes base64 encoded data from src to dst.
26 | *
27 | * @param src the data to be encoded
28 | * @param dst the byte array to write to
29 | *
30 | * @return the length of encoded data
31 | */
32 | public abstract int encode(byte[] src, byte[] dst);
33 |
34 | /**
35 | * Calculates encoded length for src
36 | *
37 | * @param src the data to be encoded
38 | *
39 | * @return the encoded length
40 | */
41 | public abstract int getEncodedLength(byte[] src);
42 |
43 | /**
44 | * Returns a newly allocated byte[] representing base64 encoded source.
45 | *
46 | * @param src the data to be encoded
47 | *
48 | * @return the length of encoded data
49 | */
50 | public byte[] encode(String src) {
51 | return encode(src.getBytes(StandardCharsets.ISO_8859_1));
52 | }
53 |
54 | /**
55 | * Writes base64 encoded data from src to dst.
56 | *
57 | * @param src the data to be encoded
58 | * @param dst the byte array to write to
59 | *
60 | * @return the base64 encoded data
61 | */
62 |
63 | public int encode(String src, byte[] dst) {
64 | return encode(src.getBytes(StandardCharsets.ISO_8859_1), dst);
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/Base64Tables.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64;
2 |
3 | public class Base64Tables {
4 | public static final char[] BASE64 = {
5 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
6 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
7 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
8 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
9 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
10 | };
11 |
12 | public static final char[] BASE64_URL = {
13 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
14 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
15 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
16 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
17 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_'
18 | };
19 | }
20 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/scalar/Base64Scalar.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import com.joad.jdz.base64.Base64Decoder;
4 | import com.joad.jdz.base64.Base64Encoder;
5 |
6 | public class Base64Scalar {
7 | private static final Base64Encoder RFC4648_ENCODER = new RFC4648ScalarEncoder();
8 |
9 | private static final Base64Encoder RFC4648URL_ENCODER = new RFC4648URLScalarEncoder();
10 |
11 | private static final Base64Encoder RFC2045_ENCODER = new RFC2045ScalarEncoder();
12 |
13 | private static final Base64Decoder RFC4648_DECODER = new RFC4648ScalarDecoder();
14 |
15 | private static final Base64Decoder RFC4648URL_DECODER = new RFC4648URLScalarDecoder();
16 |
17 | private static final Base64Decoder RFC2045_DECODER = new RFC2045ScalarDecoder();
18 |
19 | /**
20 | * Encoder for the RFC4648 Base64 spec
21 | *
22 | * @return An RFC4648 Base64 Encoder
23 | */
24 | public static Base64Encoder getEncoder() {
25 | return RFC4648_ENCODER;
26 | }
27 |
28 | /**
29 | * Encoder for the RFC4648URL Base64 spec
30 | *
31 | * @return An RFC4648 Base64 Encoder
32 | */
33 | public static Base64Encoder getUrlEncoder() {
34 | return RFC4648URL_ENCODER;
35 | }
36 |
37 | /**
38 | * Encoder for the RFC2045 Base64 spec
39 | *
40 | * @return An RFC42045 Base64 encoder
41 | */
42 | public static Base64Encoder getMimeEncoder() {
43 | return RFC2045_ENCODER;
44 | }
45 |
46 | /**
47 | * Decoder for the RFC4648 Base64 spec
48 | *
49 | * @return An RFC4648 Base64 decoder
50 | */
51 | public static Base64Decoder getDecoder() {
52 | return RFC4648_DECODER;
53 | }
54 |
55 | /**
56 | * Decoder for the RFC4648 URL Base64 spec
57 | *
58 | * @return An RFC4648 URL Base64 decoder
59 | */
60 | public static Base64Decoder getUrlDecoder() {
61 | return RFC4648URL_DECODER;
62 | }
63 |
64 | /**
65 | * Decoder for the RFC2045 Base64 spec
66 | *
67 | * @return An RFC2045 Base64 fast encoder
68 | */
69 | public static Base64Decoder getMimeDecoder() {
70 | return RFC2045_DECODER;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/scalar/RFC2045ScalarDecoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static com.joad.jdz.base64.scalar.ScalarUtils.*;
4 | import static com.joad.jdz.base64.Base64Tables.*;
5 | import static com.joad.jdz.base64.scalar.ScalarDecoderVars.*;
6 |
7 | import java.util.Arrays;
8 | import com.joad.jdz.base64.Base64Decoder;
9 |
10 | public class RFC2045ScalarDecoder extends Base64Decoder {
11 | private static final int[] SIMPLE_LOOKUP = new int[256];
12 |
13 | static {
14 | Arrays.fill(SIMPLE_LOOKUP, -1);
15 | for (int i = 0; i < 64; i++)
16 | SIMPLE_LOOKUP[BASE64[i]] = i;
17 | }
18 |
19 | @Override
20 | protected int decode(byte[] src, byte[] dst, int sl, int dl) {
21 | int sp = 0;
22 | int dp = 0;
23 |
24 | while (dp < dl - 3) {
25 | int bits = LOOKUP[0][src[sp++]]
26 | | LOOKUP[1][src[sp++]]
27 | | LOOKUP[2][src[sp++]]
28 | | LOOKUP[3][src[sp++]];
29 |
30 | if (bits > VALID_MAX) {
31 | sp -= 4;
32 |
33 | bits = LOOKUP[0][src[sp++]];
34 |
35 | if (bits > VALID_MAX)
36 | continue;
37 |
38 | for (int i = 1; i < 4;) {
39 | int b = LOOKUP[i][src[sp++]];
40 |
41 | if (b < VALID_MAX) {
42 | bits |= b;
43 | i++;
44 | }
45 | }
46 | }
47 |
48 | INT_LE.set(dst, dp, bits);
49 |
50 | dp += 3;
51 | }
52 |
53 | int remaining = dl - dp;
54 |
55 | return switch (remaining) {
56 | case 3 -> decodeLastThreeDestBytesMime(src, dst, LOOKUP, sp, dp);
57 | case 2 -> decodeLastTwoDestBytesMime(src, dst, LOOKUP, sp, dp);
58 | case 1 -> decodeLastDestByteMime(src, dst, LOOKUP, sp, dp);
59 | default -> dp;
60 | };
61 | }
62 |
63 | @Override
64 | protected int decodeFast(byte[] src, byte[] dst, int sl, int dl) {
65 | int sp = 0;
66 | int dp = 0;
67 |
68 | for (; dp < dl - 57; sp += 78, dp += 57) {
69 | decodeEightBytes(src, dst, LOOKUP, sp, dp);
70 | decodeEightBytes(src, dst, LOOKUP, sp + 8, dp + 6);
71 | decodeEightBytes(src, dst, LOOKUP, sp + 16, dp + 12);
72 | decodeEightBytes(src, dst, LOOKUP, sp + 24, dp + 18);
73 | decodeEightBytes(src, dst, LOOKUP, sp + 32, dp + 24);
74 | decodeEightBytes(src, dst, LOOKUP, sp + 40, dp + 30);
75 | decodeEightBytes(src, dst, LOOKUP, sp + 48, dp + 36);
76 | decodeEightBytes(src, dst, LOOKUP, sp + 56, dp + 42);
77 | decodeEightBytes(src, dst, LOOKUP, sp + 64, dp + 48);
78 | decodeFourBytes(src, dst, LOOKUP, sp + 72, dp + 54);
79 | }
80 |
81 | for (; sp < sl - 4; sp += 4, dp += 3) {
82 | decodeFourBytes(src, dst, LOOKUP, sp, dp);
83 | }
84 |
85 | int remaining = sl - sp;
86 |
87 | return switch (remaining) {
88 | case 4 -> decodeLastFourBytes(src, dst, LOOKUP, sp, dp);
89 | case 3 -> decodeLastThreeBytes(src, dst, LOOKUP, sp, dp);
90 | case 2 -> decodeLastTwoBytes(src, dst, LOOKUP, sp, dp);
91 | default -> dp;
92 | };
93 | }
94 |
95 | @Override
96 | protected int getDecodedLength(byte[] src, int pad) {
97 | int sl = src.length;
98 |
99 | int invalid = 0;
100 |
101 | for (int sp = 0; sp < sl - pad; sp++) {
102 | if (SIMPLE_LOOKUP[src[sp]] < 0)
103 | invalid++;
104 | }
105 |
106 | int vsl = sl - invalid;
107 |
108 | if ((vsl & MOD4) != 0)
109 | throw new IllegalArgumentException("Number of valid input bytes not divisible by 4");
110 |
111 | return vsl / 4 * 3 - pad;
112 | }
113 |
114 | @Override
115 | protected int getDecodedLengthFast(byte[] src, int pad) {
116 | int sl = src.length;
117 |
118 | int vsl = sl - (sl/78) * 2;
119 |
120 | if ((vsl & MOD4) != 0)
121 | throw new IllegalArgumentException("Number of valid input bytes not divisible by 4");
122 |
123 | return vsl / 4 * 3 - pad;
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/scalar/RFC2045ScalarEncoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static com.joad.jdz.base64.Base64Tables.*;
4 | import static com.joad.jdz.base64.scalar.ScalarUtils.*;
5 |
6 | import com.joad.jdz.base64.Base64Encoder;
7 |
8 | public class RFC2045ScalarEncoder extends Base64Encoder {
9 |
10 | @Override
11 | public int encode(byte[] src, byte[] dst) {
12 | int sl = src.length;
13 |
14 | int sp = 0;
15 | int dp = 0;
16 |
17 | for (int ldp = 76; ldp < dst.length; ldp += 78) {
18 | dst[ldp] = '\r';
19 | dst[ldp+1] = '\n';
20 | }
21 |
22 | for (; sp < src.length - 57; sp += 57, dp += 78) {
23 | encodeSixBytes(src, dst, BASE64, sp, dp);
24 | encodeSixBytes(src, dst, BASE64, sp + 6, dp + 8);
25 | encodeSixBytes(src, dst, BASE64, sp + 12, dp + 16);
26 | encodeSixBytes(src, dst, BASE64, sp + 18, dp + 24);
27 | encodeSixBytes(src, dst, BASE64, sp + 24, dp + 32);
28 | encodeSixBytes(src, dst, BASE64, sp + 30, dp + 40);
29 | encodeSixBytes(src, dst, BASE64, sp + 36, dp + 48);
30 | encodeSixBytes(src, dst, BASE64, sp + 42, dp + 56);
31 | encodeSixBytes(src, dst, BASE64, sp + 48, dp + 64);
32 | encodeThreeBytes(src, dst, BASE64, sp + 54, dp + 72);
33 | }
34 |
35 | for (; sp < src.length - 3; sp += 3, dp += 4) {
36 | encodeThreeBytes(src, dst, BASE64, sp, dp);
37 | }
38 |
39 | int remaining = sl - sp;
40 |
41 | return switch (remaining) {
42 | case 3 -> encodeLastThreeBytes(src, dst, BASE64, sp, dp);
43 | case 2 -> encodeLastTwoBytes(src, dst, BASE64, sp, dp);
44 | case 1 -> encodeLastByte(src, dst, BASE64, sp, dp);
45 | default -> dp;
46 | };
47 | }
48 |
49 | @Override
50 | public int getEncodedLength(byte[] src) {
51 | int rawLen = Math.multiplyExact(4, (Math.addExact(src.length, 2) / 3));
52 |
53 | return rawLen + ((rawLen - 1)/76) * 2;
54 | }
55 | }
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/scalar/RFC4648ScalarDecoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static com.joad.jdz.base64.scalar.ScalarDecoderVars.*;
4 | import static com.joad.jdz.base64.scalar.ScalarUtils.*;
5 |
6 | import com.joad.jdz.base64.Base64Decoder;
7 |
8 | public class RFC4648ScalarDecoder extends Base64Decoder {
9 |
10 | @Override
11 | protected int decode(byte[] src, byte[] dst, int sl, int dl) {
12 | int sp = 0;
13 | int dp = 0;
14 |
15 | for (; dp < dl - 57; sp += 76, dp += 57) {
16 | decodeEightBytesValidating(src, dst, LOOKUP, sp, dp);
17 | decodeEightBytesValidating(src, dst, LOOKUP, sp + 8, dp + 6);
18 | decodeEightBytesValidating(src, dst, LOOKUP, sp + 16, dp + 12);
19 | decodeEightBytesValidating(src, dst, LOOKUP, sp + 24, dp + 18);
20 | decodeEightBytesValidating(src, dst, LOOKUP, sp + 32, dp + 24);
21 | decodeEightBytesValidating(src, dst, LOOKUP, sp + 40, dp + 30);
22 | decodeEightBytesValidating(src, dst, LOOKUP, sp + 48, dp + 36);
23 | decodeEightBytesValidating(src, dst, LOOKUP, sp + 56, dp + 42);
24 | decodeEightBytesValidating(src, dst, LOOKUP, sp + 64, dp + 48);
25 | decodeFourBytesValidating(src, dst, LOOKUP, sp + 72, dp + 54);
26 | }
27 |
28 | for (; sp < sl - 4; sp += 4, dp += 3) {
29 | decodeFourBytesValidating(src, dst, LOOKUP, sp, dp);
30 | }
31 |
32 | int remaining = sl - sp;
33 |
34 | return switch (remaining) {
35 | case 4 -> decodeLastFourBytesValidating(src, dst, LOOKUP, sp, dp);
36 | case 3 -> decodeLastThreeBytesValidating(src, dst, LOOKUP, sp, dp);
37 | case 2 -> decodeLastTwoBytesValidating(src, dst, LOOKUP, sp, dp);
38 | default -> dp;
39 | };
40 | }
41 |
42 | @Override
43 | protected int decodeFast(byte[] src, byte[] dst, int sl, int dl) {
44 | int sp = 0;
45 | int dp = 0;
46 |
47 | for (; dp < dl - 57; sp += 76, dp += 57) {
48 | decodeEightBytes(src, dst, LOOKUP, sp, dp);
49 | decodeEightBytes(src, dst, LOOKUP, sp + 8, dp + 6);
50 | decodeEightBytes(src, dst, LOOKUP, sp + 16, dp + 12);
51 | decodeEightBytes(src, dst, LOOKUP, sp + 24, dp + 18);
52 | decodeEightBytes(src, dst, LOOKUP, sp + 32, dp + 24);
53 | decodeEightBytes(src, dst, LOOKUP, sp + 40, dp + 30);
54 | decodeEightBytes(src, dst, LOOKUP, sp + 48, dp + 36);
55 | decodeEightBytes(src, dst, LOOKUP, sp + 56, dp + 42);
56 | decodeEightBytes(src, dst, LOOKUP, sp + 64, dp + 48);
57 | decodeFourBytes(src, dst, LOOKUP, sp + 72, dp + 54);
58 | }
59 |
60 | for (; sp < sl - 4; sp += 4, dp += 3) {
61 | decodeFourBytes(src, dst, LOOKUP, sp, dp);
62 | }
63 |
64 | int remaining = sl - sp;
65 |
66 | return switch (remaining) {
67 | case 4 -> decodeLastFourBytes(src, dst, LOOKUP, sp, dp);
68 | case 3 -> decodeLastThreeBytes(src, dst, LOOKUP, sp, dp);
69 | case 2 -> decodeLastTwoBytes(src, dst, LOOKUP, sp, dp);
70 | default -> dp;
71 | };
72 | }
73 |
74 | @Override
75 | protected int getDecodedLength(byte[] src, int pad) {
76 | int sl = src.length;
77 |
78 | if ((sl & MOD4) != 0)
79 | throw new IllegalArgumentException("Number of input bytes not divisible by 4");
80 |
81 | return sl/4 * 3 - pad;
82 | }
83 |
84 | @Override
85 | protected int getDecodedLengthFast(byte[] src, int pad) {
86 | return getDecodedLength(src, pad);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/scalar/RFC4648ScalarEncoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static com.joad.jdz.base64.scalar.ScalarUtils.*;
4 | import static com.joad.jdz.base64.Base64Tables.*;
5 |
6 | import com.joad.jdz.base64.Base64Encoder;
7 |
8 | public class RFC4648ScalarEncoder extends Base64Encoder {
9 |
10 | @Override
11 | public int encode(final byte[] src, final byte[] dst) {
12 | int sl = src.length;
13 |
14 | int sp = 0;
15 | int dp = 0;
16 |
17 | for (; sp < src.length - 57; sp += 57, dp += 76) {
18 | encodeSixBytes(src, dst, BASE64, sp, dp);
19 | encodeSixBytes(src, dst, BASE64, sp + 6, dp + 8);
20 | encodeSixBytes(src, dst, BASE64, sp + 12, dp + 16);
21 | encodeSixBytes(src, dst, BASE64, sp + 18, dp + 24);
22 | encodeSixBytes(src, dst, BASE64, sp + 24, dp + 32);
23 | encodeSixBytes(src, dst, BASE64, sp + 30, dp + 40);
24 | encodeSixBytes(src, dst, BASE64, sp + 36, dp + 48);
25 | encodeSixBytes(src, dst, BASE64, sp + 42, dp + 56);
26 | encodeSixBytes(src, dst, BASE64, sp + 48, dp + 64);
27 | encodeThreeBytes(src, dst, BASE64, sp + 54, dp + 72);
28 | }
29 |
30 | for (; sp < src.length - 3; sp += 3, dp += 4) {
31 | encodeThreeBytes(src, dst, BASE64, sp, dp);
32 | }
33 |
34 | int remaining = sl - sp;
35 |
36 | return switch (remaining) {
37 | case 3 -> encodeLastThreeBytes(src, dst, BASE64, sp, dp);
38 | case 2 -> encodeLastTwoBytes(src, dst, BASE64, sp, dp);
39 | case 1 -> encodeLastByte(src, dst, BASE64, sp, dp);
40 | default -> dp;
41 | };
42 | }
43 |
44 | @Override
45 | public int getEncodedLength(final byte[] src) {
46 | return Math.multiplyExact(4, (Math.addExact(src.length, 2) / 3));
47 | }
48 | }
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/scalar/RFC4648URLScalarDecoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static com.joad.jdz.base64.scalar.ScalarDecoderVars.*;
4 | import static com.joad.jdz.base64.scalar.ScalarUtils.*;
5 |
6 | import com.joad.jdz.base64.Base64Decoder;
7 |
8 | public class RFC4648URLScalarDecoder extends Base64Decoder {
9 |
10 | @Override
11 | protected int decode(byte[] src, byte[] dst, int sl, int dl) {
12 | int sp = 0;
13 | int dp = 0;
14 |
15 | for (; dp < dl - 57; sp += 76, dp += 57) {
16 | decodeEightBytesValidating(src, dst, LOOKUP_URL, sp, dp);
17 | decodeEightBytesValidating(src, dst, LOOKUP_URL, sp + 8, dp + 6);
18 | decodeEightBytesValidating(src, dst, LOOKUP_URL, sp + 16, dp + 12);
19 | decodeEightBytesValidating(src, dst, LOOKUP_URL, sp + 24, dp + 18);
20 | decodeEightBytesValidating(src, dst, LOOKUP_URL, sp + 32, dp + 24);
21 | decodeEightBytesValidating(src, dst, LOOKUP_URL, sp + 40, dp + 30);
22 | decodeEightBytesValidating(src, dst, LOOKUP_URL, sp + 48, dp + 36);
23 | decodeEightBytesValidating(src, dst, LOOKUP_URL, sp + 56, dp + 42);
24 | decodeEightBytesValidating(src, dst, LOOKUP_URL, sp + 64, dp + 48);
25 | decodeFourBytesValidating(src, dst, LOOKUP_URL, sp + 72, dp + 54);
26 | }
27 |
28 | for (; sp < sl - 4; sp += 4, dp += 3) {
29 | decodeFourBytesValidating(src, dst, LOOKUP_URL, sp, dp);
30 | }
31 |
32 | int remaining = sl - sp;
33 |
34 | return switch (remaining) {
35 | case 4 -> decodeLastFourBytesValidating(src, dst, LOOKUP_URL, sp, dp);
36 | case 3 -> decodeLastThreeBytesValidating(src, dst, LOOKUP_URL, sp, dp);
37 | case 2 -> decodeLastTwoBytesValidating(src, dst, LOOKUP_URL, sp, dp);
38 | default -> dp;
39 | };
40 | }
41 |
42 | @Override
43 | protected int decodeFast(byte[] src, byte[] dst, int sl, int dl) {
44 | int sp = 0;
45 | int dp = 0;
46 |
47 | for (; dp < dl - 57; sp += 76, dp += 57) {
48 | decodeEightBytes(src, dst, LOOKUP_URL, sp, dp);
49 | decodeEightBytes(src, dst, LOOKUP_URL, sp + 8, dp + 6);
50 | decodeEightBytes(src, dst, LOOKUP_URL, sp + 16, dp + 12);
51 | decodeEightBytes(src, dst, LOOKUP_URL, sp + 24, dp + 18);
52 | decodeEightBytes(src, dst, LOOKUP_URL, sp + 32, dp + 24);
53 | decodeEightBytes(src, dst, LOOKUP_URL, sp + 40, dp + 30);
54 | decodeEightBytes(src, dst, LOOKUP_URL, sp + 48, dp + 36);
55 | decodeEightBytes(src, dst, LOOKUP_URL, sp + 56, dp + 42);
56 | decodeEightBytes(src, dst, LOOKUP_URL, sp + 64, dp + 48);
57 | decodeFourBytes(src, dst, LOOKUP_URL, sp + 72, dp + 54);
58 | }
59 |
60 | for (; sp < sl - 4; sp += 4, dp += 3) {
61 | decodeFourBytes(src, dst, LOOKUP_URL, sp, dp);
62 | }
63 |
64 | int remaining = sl - sp;
65 |
66 | return switch (remaining) {
67 | case 4 -> decodeLastFourBytes(src, dst, LOOKUP_URL, sp, dp);
68 | case 3 -> decodeLastThreeBytes(src, dst, LOOKUP_URL, sp, dp);
69 | case 2 -> decodeLastTwoBytes(src, dst, LOOKUP_URL, sp, dp);
70 | default -> dp;
71 | };
72 | }
73 |
74 | @Override
75 | protected int getDecodedLength(byte[] src, int pad) {
76 | int sl = src.length;
77 |
78 | if ((sl & MOD4) != 0)
79 | throw new IllegalArgumentException("Number of input bytes not divisible by 4");
80 |
81 | return sl/4 * 3 - pad;
82 | }
83 |
84 | @Override
85 | protected int getDecodedLengthFast(byte[] src, int pad) {
86 | return getDecodedLength(src, pad);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/scalar/RFC4648URLScalarEncoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static com.joad.jdz.base64.scalar.ScalarUtils.*;
4 | import static com.joad.jdz.base64.Base64Tables.*;
5 |
6 | import com.joad.jdz.base64.Base64Encoder;
7 |
8 | public class RFC4648URLScalarEncoder extends Base64Encoder {
9 |
10 | @Override
11 | public int encode(final byte[] src, final byte[] dst) {
12 | int sl = src.length;
13 |
14 | int sp = 0;
15 | int dp = 0;
16 |
17 | for (; sp < src.length - 57; sp += 57, dp += 76) {
18 | encodeSixBytes(src, dst, BASE64_URL, sp, dp);
19 | encodeSixBytes(src, dst, BASE64_URL, sp + 6, dp + 8);
20 | encodeSixBytes(src, dst, BASE64_URL, sp + 12, dp + 16);
21 | encodeSixBytes(src, dst, BASE64_URL, sp + 18, dp + 24);
22 | encodeSixBytes(src, dst, BASE64_URL, sp + 24, dp + 32);
23 | encodeSixBytes(src, dst, BASE64_URL, sp + 30, dp + 40);
24 | encodeSixBytes(src, dst, BASE64_URL, sp + 36, dp + 48);
25 | encodeSixBytes(src, dst, BASE64_URL, sp + 42, dp + 56);
26 | encodeSixBytes(src, dst, BASE64_URL, sp + 48, dp + 64);
27 | encodeThreeBytes(src, dst, BASE64_URL, sp + 54, dp + 72);
28 | }
29 |
30 | for (; sp < src.length - 3; sp += 3, dp += 4) {
31 | encodeThreeBytes(src, dst, BASE64_URL, sp, dp);
32 | }
33 |
34 | int remaining = sl - sp;
35 |
36 | return switch (remaining) {
37 | case 3 -> encodeLastThreeBytes(src, dst, BASE64_URL, sp, dp);
38 | case 2 -> encodeLastTwoBytes(src, dst, BASE64_URL, sp, dp);
39 | case 1 -> encodeLastByte(src, dst, BASE64_URL, sp, dp);
40 | default -> dp;
41 | };
42 | }
43 |
44 | @Override
45 | public int getEncodedLength(final byte[] src) {
46 | return Math.multiplyExact(4, (Math.addExact(src.length, 2) / 3));
47 | }
48 | }
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/scalar/ScalarDecoderVars.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static com.joad.jdz.base64.Base64Tables.*;
4 |
5 | import java.lang.invoke.MethodHandles;
6 | import java.lang.invoke.VarHandle;
7 | import java.nio.ByteOrder;
8 | import java.util.Arrays;
9 |
10 | class ScalarDecoderVars {
11 | static final int[][] LOOKUP = new int[4][256];
12 |
13 | static final int[][] LOOKUP_URL = new int[4][256];
14 |
15 | final static VarHandle INT_LE =
16 | MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
17 |
18 | static {
19 | for (int i = 0; i < 4; i++) {
20 | Arrays.fill(LOOKUP[i], 1 << (24 + 3 - i));
21 | Arrays.fill(LOOKUP_URL[i], 1 << (24 + 3 - i));
22 | }
23 |
24 | for (int i = 0; i < 64; i++) {
25 | LOOKUP[0][BASE64[i]] = i << 2;
26 | LOOKUP[1][BASE64[i]] = (i >> 4) | ((i & 0x0f) << 12);
27 | LOOKUP[2][BASE64[i]] = ((i & 0x3) << 22) | ((i & 0x3c) << 6);
28 | LOOKUP[3][BASE64[i]] = i << 16;
29 |
30 | LOOKUP_URL[0][BASE64_URL[i]] = i << 2;
31 | LOOKUP_URL[1][BASE64_URL[i]] = (i >> 4) | ((i & 0x0f) << 12);
32 | LOOKUP_URL[2][BASE64_URL[i]] = ((i & 0x3) << 22) | ((i & 0x3c) << 6);
33 | LOOKUP_URL[3][BASE64_URL[i]] = i << 16;
34 | }
35 | }
36 |
37 | static final int VALID_MAX = (1 << 24) - 1;
38 |
39 | static final int MOD4 = 3;
40 | }
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/scalar/ScalarUtils.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static com.joad.jdz.base64.scalar.ScalarDecoderVars.*;
4 |
5 | import java.lang.invoke.MethodHandles;
6 | import java.lang.invoke.VarHandle;
7 | import java.nio.ByteOrder;
8 |
9 | class ScalarUtils {
10 | private final static VarHandle LONG_BE =
11 | MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN);
12 |
13 | private final static VarHandle LONG_LE =
14 | MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN);
15 |
16 | private final static VarHandle INT_BE =
17 | MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
18 |
19 | private final static VarHandle INT_LE =
20 | MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
21 |
22 | static void encodeSixBytes(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
23 | long bits = (long) LONG_BE.get(src, sp);
24 |
25 | dst[dp++] = (byte) lookup[(int) (bits >>> 58) & 0x3f];
26 | dst[dp++] = (byte) lookup[(int) (bits >>> 52) & 0x3f];
27 | dst[dp++] = (byte) lookup[(int) (bits >>> 46) & 0x3f];
28 | dst[dp++] = (byte) lookup[(int) (bits >>> 40) & 0x3f];
29 | dst[dp++] = (byte) lookup[(int) (bits >>> 34) & 0x3f];
30 | dst[dp++] = (byte) lookup[(int) (bits >>> 28) & 0x3f];
31 | dst[dp++] = (byte) lookup[(int) (bits >>> 22) & 0x3f];
32 | dst[dp] = (byte) lookup[(int) (bits >>> 16) & 0x3f];
33 | }
34 |
35 | static void encodeThreeBytes(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
36 | int bits = (int) INT_BE.get(src, sp);
37 |
38 | dst[dp++] = (byte) lookup[(bits >>> 26) & 0x3f];
39 | dst[dp++] = (byte) lookup[(bits >>> 20) & 0x3f];
40 | dst[dp++] = (byte) lookup[(bits >>> 14) & 0x3f];
41 | dst[dp] = (byte) lookup[(bits >>> 8) & 0x3f];
42 | }
43 |
44 | static void decodeFourBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
45 | int bits = lookup[0][src[sp++]]
46 | | lookup[1][src[sp++]]
47 | | lookup[2][src[sp++]]
48 | | lookup[3][src[sp]];
49 |
50 | INT_LE.set(dst, dp, bits);
51 | }
52 |
53 | static void decodeFourBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
54 | int osp = sp;
55 |
56 | int bits = lookup[0][src[sp++]]
57 | | lookup[1][src[sp++]]
58 | | lookup[2][src[sp++]]
59 | | lookup[3][src[sp]];
60 |
61 | assertValidBase64(src, bits, osp);
62 |
63 | INT_LE.set(dst, dp, bits);
64 | }
65 |
66 | static void decodeEightBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
67 | long bits1 = lookup[0][src[sp++]]
68 | | lookup[1][src[sp++]]
69 | | lookup[2][src[sp++]]
70 | | lookup[3][src[sp++]];
71 |
72 | long bits2 = lookup[0][src[sp++]]
73 | | lookup[1][src[sp++]]
74 | | lookup[2][src[sp++]]
75 | | lookup[3][src[sp]];
76 |
77 | long bits = bits1 | (bits2 << 24);
78 |
79 | LONG_LE.set(dst, dp, bits);
80 | }
81 |
82 | static void decodeEightBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
83 | int osp = sp;
84 |
85 | long bits1 = lookup[0][src[sp++]]
86 | | lookup[1][src[sp++]]
87 | | lookup[2][src[sp++]]
88 | | lookup[3][src[sp++]];
89 |
90 | long bits2 = lookup[0][src[sp++]]
91 | | lookup[1][src[sp++]]
92 | | lookup[2][src[sp++]]
93 | | lookup[3][src[sp]];
94 |
95 | assertValidBase64(src, (int) bits1, osp);
96 | assertValidBase64(src, (int) bits2, osp);
97 |
98 | long bits = bits1 | (bits2 << 24);
99 |
100 | LONG_LE.set(dst, dp, bits);
101 | }
102 |
103 | static int encodeLastByte(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
104 | int b0 = src[sp] & 0xff;
105 |
106 | dst[dp++] = (byte) lookup[b0 >> 2];
107 | dst[dp++] = (byte) lookup[(b0 << 4) & 0x3f];
108 | dst[dp++] = '=';
109 | dst[dp++] = '=';
110 |
111 | return dp;
112 | }
113 |
114 | static int encodeLastTwoBytes(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
115 | int b0 = src[sp++] & 0xff;
116 | int b1 = src[sp] & 0xff;
117 |
118 | dst[dp++] = (byte) lookup[b0 >> 2];
119 | dst[dp++] = (byte) lookup[(b0 << 4) & 0x3f | (b1 >> 4)];
120 | dst[dp++] = (byte) lookup[(b1 << 2) & 0x3f];
121 | dst[dp++] = '=';
122 |
123 | return dp;
124 | }
125 |
126 | static int encodeLastThreeBytes(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
127 | int b0 = src[sp++] & 0xff;
128 | int b1 = src[sp++] & 0xff;
129 | int b2 = src[sp] & 0xff;
130 |
131 | dst[dp++] = (byte) lookup[b0 >> 2];
132 | dst[dp++] = (byte) lookup[(b0 << 4) & 0x3f | (b1 >> 4)];
133 | dst[dp++] = (byte) lookup[(b1 << 2) & 0x3f | (b2 >> 6)];
134 | dst[dp++] = (byte) lookup[b2 & 0x3f];
135 |
136 | return dp;
137 | }
138 |
139 | static int decodeLastFourBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
140 | int bits = lookup[0][src[sp++]]
141 | | lookup[1][src[sp++]]
142 | | lookup[2][src[sp++]]
143 | | lookup[3][src[sp]];
144 |
145 | dst[dp++] = (byte) bits;
146 | dst[dp++] = (byte) (bits >> 8);
147 | dst[dp++] = (byte) (bits >> 16);
148 |
149 | return dp;
150 | }
151 |
152 | static int decodeLastThreeBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
153 | int bits = lookup[0][src[sp++]]
154 | | lookup[1][src[sp++]]
155 | | lookup[2][src[sp++]];
156 |
157 | dst[dp++] = (byte) bits;
158 | dst[dp++] = (byte) (bits >> 8);
159 |
160 | return dp;
161 | }
162 |
163 | static int decodeLastTwoBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
164 | int bits = lookup[0][src[sp++]]
165 | | lookup[1][src[sp++]];
166 |
167 | dst[dp++] = (byte) bits;
168 |
169 | return dp;
170 | }
171 |
172 | static int decodeLastFourBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
173 | int osp = sp;
174 |
175 | int bits = lookup[0][src[sp++]]
176 | | lookup[1][src[sp++]]
177 | | lookup[2][src[sp++]]
178 | | lookup[3][src[sp]];
179 |
180 | assertValidBase64(src, bits, osp);
181 |
182 | dst[dp++] = (byte) bits;
183 | dst[dp++] = (byte) (bits >> 8);
184 | dst[dp++] = (byte) (bits >> 16);
185 |
186 | return dp;
187 | }
188 |
189 | static int decodeLastThreeBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
190 | int osp = sp;
191 |
192 | int bits = lookup[0][src[sp++]]
193 | | lookup[1][src[sp++]]
194 | | lookup[2][src[sp]];
195 |
196 | assertValidBase64(src, bits, osp);
197 |
198 | dst[dp++] = (byte) bits;
199 | dst[dp++] = (byte) (bits >> 8);
200 |
201 | return dp;
202 | }
203 |
204 | static int decodeLastTwoBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
205 | int osp = sp;
206 |
207 | int bits = lookup[0][src[sp++]]
208 | | lookup[1][src[sp]];
209 |
210 | assertValidBase64(src, bits, osp);
211 |
212 | dst[dp++] = (byte) bits;
213 |
214 | return dp;
215 | }
216 |
217 | static int decodeLastThreeDestBytesMime(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
218 | int bits = 0;
219 | for (int i = 0; i < 4;) {
220 | int b = lookup[i][src[sp++]];
221 |
222 | if (b <= VALID_MAX) {
223 | bits |= b;
224 | i++;
225 | }
226 | }
227 |
228 | dst[dp++] = (byte) bits;
229 | dst[dp++] = (byte) (bits >> 8);
230 | dst[dp++] = (byte) (bits >> 16);
231 |
232 | return dp;
233 | }
234 |
235 | static int decodeLastTwoDestBytesMime(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
236 | int bits = 0;
237 | for (int i = 0; i < 3;) {
238 | int b = lookup[i][src[sp++]];
239 |
240 | if (b <= VALID_MAX) {
241 | bits |= b;
242 | i++;
243 | }
244 | }
245 |
246 | dst[dp++] = (byte) bits;
247 | dst[dp++] = (byte) (bits >> 8);
248 |
249 | return dp;
250 | }
251 |
252 | static int decodeLastDestByteMime(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
253 | int bits = 0;
254 | for (int i = 0; i < 2;) {
255 | int b = lookup[i][src[sp++]];
256 |
257 | if (b <= VALID_MAX) {
258 | bits |= b;
259 | i++;
260 | }
261 | }
262 |
263 | dst[dp++] = (byte) bits;
264 |
265 | return dp;
266 | }
267 |
268 | private static void assertValidBase64(byte[] src, int bits, int sp) {
269 | if (bits > VALID_MAX) {
270 | int ip = sp + Integer.numberOfLeadingZeros(bits) - 4;
271 |
272 | throw new IllegalArgumentException("Illegal base64 character " + Integer.toString(src[ip], 16) + " at position " + ip);
273 | }
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/Base64Vector.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import com.joad.jdz.base64.Base64Decoder;
4 | import com.joad.jdz.base64.Base64Encoder;
5 |
6 | public class Base64Vector {
7 | private static final Base64Encoder RFC4648_ENCODER = new RFC4648VectorEncoder();
8 |
9 | private static final Base64Encoder RFC4648URL_ENCODER = new RFC4648URLVectorEncoder();
10 |
11 | private static final Base64Encoder RFC2045_ENCODER = new RFC2045VectorEncoder();
12 |
13 | private static final Base64Decoder RFC4648_DECODER = new RFC4648VectorDecoder();
14 |
15 | private static final Base64Decoder RFC4648URL_DECODER = new RFC4648URLVectorDecoder();
16 |
17 | private static final Base64Decoder RFC2045_DECODER = new RFC2045VectorDecoder();
18 |
19 | /**
20 | * Encoder for the RFC4648 Base64 spec
21 | *
22 | * @return An RFC4648 Base64 Encoder
23 | */
24 | public static Base64Encoder getEncoder() {
25 | return RFC4648_ENCODER;
26 | }
27 |
28 | /**
29 | * Encoder for the RFC4648URL Base64 spec
30 | *
31 | * @return An RFC4648 Base64 Encoder
32 | */
33 | public static Base64Encoder getUrlEncoder() {
34 | return RFC4648URL_ENCODER;
35 | }
36 |
37 | /**
38 | * Encoder for the RFC2045 Base64 spec
39 | *
40 | * @return An RFC42045 Base64 encoder
41 | */
42 | public static Base64Encoder getMimeEncoder() {
43 | return RFC2045_ENCODER;
44 | }
45 |
46 | /**
47 | * Decoder for the RFC4648 Base64 spec
48 | *
49 | * @return An RFC4648 Base64 decoder
50 | */
51 | public static Base64Decoder getDecoder() {
52 | return RFC4648_DECODER;
53 | }
54 |
55 | /**
56 | * Decoder for the RFC4648 URL Base64 spec
57 | *
58 | * @return An RFC4648 URL Base64 decoder
59 | */
60 | public static Base64Decoder getUrlDecoder() {
61 | return RFC4648URL_DECODER;
62 | }
63 |
64 | /**
65 | * Decoder for the RFC2045 Base64 spec
66 | *
67 | * @return An RFC2045 Base64 fast encoder
68 | */
69 | public static Base64Decoder getMimeDecoder() {
70 | return RFC2045_DECODER;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/RFC2045VectorDecoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.Base64Tables.*;
4 | import static com.joad.jdz.base64.vector.ScalarUtils.*;
5 | import static com.joad.jdz.base64.vector.VectorUtils.*;
6 | import static com.joad.jdz.base64.vector.VectorDecoderVars.*;
7 |
8 | import java.util.Arrays;
9 | import com.joad.jdz.base64.Base64Decoder;
10 |
11 | public class RFC2045VectorDecoder extends Base64Decoder {
12 | private static final int[] SIMPLE_LOOKUP = new int[256];
13 |
14 | static {
15 | Arrays.fill(SIMPLE_LOOKUP, -1);
16 | for (int i = 0; i < 64; i++)
17 | SIMPLE_LOOKUP[BASE64[i]] = i;
18 | }
19 |
20 | private static final int NUM_ITERS = 64 / SPECIES_LENGTH + 1;
21 |
22 | @Override
23 | protected int decode(byte[] src, byte[] dst, int sl, int dl) {
24 | int sp = 0;
25 | int dp = 0;
26 |
27 | while (dp < dl - SPECIES_LENGTH) {
28 | int invalid = decodeBytesVectorizedMime(src, dst, SHIFT, SLASH_BYTE, SLASH_SWAP, sp, dp);
29 |
30 | if (invalid != SPECIES_LENGTH) {
31 | int spInc = invalid - (invalid & MOD4);
32 |
33 | sp += spInc;
34 | dp += spInc / 4 * 3;
35 |
36 | int bits = 0;
37 |
38 | for (int i = 0; i < 4;) {
39 | int b = LOOKUP[i][src[sp++]];
40 |
41 | if (b <= VALID_MAX) {
42 | bits |= b;
43 | i++;
44 | }
45 | }
46 |
47 | INT_LE.set(dst, dp, bits);
48 |
49 | dp += 3;
50 | }
51 | else {
52 | dp += DP_INC;
53 | sp += SP_INC;
54 | }
55 | }
56 |
57 | while (dp < dl - 3) {
58 | int bits = 0;
59 | for (int i = 0; i < 4;) {
60 | int b = LOOKUP[i][src[sp++]];
61 |
62 | if (b <= VALID_MAX) {
63 | bits |= b;
64 | i++;
65 | }
66 | }
67 |
68 | INT_LE.set(dst, dp, bits);
69 |
70 | dp += 3;
71 | }
72 |
73 | int remaining = dl - dp;
74 |
75 | return switch (remaining) {
76 | case 3 -> decodeLastThreeDestBytesMime(src, dst, LOOKUP, sp, dp);
77 | case 2 -> decodeLastTwoDestBytesMime(src, dst, LOOKUP, sp, dp);
78 | case 1 -> decodeLastDestByteMime(src, dst, LOOKUP, sp, dp);
79 | default -> dp;
80 | };
81 | }
82 |
83 | @Override
84 | protected int decodeFast(byte[] src, byte[] dst, int sl, int dl) {
85 | int sp = 0;
86 | int dp = 0;
87 |
88 | int end = dl - (NUM_ITERS - 1) * DP_INC - SPECIES_LENGTH;
89 |
90 | for (; dp < end; sp += 78, dp += 57) {
91 | for (int i = 0; i < NUM_ITERS; i++)
92 | decodeBytesVectorized(src, dst, SHIFT, SLASH_BYTE, SLASH_SWAP, sp + SP_INC * i, dp + DP_INC * i);
93 | }
94 |
95 | for (; dp < dl - 57; sp += 78, dp += 57) {
96 | decodeEightBytes(src, dst, LOOKUP, sp, dp);
97 | decodeEightBytes(src, dst, LOOKUP, sp + 8, dp + 6);
98 | decodeEightBytes(src, dst, LOOKUP, sp + 16, dp + 12);
99 | decodeEightBytes(src, dst, LOOKUP, sp + 24, dp + 18);
100 | decodeEightBytes(src, dst, LOOKUP, sp + 32, dp + 24);
101 | decodeEightBytes(src, dst, LOOKUP, sp + 40, dp + 30);
102 | decodeEightBytes(src, dst, LOOKUP, sp + 48, dp + 36);
103 | decodeEightBytes(src, dst, LOOKUP, sp + 56, dp + 42);
104 | decodeEightBytes(src, dst, LOOKUP, sp + 64, dp + 48);
105 | decodeFourBytes(src, dst, LOOKUP, sp + 72, dp + 54);
106 | }
107 |
108 | for (; sp < sl - 4; sp += 4, dp += 3) {
109 | decodeFourBytes(src, dst, LOOKUP, sp, dp);
110 | }
111 |
112 | int remaining = sl - sp;
113 | return switch (remaining) {
114 | case 4 -> decodeLastFourBytes(src, dst, LOOKUP, sp, dp);
115 | case 3 -> decodeLastThreeBytes(src, dst, LOOKUP, sp, dp);
116 | case 2 -> decodeLastTwoBytes(src, dst, LOOKUP, sp, dp);
117 | default -> dp;
118 | };
119 | }
120 |
121 | @Override
122 | protected int getDecodedLength(byte[] src, int pad) {
123 | int sl = src.length;
124 |
125 | int invalid = 0;
126 |
127 | int sp = 0;
128 | for (; sp < sl - SPECIES_LENGTH; sp += SPECIES_LENGTH) {
129 | invalid += countInvalidBytesVectorized(src, sp);
130 | }
131 |
132 | while (sp < sl - pad) {
133 | if (SIMPLE_LOOKUP[src[sp++]] < 0)
134 | invalid++;
135 | }
136 |
137 | int vsl = sl - invalid;
138 |
139 | if ((vsl & MOD4) != 0)
140 | throw new IllegalArgumentException("Number of valid input bytes not divisible by 4");
141 |
142 | return vsl / 4 * 3 - pad;
143 | }
144 |
145 | @Override
146 | protected int getDecodedLengthFast(byte[] src, int pad) {
147 | int sl = src.length;
148 |
149 | int vsl = sl - (sl/78) * 2;
150 |
151 | if ((vsl & MOD4) != 0)
152 | throw new IllegalArgumentException("Number of valid input bytes not divisible by 4");
153 |
154 | return vsl / 4 * 3 - pad;
155 | }
156 | }
157 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/RFC2045VectorEncoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.Base64Tables.*;
4 | import static com.joad.jdz.base64.vector.ScalarUtils.*;
5 | import static com.joad.jdz.base64.vector.VectorUtils.*;
6 | import static com.joad.jdz.base64.vector.VectorEncoderVars.*;
7 |
8 | import com.joad.jdz.base64.Base64Encoder;
9 |
10 | public class RFC2045VectorEncoder extends Base64Encoder {
11 | private static final int NUM_ITERS_64 = 64 / SPECIES_LENGTH;
12 |
13 | private static final int NUM_ITERS_OVERFLOW = NUM_ITERS_64 + 1;
14 |
15 | @Override
16 | public int encode(byte[] src, byte[] dst) {
17 | int sl = src.length;
18 | int dl = dst.length;
19 | int dp = 0;
20 | int sp = 0;
21 |
22 | for (; sp < sl - SPECIES_LENGTH * NUM_ITERS_OVERFLOW; sp += 57, dp += 78) {
23 | for (int i = 0; i < NUM_ITERS_OVERFLOW; i++)
24 | encodeBytesVectorized(src, dst, SHIFT, sp + SP_INC * i, dp + DP_INC * i);
25 | }
26 |
27 | for (; sp < sl - 57; sp += 57, dp += 78) {
28 | encodeSixBytes(src, dst, BASE64, sp, dp);
29 | encodeSixBytes(src, dst, BASE64, sp + 6, dp + 8);
30 | encodeSixBytes(src, dst, BASE64, sp + 12, dp + 16);
31 | encodeSixBytes(src, dst, BASE64, sp + 18, dp + 24);
32 | encodeSixBytes(src, dst, BASE64, sp + 24, dp + 32);
33 | encodeSixBytes(src, dst, BASE64, sp + 30, dp + 40);
34 | encodeSixBytes(src, dst, BASE64, sp + 36, dp + 48);
35 | encodeSixBytes(src, dst, BASE64, sp + 42, dp + 56);
36 | encodeSixBytes(src, dst, BASE64, sp + 48, dp + 64);
37 | encodeThreeBytes(src, dst, BASE64, sp + 54, dp + 72);
38 | }
39 |
40 |
41 | for (; sp < sl - 3; sp += 3, dp += 4) {
42 | encodeThreeBytes(src, dst, BASE64, sp, dp);
43 | }
44 |
45 | for (int ldp = 76; ldp < dl; ldp += 78) {
46 | dst[ldp] = '\r';
47 | dst[ldp+1] = '\n';
48 | }
49 |
50 | int remaining = sl - sp;
51 |
52 | return switch (remaining) {
53 | case 3 -> encodeLastThreeBytes(src, dst, BASE64, sp, dp);
54 | case 2 -> encodeLastTwoBytes(src, dst, BASE64, sp, dp);
55 | case 1 -> encodeLastByte(src, dst, BASE64, sp, dp);
56 | default -> dp;
57 | };
58 | }
59 |
60 | @Override
61 | public int getEncodedLength(byte[] src) {
62 | int rawLen = Math.multiplyExact(4, (Math.addExact(src.length, 2) / 3));
63 |
64 | return rawLen + ((rawLen - 1)/76) * 2;
65 | }
66 | }
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/RFC4648URLVectorDecoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.vector.ScalarUtils.*;
4 | import static com.joad.jdz.base64.vector.VectorUtils.*;
5 | import static com.joad.jdz.base64.vector.VectorDecoderVars.*;
6 |
7 | import com.joad.jdz.base64.Base64Decoder;
8 |
9 | public class RFC4648URLVectorDecoder extends Base64Decoder {
10 |
11 | @Override
12 | protected int decode(byte[] src, byte[] dst, int sl, int dl) {
13 | int sp = 0;
14 | int dp = 0;
15 |
16 | for (; dp < dl - SPECIES_LENGTH; sp += SP_INC, dp += DP_INC) {
17 | decodeBytesVectorizedValidating(src, dst, SHIFT_URL, MASK_URL, UNDERSCORE_BYTE, UNDERSCORE_SWAP, sp, dp);
18 | }
19 |
20 | for (; sp < sl - 4; sp += 4, dp += 3) {
21 | decodeFourBytesValidating(src, dst, LOOKUP_URL, sp, dp);
22 | }
23 |
24 | int remaining = sl - sp;
25 |
26 | return switch (remaining) {
27 | case 4 -> decodeLastFourBytesValidating(src, dst, LOOKUP_URL, sp, dp);
28 | case 3 -> decodeLastThreeBytesValidating(src, dst, LOOKUP_URL, sp, dp);
29 | case 2 -> decodeLastTwoBytesValidating(src, dst, LOOKUP_URL, sp, dp);
30 | default -> dp;
31 | };
32 | }
33 |
34 | @Override
35 | protected int decodeFast(byte[] src, byte[] dst, int sl, int dl) {
36 | int sp = 0;
37 | int dp = 0;
38 |
39 | for (; dp < dl - SPECIES_LENGTH; sp += SP_INC, dp += DP_INC) {
40 | decodeBytesVectorized(src, dst, SHIFT_URL, UNDERSCORE_BYTE, UNDERSCORE_SWAP, sp, dp);
41 | }
42 |
43 | for (; sp < sl - 4; sp += 4, dp += 3) {
44 | decodeFourBytes(src, dst, LOOKUP_URL, sp, dp);
45 | }
46 |
47 | int remaining = sl - sp;
48 |
49 | return switch (remaining) {
50 | case 4 -> decodeLastFourBytes(src, dst, LOOKUP_URL, sp, dp);
51 | case 3 -> decodeLastThreeBytes(src, dst, LOOKUP_URL, sp, dp);
52 | case 2 -> decodeLastTwoBytes(src, dst, LOOKUP_URL, sp, dp);
53 | default -> dp;
54 | };
55 | }
56 |
57 | @Override
58 | protected int getDecodedLength(byte[] src, int pad) {
59 | int sl = src.length;
60 |
61 | if ((sl & MOD4) != 0)
62 | throw new IllegalArgumentException("Number of input bytes not divisible by 4");
63 |
64 | return sl / 4 * 3 - pad;
65 | }
66 |
67 | @Override
68 | protected int getDecodedLengthFast(byte[] src, int pad) {
69 | return getDecodedLength(src, pad);
70 | }
71 | }
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/RFC4648URLVectorEncoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.Base64Tables.*;
4 | import static com.joad.jdz.base64.vector.ScalarUtils.*;
5 | import static com.joad.jdz.base64.vector.VectorUtils.*;
6 | import static com.joad.jdz.base64.vector.VectorEncoderVars.*;
7 |
8 | import com.joad.jdz.base64.Base64Encoder;
9 |
10 | public class RFC4648URLVectorEncoder extends Base64Encoder {
11 |
12 | @Override
13 | public int encode(byte[] src, byte[] dst) {
14 | int sl = src.length;
15 | int dp = 0;
16 | int sp = 0;
17 |
18 | for (; sp < sl - SPECIES_LENGTH; sp += SP_INC, dp += DP_INC) {
19 | encodeBytesVectorized(src, dst, SHIFT_URL, sp, dp);
20 | }
21 |
22 | for (; sp < src.length - 3; sp += 3, dp += 4) {
23 | encodeThreeBytes(src, dst, BASE64_URL, sp, dp);
24 | }
25 |
26 | int remaining = sl - sp;
27 |
28 | return switch (remaining) {
29 | case 3 -> encodeLastThreeBytes(src, dst, BASE64_URL, sp, dp);
30 | case 2 -> encodeLastTwoBytes(src, dst, BASE64_URL, sp, dp);
31 | case 1 -> encodeLastByte(src, dst, BASE64_URL, sp, dp);
32 | default -> dp;
33 | };
34 | }
35 |
36 | @Override
37 | public int getEncodedLength(byte[] src) {
38 | return Math.multiplyExact(4, (Math.addExact(src.length, 2) / 3));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/RFC4648VectorDecoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.vector.ScalarUtils.*;
4 | import static com.joad.jdz.base64.vector.VectorUtils.*;
5 | import static com.joad.jdz.base64.vector.VectorDecoderVars.*;
6 |
7 | import com.joad.jdz.base64.Base64Decoder;
8 |
9 | public class RFC4648VectorDecoder extends Base64Decoder {
10 |
11 | @Override
12 | protected int decode(byte[] src, byte[] dst, int sl, int dl) {
13 | int sp = 0;
14 | int dp = 0;
15 |
16 | for (; dp < dl - SPECIES_LENGTH; sp += SP_INC, dp += DP_INC) {
17 | decodeBytesVectorizedValidating(src, dst, SHIFT, MASK, SLASH_BYTE, SLASH_SWAP, sp, dp);
18 | }
19 |
20 | for (; sp < sl - 4; sp += 4, dp += 3) {
21 | decodeFourBytesValidating(src, dst, LOOKUP, sp, dp);
22 | }
23 |
24 | int remaining = sl - sp;
25 |
26 | return switch (remaining) {
27 | case 4 -> decodeLastFourBytesValidating(src, dst, LOOKUP, sp, dp);
28 | case 3 -> decodeLastThreeBytesValidating(src, dst, LOOKUP, sp, dp);
29 | case 2 -> decodeLastTwoBytesValidating(src, dst, LOOKUP, sp, dp);
30 | default -> dp;
31 | };
32 | }
33 |
34 | @Override
35 | protected int decodeFast(byte[] src, byte[] dst, int sl, int dl) {
36 | int sp = 0;
37 | int dp = 0;
38 |
39 | for (; dp < dl - SPECIES_LENGTH; sp += SP_INC, dp += DP_INC) {
40 | decodeBytesVectorized(src, dst, SHIFT, SLASH_BYTE, SLASH_SWAP, sp, dp);
41 | }
42 |
43 | for (; sp < sl - 4; sp += 4, dp += 3) {
44 | decodeFourBytes(src, dst, LOOKUP, sp, dp);
45 | }
46 |
47 | int remaining = sl - sp;
48 |
49 | return switch (remaining) {
50 | case 4 -> decodeLastFourBytes(src, dst, LOOKUP, sp, dp);
51 | case 3 -> decodeLastThreeBytes(src, dst, LOOKUP, sp, dp);
52 | case 2 -> decodeLastTwoBytes(src, dst, LOOKUP, sp, dp);
53 | default -> dp;
54 | };
55 | }
56 |
57 | @Override
58 | protected int getDecodedLength(byte[] src, int pad) {
59 | int sl = src.length;
60 |
61 | if ((sl & MOD4) != 0)
62 | throw new IllegalArgumentException("Number of input bytes not divisible by 4");
63 |
64 | return sl / 4 * 3 - pad;
65 | }
66 |
67 | @Override
68 | protected int getDecodedLengthFast(byte[] src, int pad) {
69 | return getDecodedLength(src, pad);
70 | }
71 | }
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/RFC4648VectorEncoder.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.Base64Tables.*;
4 | import static com.joad.jdz.base64.vector.ScalarUtils.*;
5 | import static com.joad.jdz.base64.vector.VectorUtils.*;
6 | import static com.joad.jdz.base64.vector.VectorEncoderVars.*;
7 |
8 | import com.joad.jdz.base64.Base64Encoder;
9 |
10 | public class RFC4648VectorEncoder extends Base64Encoder {
11 |
12 | @Override
13 | public int encode(byte[] src, byte[] dst) {
14 | int sl = src.length;
15 | int dp = 0;
16 | int sp = 0;
17 |
18 | for (; sp < sl - SPECIES_LENGTH; sp += SP_INC, dp += DP_INC) {
19 | encodeBytesVectorized(src, dst, SHIFT, sp, dp);
20 | }
21 |
22 | for (; sp < src.length - 3; sp += 3, dp += 4) {
23 | encodeThreeBytes(src, dst, BASE64, sp, dp);
24 | }
25 |
26 | int remaining = sl - sp;
27 |
28 | return switch (remaining) {
29 | case 3 -> encodeLastThreeBytes(src, dst, BASE64, sp, dp);
30 | case 2 -> encodeLastTwoBytes(src, dst, BASE64, sp, dp);
31 | case 1 -> encodeLastByte(src, dst, BASE64, sp, dp);
32 | default -> dp;
33 | };
34 | }
35 |
36 | @Override
37 | public int getEncodedLength(byte[] src) {
38 | return Math.multiplyExact(4, (Math.addExact(src.length, 2) / 3));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/ScalarUtils.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.vector.VectorDecoderVars.*;
4 |
5 | import java.lang.invoke.MethodHandles;
6 | import java.lang.invoke.VarHandle;
7 | import java.nio.ByteOrder;
8 |
9 | class ScalarUtils {
10 | private final static VarHandle LONG_BE =
11 | MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN);
12 |
13 | private final static VarHandle LONG_LE =
14 | MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN);
15 |
16 | private final static VarHandle INT_BE =
17 | MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
18 |
19 | private final static VarHandle INT_LE =
20 | MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
21 |
22 | static void encodeSixBytes(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
23 | long bits = (long) LONG_BE.get(src, sp);
24 |
25 | dst[dp++] = (byte) lookup[(int) (bits >>> 58) & 0x3f];
26 | dst[dp++] = (byte) lookup[(int) (bits >>> 52) & 0x3f];
27 | dst[dp++] = (byte) lookup[(int) (bits >>> 46) & 0x3f];
28 | dst[dp++] = (byte) lookup[(int) (bits >>> 40) & 0x3f];
29 | dst[dp++] = (byte) lookup[(int) (bits >>> 34) & 0x3f];
30 | dst[dp++] = (byte) lookup[(int) (bits >>> 28) & 0x3f];
31 | dst[dp++] = (byte) lookup[(int) (bits >>> 22) & 0x3f];
32 | dst[dp] = (byte) lookup[(int) (bits >>> 16) & 0x3f];
33 | }
34 |
35 | static void encodeThreeBytes(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
36 | int bits = (int) INT_BE.get(src, sp);
37 |
38 | dst[dp++] = (byte) lookup[(bits >>> 26) & 0x3f];
39 | dst[dp++] = (byte) lookup[(bits >>> 20) & 0x3f];
40 | dst[dp++] = (byte) lookup[(bits >>> 14) & 0x3f];
41 | dst[dp] = (byte) lookup[(bits >>> 8) & 0x3f];
42 | }
43 |
44 | static void decodeFourBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
45 | int bits = lookup[0][src[sp++]]
46 | | lookup[1][src[sp++]]
47 | | lookup[2][src[sp++]]
48 | | lookup[3][src[sp]];
49 |
50 | INT_LE.set(dst, dp, bits);
51 | }
52 |
53 | static void decodeFourBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
54 | int osp = sp;
55 |
56 | int bits = lookup[0][src[sp++]]
57 | | lookup[1][src[sp++]]
58 | | lookup[2][src[sp++]]
59 | | lookup[3][src[sp]];
60 |
61 | assertValidBase64(src, bits, osp);
62 |
63 | INT_LE.set(dst, dp, bits);
64 | }
65 |
66 | static void decodeEightBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
67 | long bits1 = lookup[0][src[sp++]]
68 | | lookup[1][src[sp++]]
69 | | lookup[2][src[sp++]]
70 | | lookup[3][src[sp++]];
71 |
72 | long bits2 = lookup[0][src[sp++]]
73 | | lookup[1][src[sp++]]
74 | | lookup[2][src[sp++]]
75 | | lookup[3][src[sp]];
76 |
77 | long bits = bits1 | (bits2 << 24);
78 |
79 | LONG_LE.set(dst, dp, bits);
80 | }
81 |
82 | static void decodeEightBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
83 | int osp = sp;
84 |
85 | long bits1 = lookup[0][src[sp++]]
86 | | lookup[1][src[sp++]]
87 | | lookup[2][src[sp++]]
88 | | lookup[3][src[sp++]];
89 |
90 | long bits2 = lookup[0][src[sp++]]
91 | | lookup[1][src[sp++]]
92 | | lookup[2][src[sp++]]
93 | | lookup[3][src[sp]];
94 |
95 | assertValidBase64(src, (int) bits1, osp);
96 | assertValidBase64(src, (int) bits2, osp);
97 |
98 | long bits = bits1 | (bits2 << 24);
99 |
100 | LONG_LE.set(dst, dp, bits);
101 | }
102 |
103 | static int encodeLastByte(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
104 | int b0 = src[sp] & 0xff;
105 |
106 | dst[dp++] = (byte) lookup[b0 >> 2];
107 | dst[dp++] = (byte) lookup[(b0 << 4) & 0x3f];
108 | dst[dp++] = '=';
109 | dst[dp++] = '=';
110 |
111 | return dp;
112 | }
113 |
114 | static int encodeLastTwoBytes(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
115 | int b0 = src[sp++] & 0xff;
116 | int b1 = src[sp] & 0xff;
117 |
118 | dst[dp++] = (byte) lookup[b0 >> 2];
119 | dst[dp++] = (byte) lookup[(b0 << 4) & 0x3f | (b1 >> 4)];
120 | dst[dp++] = (byte) lookup[(b1 << 2) & 0x3f];
121 | dst[dp++] = '=';
122 |
123 | return dp;
124 | }
125 |
126 | static int encodeLastThreeBytes(byte[] src, byte[] dst, char[] lookup, int sp, int dp) {
127 | int b0 = src[sp++] & 0xff;
128 | int b1 = src[sp++] & 0xff;
129 | int b2 = src[sp] & 0xff;
130 |
131 | dst[dp++] = (byte) lookup[b0 >> 2];
132 | dst[dp++] = (byte) lookup[(b0 << 4) & 0x3f | (b1 >> 4)];
133 | dst[dp++] = (byte) lookup[(b1 << 2) & 0x3f | (b2 >> 6)];
134 | dst[dp++] = (byte) lookup[b2 & 0x3f];
135 |
136 | return dp;
137 | }
138 |
139 | static int decodeLastFourBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
140 | int bits = lookup[0][src[sp++]]
141 | | lookup[1][src[sp++]]
142 | | lookup[2][src[sp++]]
143 | | lookup[3][src[sp]];
144 |
145 | dst[dp++] = (byte) bits;
146 | dst[dp++] = (byte) (bits >> 8);
147 | dst[dp++] = (byte) (bits >> 16);
148 |
149 | return dp;
150 | }
151 |
152 | static int decodeLastThreeBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
153 | int bits = lookup[0][src[sp++]]
154 | | lookup[1][src[sp++]]
155 | | lookup[2][src[sp]];
156 |
157 | dst[dp++] = (byte) bits;
158 | dst[dp++] = (byte) (bits >> 8);
159 |
160 | return dp;
161 | }
162 |
163 | static int decodeLastTwoBytes(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
164 | int bits = lookup[0][src[sp++]]
165 | | lookup[1][src[sp]];
166 |
167 | dst[dp++] = (byte) bits;
168 |
169 | return dp;
170 | }
171 |
172 | static int decodeLastFourBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
173 | int osp = sp;
174 |
175 | int bits = lookup[0][src[sp++]]
176 | | lookup[1][src[sp++]]
177 | | lookup[2][src[sp++]]
178 | | lookup[3][src[sp]];
179 |
180 | assertValidBase64(src, bits, osp);
181 |
182 | dst[dp++] = (byte) bits;
183 | dst[dp++] = (byte) (bits >> 8);
184 | dst[dp++] = (byte) (bits >> 16);
185 |
186 | return dp;
187 | }
188 |
189 | static int decodeLastThreeBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
190 | int osp = sp;
191 |
192 | int bits = lookup[0][src[sp++]]
193 | | lookup[1][src[sp++]]
194 | | lookup[2][src[sp]];
195 |
196 | assertValidBase64(src, bits, osp);
197 |
198 | dst[dp++] = (byte) bits;
199 | dst[dp++] = (byte) (bits >> 8);
200 |
201 | return dp;
202 | }
203 |
204 | static int decodeLastTwoBytesValidating(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
205 | int osp = sp;
206 |
207 | int bits = lookup[0][src[sp++]]
208 | | lookup[1][src[sp]];
209 |
210 | assertValidBase64(src, bits, osp);
211 |
212 | dst[dp++] = (byte) bits;
213 |
214 | return dp;
215 | }
216 |
217 | static int decodeLastThreeDestBytesMime(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
218 | int bits = 0;
219 | for (int i = 0; i < 4;) {
220 | int b = lookup[i][src[sp++]];
221 |
222 | if (b <= VALID_MAX) {
223 | bits |= b;
224 | i++;
225 | }
226 | }
227 |
228 | dst[dp++] = (byte) bits;
229 | dst[dp++] = (byte) (bits >> 8);
230 | dst[dp++] = (byte) (bits >> 16);
231 |
232 | return dp;
233 | }
234 |
235 | static int decodeLastTwoDestBytesMime(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
236 | int bits = 0;
237 | for (int i = 0; i < 3;) {
238 | int b = lookup[i][src[sp++]];
239 |
240 | if (b <= VALID_MAX) {
241 | bits |= b;
242 | i++;
243 | }
244 | }
245 |
246 | dst[dp++] = (byte) bits;
247 | dst[dp++] = (byte) (bits >> 8);
248 |
249 | return dp;
250 | }
251 |
252 | static int decodeLastDestByteMime(byte[] src, byte[] dst, int[][] lookup, int sp, int dp) {
253 | int bits = 0;
254 | for (int i = 0; i < 2;) {
255 | int b = lookup[i][src[sp++]];
256 |
257 | if (b <= VALID_MAX) {
258 | bits |= b;
259 | i++;
260 | }
261 | }
262 |
263 | dst[dp++] = (byte) bits;
264 |
265 | return dp;
266 | }
267 |
268 | private static void assertValidBase64(byte[] src, int bits, int sp) {
269 | if (bits > VALID_MAX) {
270 | int ip = sp + Integer.numberOfLeadingZeros(bits) - 4;
271 |
272 | throw new IllegalArgumentException("Illegal base64 character " + Integer.toString(src[ip], 16) + " at position " + ip);
273 | }
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/VectorDecoderVars.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.Base64Tables.*;
4 | import static com.joad.jdz.base64.vector.VectorSpeciesSelection.*;
5 |
6 | import java.lang.invoke.MethodHandles;
7 | import java.lang.invoke.VarHandle;
8 | import java.nio.ByteOrder;
9 | import java.util.Arrays;
10 | import jdk.incubator.vector.ByteVector;
11 |
12 | class VectorDecoderVars {
13 | static final ByteVector SHIFT = ByteVector.fromArray(BYTE_SPECIES, new byte[] {
14 | 0, 0, 19, 4, -65, -65, -71, -71, 0, 0, 0, 0, 0, 0, 0, 0,
15 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
17 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
18 | 0);
19 |
20 | static final ByteVector SHIFT_URL = ByteVector.fromArray(BYTE_SPECIES, new byte[] {
21 | 0, 0, 17, 4, -65, -65, -71, -71, 0, 0, 0, 0, 0, 0, 0, 0,
22 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
24 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
25 | 0);
26 |
27 |
28 | static final ByteVector MASK = ByteVector.fromArray(BYTE_SPECIES, new byte[] {
29 | (byte) 0b10101000,
30 | (byte) 0b11111000, (byte) 0b11111000, (byte) 0b11111000, (byte) 0b11111000,
31 | (byte) 0b11111000, (byte) 0b11111000, (byte) 0b11111000, (byte) 0b11111000,
32 | (byte) 0b11111000,
33 | (byte) 0b11110000,
34 | (byte) 0b01010100,
35 | (byte) 0b01010000, (byte) 0b01010000, (byte) 0b01010000,
36 | (byte) 0b01010100,
37 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
38 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
40 | }, 0);
41 |
42 | static final ByteVector MASK_URL = ByteVector.fromArray(BYTE_SPECIES, new byte[] {
43 | (byte) 0b10101000,
44 | (byte) 0b11111000, (byte) 0b11111000, (byte) 0b11111000, (byte) 0b11111000,
45 | (byte) 0b11111000, (byte) 0b11111000, (byte) 0b11111000, (byte) 0b11111000,
46 | (byte) 0b11111000,
47 | (byte) 0b11110000,
48 | (byte) 0b01010000,
49 | (byte) 0b01010000, (byte) 0b01010100, (byte) 0b01010000,
50 | (byte) 0b01110000,
51 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
54 | }, 0);
55 |
56 | static final int[][] LOOKUP = new int[4][256];
57 |
58 | static final int[][] LOOKUP_URL = new int[4][256];
59 |
60 | final static VarHandle INT_LE =
61 | MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN);
62 |
63 | static {
64 | for (int i = 0; i < 4; i++) {
65 | Arrays.fill(LOOKUP[i], 1 << (24 + 3 - i));
66 | Arrays.fill(LOOKUP_URL[i], 1 << (24 + 3 - i));
67 | }
68 |
69 | for (int i = 0; i < 64; i++) {
70 | LOOKUP[0][BASE64[i]] = i << 2;
71 | LOOKUP[1][BASE64[i]] = (i >> 4) | ((i & 0x0f) << 12);
72 | LOOKUP[2][BASE64[i]] = ((i & 0x3) << 22) | ((i & 0x3c) << 6);
73 | LOOKUP[3][BASE64[i]] = i << 16;
74 |
75 | LOOKUP_URL[0][BASE64_URL[i]] = i << 2;
76 | LOOKUP_URL[1][BASE64_URL[i]] = (i >> 4) | ((i & 0x0f) << 12);
77 | LOOKUP_URL[2][BASE64_URL[i]] = ((i & 0x3) << 22) | ((i & 0x3c) << 6);
78 | LOOKUP_URL[3][BASE64_URL[i]] = i << 16;
79 | }
80 | }
81 |
82 | static final int SPECIES_LENGTH = BYTE_SPECIES.length();
83 |
84 | static final int SP_INC = SPECIES_LENGTH;
85 |
86 | static final int DP_INC = SP_INC / 4 * 3;
87 |
88 | static final byte SLASH_BYTE = (byte) '/';
89 |
90 | static final byte SLASH_SWAP = (byte) 16;
91 |
92 | static final byte UNDERSCORE_BYTE = (byte) '_';
93 |
94 | static final byte UNDERSCORE_SWAP = (byte) -32;
95 |
96 | static final int VALID_MAX = (1 << 24) - 1;
97 |
98 | static final int MOD4 = 3;
99 | }
100 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/VectorEncoderVars.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.vector.VectorSpeciesSelection.*;
4 |
5 | import jdk.incubator.vector.ByteVector;
6 |
7 | class VectorEncoderVars {
8 | static final ByteVector SHIFT = ByteVector.fromArray(BYTE_SPECIES,
9 | new byte[] {'A', '0' - 52, '0' - 52, '0' - 52, '0' - 52, '0' - 52,
10 | '0' - 52, '0' - 52, '0' - 52, '0' - 52, '0' - 52, '+' - 62,
11 | '/' - 63, 'a' - 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
12 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
13 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0);
14 |
15 | static final ByteVector SHIFT_URL = ByteVector.fromArray(BYTE_SPECIES,
16 | new byte[] {'A', '0' - 52, '0' - 52, '0' - 52, '0' - 52, '0' - 52,
17 | '0' - 52, '0' - 52, '0' - 52, '0' - 52, '0' - 52, '-' - 62,
18 | '_' - 63, 'a' - 26, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
19 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
20 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, 0);
21 |
22 | static final int SPECIES_LENGTH = BYTE_SPECIES.length();
23 |
24 | static final int DP_INC = SPECIES_LENGTH;
25 |
26 | static final int SP_INC = DP_INC / 4 * 3;
27 | }
28 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/VectorSpeciesSelection.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 | import jdk.incubator.vector.ByteVector;
6 | import jdk.incubator.vector.IntVector;
7 | import jdk.incubator.vector.VectorSpecies;
8 |
9 | class VectorSpeciesSelection {
10 | static final VectorSpecies BYTE_SPECIES;
11 |
12 | static final VectorSpecies INT_SPECIES;
13 |
14 | static {
15 | Map> BYTE_SPECIES_MAP = new HashMap<>();
16 |
17 | Map> INT_SPECIES_MAP = new HashMap<>();
18 |
19 | BYTE_SPECIES_MAP.put("128", ByteVector.SPECIES_128);
20 | BYTE_SPECIES_MAP.put("256", ByteVector.SPECIES_256);
21 | BYTE_SPECIES_MAP.put("512", ByteVector.SPECIES_512);
22 |
23 | INT_SPECIES_MAP.put("128", IntVector.SPECIES_128);
24 | INT_SPECIES_MAP.put("256", IntVector.SPECIES_256);
25 | INT_SPECIES_MAP.put("512", IntVector.SPECIES_512);
26 |
27 | String speciesLength = System.getProperty("jdz.vector.size");
28 |
29 | if (speciesLength != null) {
30 | if (!BYTE_SPECIES_MAP.containsKey(speciesLength))
31 | throw new ExceptionInInitializerError(speciesLength + " is not a valid vector size - please pick one of 128, 256 or 512");
32 |
33 | BYTE_SPECIES = BYTE_SPECIES_MAP.get(speciesLength);
34 |
35 | INT_SPECIES = INT_SPECIES_MAP.get(speciesLength);
36 | }
37 | else {
38 | if (ByteVector.SPECIES_PREFERRED.equals(ByteVector.SPECIES_64)) {
39 | throw new ExceptionInInitializerError("Vectorized base64 encoding/decoding requires 128 or greater bit vector support - system preferred is 64.");
40 | }
41 |
42 | BYTE_SPECIES = ByteVector.SPECIES_PREFERRED;
43 |
44 | INT_SPECIES = IntVector.SPECIES_PREFERRED;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/base64/src/main/java/com/joad/jdz/base64/vector/VectorUtils.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static com.joad.jdz.base64.vector.VectorSpeciesSelection.*;
4 | import static com.joad.jdz.base64.vector.VectorDecoderVars.*;
5 |
6 | import jdk.incubator.vector.ByteVector;
7 | import jdk.incubator.vector.IntVector;
8 | import jdk.incubator.vector.ShortVector;
9 | import jdk.incubator.vector.VectorMask;
10 | import jdk.incubator.vector.VectorOperators;
11 | import jdk.incubator.vector.VectorShuffle;
12 |
13 | /*
14 | * The methods in this class are heavily inspired by the following articles by Wojciech Mula:
15 | *
16 | * http://0x80.pl/notesen/2016-01-12-sse-base64-encoding.html
17 | * http://0x80.pl/notesen/2016-01-17-sse-base64-decoding.html
18 | */
19 | public class VectorUtils {
20 | private static final VectorShuffle ENC_SHUFFLE = VectorShuffle.fromArray(BYTE_SPECIES, new int[]
21 | {1, 0, 2, 1, 4, 3, 5, 4, 7, 6, 8, 7, 10, 9, 11, 10, 13, 12, 14, 13,
22 | 16, 15, 17, 16, 19, 18, 20, 19, 22, 21, 23, 22, 25, 24, 26, 25,
23 | 28, 27, 29, 28, 31, 30, 32, 31, 34, 33, 35, 34, 37, 36, 38, 37,
24 | 40, 39, 41, 40, 43, 42, 44, 43, 46, 45, 47, 46, 49, 48, 50, 49},
25 | 0);
26 |
27 | private static final ShortVector AC_MASK = IntVector.broadcast(INT_SPECIES, 0x0fc0fc00).reinterpretAsShorts();
28 |
29 | private static final ShortVector AC_SHIFT = IntVector.broadcast(INT_SPECIES, 0x0006000a).reinterpretAsShorts();
30 |
31 | private static final ShortVector BD_MASK = IntVector.broadcast(INT_SPECIES, 0x003f03f0).reinterpretAsShorts();
32 |
33 | private static final ShortVector BD_SHIFT = IntVector.broadcast(INT_SPECIES, 0x00080004).reinterpretAsShorts();
34 |
35 | private static final VectorShuffle DEC_PACK = switch (BYTE_SPECIES.length()) {
36 | case 16 -> VectorShuffle.fromArray(BYTE_SPECIES, new int[] {
37 | 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, 0, 0, 0, 0
38 | }, 0);
39 |
40 | case 32 -> VectorShuffle.fromArray(BYTE_SPECIES, new int[] {
41 | 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, 18, 17, 16,
42 | 22, 21, 20, 26, 25, 24, 30, 29, 28,
43 | 0, 0, 0, 0, 0, 0, 0, 0
44 | }, 0);
45 |
46 | case 64 -> VectorShuffle.fromArray(BYTE_SPECIES, new int[] {
47 | 2, 1, 0, 6, 5, 4, 10, 9, 8, 14, 13, 12, 18, 17, 16,
48 | 22, 21, 20, 26, 25, 24, 30, 29, 28, 34, 33, 32, 38, 37, 36,
49 | 42, 41, 40, 46, 45, 44, 50, 49, 48, 54, 53, 52, 58, 57, 56,
50 | 62, 61, 60, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
51 | }, 0);
52 |
53 | default -> throw new ExceptionInInitializerError("Byte species length unsupported");
54 | };
55 |
56 | private static final ByteVector BIT_POS_LUT = ByteVector.fromArray(BYTE_SPECIES, new byte[] {
57 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, (byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0,
58 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
60 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
61 | }, 0);
62 |
63 | static void encodeBytesVectorized(byte[] src, byte[] dst, ByteVector shiftLookup, int sp, int dp) {
64 | ByteVector input = ByteVector.fromArray(BYTE_SPECIES, src, sp);
65 | ByteVector shuffled = input.rearrange(ENC_SHUFFLE);
66 | ShortVector shortShuf = shuffled.reinterpretAsShorts();
67 |
68 | ShortVector ac = shortShuf.and(AC_MASK);
69 | ShortVector bd = shortShuf.and(BD_MASK);
70 |
71 | ShortVector acShifted = ac.lanewise(VectorOperators.LSHR, AC_SHIFT);
72 | ShortVector bdShifted = bd.lanewise(VectorOperators.LSHL, BD_SHIFT);
73 |
74 | ByteVector noLookupRes = bdShifted.or(acShifted).reinterpretAsBytes();
75 |
76 | VectorMask lt26 = noLookupRes.lt((byte) 26);
77 | VectorMask lt52 = noLookupRes.lt((byte) 52);
78 | VectorMask thirteens = lt52.andNot(lt26);
79 |
80 | ByteVector subbed = noLookupRes.sub((byte) 51)
81 | .lanewise(VectorOperators.AND, 0x00, lt52)
82 | .blend((byte) 13, thirteens);
83 |
84 | ByteVector shifts = subbed.selectFrom(shiftLookup);
85 |
86 | ByteVector res = noLookupRes.add(shifts);
87 |
88 | res.intoArray(dst, dp);
89 | }
90 |
91 | static void decodeBytesVectorized(byte[] src, byte[] dst, ByteVector shiftLookup, byte swapKey, byte swapVal, int sp, int dp) {
92 | ByteVector input = ByteVector.fromArray(BYTE_SPECIES, src, sp);
93 |
94 | ByteVector higherNibble = input.lanewise(VectorOperators.LSHR, 4);
95 |
96 | ByteVector sh = higherNibble.selectFrom(shiftLookup);
97 | VectorMask eqSwap = input.eq(swapKey);
98 | ByteVector shift = sh.blend(swapVal, eqSwap);
99 |
100 | IntVector shifted = input.add(shift).reinterpretAsInts();
101 |
102 | IntVector ca = shifted.and(0x003f003f);
103 | IntVector db = shifted.and(0x3f003f00);
104 |
105 | IntVector t0 = db.lanewise(VectorOperators.LSHR, 8).or(ca.lanewise(VectorOperators.LSHL, 6));
106 | IntVector t1 = t0.lanewise(VectorOperators.LSHR, 16).or(t0.lanewise(VectorOperators.LSHL, 12));
107 |
108 | ByteVector res = t1.reinterpretAsBytes().rearrange(DEC_PACK);
109 |
110 | res.intoArray(dst, dp);
111 | }
112 |
113 | static void decodeBytesVectorizedValidating(byte[] src, byte[] dst, ByteVector shiftLookup, ByteVector mask, byte swapKey, byte swapVal, int sp, int dp) {
114 | ByteVector input = ByteVector.fromArray(BYTE_SPECIES, src, sp);
115 |
116 | ByteVector higherNibble = input.lanewise(VectorOperators.LSHR, 4);
117 | ByteVector lowerNibble = input.and((byte) 0x0f);
118 |
119 | ByteVector sh = higherNibble.selectFrom(shiftLookup);
120 | VectorMask eqSwap = input.eq(swapKey);
121 | ByteVector shift = sh.blend(swapVal, eqSwap);
122 |
123 | ByteVector masked = lowerNibble.selectFrom(mask);
124 | ByteVector bit = higherNibble.selectFrom(BIT_POS_LUT);
125 | ByteVector maskedAndBit = masked.and(bit);
126 |
127 | boolean invalid = maskedAndBit.eq((byte) 0).anyTrue();
128 |
129 | if (invalid) {
130 | int ip = sp + maskedAndBit.eq((byte) 0).firstTrue();
131 |
132 | throw new IllegalArgumentException("Illegal base64 character " + Integer.toString(src[ip], 16) + " at position " + ip);
133 | }
134 |
135 | IntVector shifted = input.add(shift).reinterpretAsInts();
136 |
137 | IntVector ca = shifted.and(0x003f003f);
138 | IntVector db = shifted.and(0x3f003f00);
139 |
140 | IntVector t0 = db.lanewise(VectorOperators.LSHR, 8).or(ca.lanewise(VectorOperators.LSHL, 6));
141 | IntVector t1 = t0.lanewise(VectorOperators.LSHR, 16).or(t0.lanewise(VectorOperators.LSHL, 12));
142 |
143 | ByteVector res = t1.reinterpretAsBytes().rearrange(DEC_PACK);
144 |
145 | res.intoArray(dst, dp);
146 | }
147 |
148 | static int decodeBytesVectorizedMime(byte[] src, byte[] dst, ByteVector shiftLookup, byte swapKey, byte swapVal, int sp, int dp) {
149 | ByteVector input = ByteVector.fromArray(BYTE_SPECIES, src, sp);
150 |
151 | ByteVector higherNibble = input.lanewise(VectorOperators.LSHR, 4);
152 | ByteVector lowerNibble = input.and((byte) 0x0f);
153 |
154 | ByteVector sh = higherNibble.selectFrom(shiftLookup);
155 | VectorMask eqSwap = input.eq(swapKey);
156 | ByteVector shift = sh.blend(swapVal, eqSwap);
157 |
158 | ByteVector masked = lowerNibble.selectFrom(MASK);
159 | ByteVector bit = higherNibble.selectFrom(BIT_POS_LUT);
160 | ByteVector maskedAndBit = masked.and(bit);
161 |
162 | int firstInvalid = maskedAndBit.eq((byte) 0).firstTrue();
163 |
164 | IntVector shifted = input.add(shift).reinterpretAsInts();
165 |
166 | IntVector ca = shifted.and(0x003f003f);
167 | IntVector db = shifted.and(0x3f003f00);
168 |
169 | IntVector t0 = db.lanewise(VectorOperators.LSHR, 8).or(ca.lanewise(VectorOperators.LSHL, 6));
170 | IntVector t1 = t0.lanewise(VectorOperators.LSHR, 16).or(t0.lanewise(VectorOperators.LSHL, 12));
171 |
172 | ByteVector res = t1.reinterpretAsBytes().rearrange(DEC_PACK);
173 |
174 | res.intoArray(dst, dp);
175 |
176 | return firstInvalid;
177 | }
178 |
179 | static int countInvalidBytesVectorized(byte[] src, int sp) {
180 | ByteVector input = ByteVector.fromArray(BYTE_SPECIES, src, sp);
181 |
182 | ByteVector higherNibble = input.lanewise(VectorOperators.LSHR, 4);
183 | ByteVector lowerNibble = input.and((byte) 0x0f);
184 |
185 | ByteVector masked = lowerNibble.selectFrom(MASK);
186 | ByteVector bit = higherNibble.selectFrom(BIT_POS_LUT);
187 | ByteVector maskedAndBit = masked.and(bit);
188 |
189 | int invalid = maskedAndBit.eq((byte) 0).trueCount();
190 |
191 | return invalid;
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/base64/src/main/java/module-info.java:
--------------------------------------------------------------------------------
1 | module com.joad.jdz.base64 {
2 | requires jdk.incubator.vector;
3 | exports com.joad.jdz.base64;
4 | }
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/dev/LengthFuzzTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.dev;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class LengthFuzzTest {
9 | @Test
10 | public void lengthFuzz() {
11 | // for (int i = 0; i < 1000; i++) {
12 | for (int i = 0; i < 100; i++) {
13 | byte[] randomData = new byte[i];
14 |
15 | //System.out.println(i);
16 | new Random().nextBytes(randomData);
17 |
18 | // try{
19 | byte[] randomDataEnc = java.util.Base64.getEncoder().encode(randomData);
20 | byte[] randomDataEncUrl = java.util.Base64.getUrlEncoder().encode(randomData);
21 | byte[] randomDataEncMime = java.util.Base64.getMimeEncoder().encode(randomData);
22 |
23 | String javaResEnc = new String(randomDataEnc);
24 | String javaResUrlEnc = new String(randomDataEncUrl);
25 | String javaResMimeEnc = new String(randomDataEncMime);
26 |
27 | String javaResDec = new String(java.util.Base64.getDecoder().decode(randomDataEnc));
28 | String javaResUrlDec = new String(java.util.Base64.getUrlDecoder().decode(randomDataEncUrl));
29 | String javaResMimeDec = new String(java.util.Base64.getMimeDecoder().decode(randomDataEncMime));
30 |
31 | String jdzResScalarEnc = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(randomData));
32 | String jdzResScalarUrlEnc = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(randomData));
33 | String jdzResScalarMimeEnc = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(randomData));
34 |
35 | String jdzResVectorEnc = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(randomData));
36 | String jdzResVectorUrlEnc = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(randomData));
37 | String jdzResVectorMimeEnc = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(randomData));
38 |
39 | String jdzResScalarDec = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(randomDataEnc));
40 | String jdzResScalarUrlDec = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(randomDataEncUrl));
41 | String jdzResScalarMimeDec = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(randomDataEncMime));
42 | String jdzResScalarFastMimeDec = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(randomDataEncMime));
43 |
44 | String jdzResVectorDec = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(randomDataEnc));
45 | String jdzResVectorUrlDec = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(randomDataEncUrl));
46 | String jdzResVectorMimeDec = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(randomDataEncMime));
47 | String jdzResVectorFastMimeDec = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(randomDataEncMime));
48 |
49 | assertEquals("scalarEnc", javaResEnc, jdzResScalarEnc);
50 | assertEquals("scalarUrlEnc", javaResUrlEnc, jdzResScalarUrlEnc);
51 | assertEquals("scalarMimeEnc", javaResMimeEnc, jdzResScalarMimeEnc);
52 |
53 | assertEquals("vectorEnc", javaResEnc, jdzResVectorEnc);
54 | assertEquals("vectorUrlEnc", javaResUrlEnc, jdzResVectorUrlEnc);
55 | assertEquals("vectorMimeEnc", javaResMimeEnc, jdzResVectorMimeEnc);
56 |
57 | assertEquals("scalarDec", javaResDec, jdzResScalarDec);
58 | assertEquals("scalarUrlDec", javaResUrlDec, jdzResScalarUrlDec);
59 | assertEquals("scalarMimeDec", javaResMimeDec, jdzResScalarMimeDec);
60 | assertEquals("scalarFastMimeDec", javaResMimeDec, jdzResScalarFastMimeDec);
61 |
62 | assertEquals("vectorDec", javaResDec, jdzResVectorDec);
63 | assertEquals("vectorUrlDec", javaResUrlDec, jdzResVectorUrlDec);
64 | assertEquals("vectorMimeDec", javaResMimeDec, jdzResVectorMimeDec);
65 | assertEquals("vectorFastMimeDec", javaResMimeDec, jdzResVectorFastMimeDec);
66 | // } catch (Exception e) {e.printStackTrace(); System.exit(0);}
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/scalar/RFC2045FastScalarDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC2045FastScalarDecodeTest {
9 | /*
10 | * RFC2045 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 | private static final byte[] randomDataSixtyOne = new byte[61];
28 |
29 | static {
30 | new Random().nextBytes(randomDataZeroMod);
31 | new Random().nextBytes(randomDataOneMod);
32 | new Random().nextBytes(randomDataTwoMod);
33 | new Random().nextBytes(randomDataThreeMod);
34 | new Random().nextBytes(randomDataSixtyOne);
35 | }
36 |
37 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getMimeEncoder().encode(randomDataZeroMod);
38 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getMimeEncoder().encode(randomDataOneMod);
39 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getMimeEncoder().encode(randomDataTwoMod);
40 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getMimeEncoder().encode(randomDataThreeMod);
41 | private static final byte[] base64RandomDataSixtyOne = java.util.Base64.getMimeEncoder().encode(randomDataSixtyOne);
42 |
43 | @Test
44 | public void RFC2045DecodeEmptyVector() {
45 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(emptyVector));
46 |
47 | assertEquals("", jdzRes);
48 | }
49 |
50 | @Test
51 | public void RFC2045DecodefVector() {
52 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(fVector));
53 |
54 | assertEquals("f", jdzRes);
55 | }
56 |
57 | @Test
58 | public void RFC2045DecodefoVector() {
59 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(foVector));
60 |
61 | assertEquals("fo", jdzRes);
62 | }
63 |
64 | @Test
65 | public void RFC2045DecodefooVector() {
66 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(fooVector));
67 |
68 | assertEquals("foo", jdzRes);
69 | }
70 |
71 | @Test
72 | public void RFC2045DecodefoobVector() {
73 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(foobVector));
74 |
75 | assertEquals("foob", jdzRes);
76 | }
77 |
78 | @Test
79 | public void RFC2045DecodefoobaVector() {
80 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(foobaVector));
81 |
82 | assertEquals("fooba", jdzRes);
83 | }
84 |
85 | @Test
86 | public void RFC2045DecodefoobarVector() {
87 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(foobarVector));
88 |
89 | assertEquals("foobar", jdzRes);
90 | }
91 |
92 | @Test
93 | public void RFC2045DecodeZeroMod() {
94 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataZeroMod));
95 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(base64RandomDataZeroMod));
96 |
97 | assertEquals(javaRes, jdzRes);
98 | }
99 |
100 | @Test
101 | public void RFC2045DecodeOneMod() {
102 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataOneMod));
103 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(base64RandomDataOneMod));
104 |
105 | assertEquals(javaRes, jdzRes);
106 | }
107 |
108 | @Test
109 | public void RFC2045DecodeTwoMod() {
110 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataTwoMod));
111 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(base64RandomDataTwoMod));
112 |
113 | assertEquals(javaRes, jdzRes);
114 | }
115 |
116 | @Test
117 | public void RFC2045DecodeThreeMod() {
118 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataThreeMod));
119 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(base64RandomDataThreeMod));
120 |
121 | assertEquals(javaRes, jdzRes);
122 | }
123 |
124 | @Test
125 | public void RFC2045DecodeSixtyOne() {
126 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataSixtyOne));
127 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(base64RandomDataSixtyOne));
128 |
129 | assertEquals(javaRes, jdzRes);
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/scalar/RFC2045ScalarDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC2045ScalarDecodeTest {
9 | /*
10 | * RFC2045 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 | private static final byte[] randomDataSixtyOne = new byte[61];
28 |
29 | static {
30 | new Random().nextBytes(randomDataZeroMod);
31 | new Random().nextBytes(randomDataOneMod);
32 | new Random().nextBytes(randomDataTwoMod);
33 | new Random().nextBytes(randomDataThreeMod);
34 | new Random().nextBytes(randomDataSixtyOne);
35 | }
36 |
37 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getMimeEncoder().encode(randomDataZeroMod);
38 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getMimeEncoder().encode(randomDataOneMod);
39 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getMimeEncoder().encode(randomDataTwoMod);
40 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getMimeEncoder().encode(randomDataThreeMod);
41 | private static final byte[] base64RandomDataSixtyOne = java.util.Base64.getMimeEncoder().encode(randomDataSixtyOne);
42 |
43 | @Test
44 | public void RFC2045DecodeEmptyVector() {
45 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(emptyVector));
46 |
47 | assertEquals("", jdzRes);
48 | }
49 |
50 | @Test
51 | public void RFC2045DecodefVector() {
52 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(fVector));
53 |
54 | assertEquals("f", jdzRes);
55 | }
56 |
57 | @Test
58 | public void RFC2045DecodefoVector() {
59 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(foVector));
60 |
61 | assertEquals("fo", jdzRes);
62 | }
63 |
64 | @Test
65 | public void RFC2045DecodefooVector() {
66 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(fooVector));
67 |
68 | assertEquals("foo", jdzRes);
69 | }
70 |
71 | @Test
72 | public void RFC2045DecodefoobVector() {
73 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(foobVector));
74 |
75 | assertEquals("foob", jdzRes);
76 | }
77 |
78 | @Test
79 | public void RFC2045DecodefoobaVector() {
80 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(foobaVector));
81 |
82 | assertEquals("fooba", jdzRes);
83 | }
84 |
85 | @Test
86 | public void RFC2045DecodefoobarVector() {
87 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(foobarVector));
88 |
89 | assertEquals("foobar", jdzRes);
90 | }
91 |
92 | @Test
93 | public void RFC2045DecodeZeroMod() {
94 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataZeroMod));
95 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(base64RandomDataZeroMod));
96 |
97 | assertEquals(javaRes, jdzRes);
98 | }
99 |
100 | @Test
101 | public void RFC2045DecodeOneMod() {
102 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataOneMod));
103 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(base64RandomDataOneMod));
104 |
105 | assertEquals(javaRes, jdzRes);
106 | }
107 |
108 | @Test
109 | public void RFC2045DecodeTwoMod() {
110 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataTwoMod));
111 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(base64RandomDataTwoMod));
112 |
113 | assertEquals(javaRes, jdzRes);
114 | }
115 |
116 | @Test
117 | public void RFC2045DecodeThreeMod() {
118 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataThreeMod));
119 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(base64RandomDataThreeMod));
120 |
121 | assertEquals(javaRes, jdzRes);
122 | }
123 |
124 | @Test
125 | public void RFC2045DecodeSixtyOne() {
126 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataSixtyOne));
127 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(base64RandomDataSixtyOne));
128 |
129 | assertEquals(javaRes, jdzRes);
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/scalar/RFC2045ScalarEncodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC2045ScalarEncodeTest {
9 | /*
10 | * RFC2045 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "f".getBytes();
14 | private static final byte[] foVector = "fo".getBytes();
15 | private static final byte[] fooVector = "foo".getBytes();
16 | private static final byte[] foobVector = "foob".getBytes();
17 | private static final byte[] foobaVector = "fooba".getBytes();
18 | private static final byte[] foobarVector = "foobar".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 | private static final byte[] randomDataSeventySix = new byte[55];
28 |
29 | static {
30 | new Random().nextBytes(randomDataZeroMod);
31 | new Random().nextBytes(randomDataOneMod);
32 | new Random().nextBytes(randomDataTwoMod);
33 | new Random().nextBytes(randomDataThreeMod);
34 | new Random().nextBytes(randomDataSeventySix);
35 | }
36 |
37 | @Test
38 | public void RFC2045EncodeEmptyVector() {
39 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(emptyVector));
40 |
41 | assertEquals("", jdzRes);
42 | }
43 |
44 | @Test
45 | public void RFC2045EncodefVector() {
46 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(fVector));
47 |
48 | assertEquals("Zg==", jdzRes);
49 | }
50 |
51 | @Test
52 | public void RFC2045EncodefoVector() {
53 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(foVector));
54 |
55 | assertEquals("Zm8=", jdzRes);
56 | }
57 |
58 | @Test
59 | public void RFC2045EncodefooVector() {
60 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(fooVector));
61 |
62 | assertEquals("Zm9v", jdzRes);
63 | }
64 |
65 | @Test
66 | public void RFC2045EncodefoobVector() {
67 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(foobVector));
68 |
69 | assertEquals("Zm9vYg==", jdzRes);
70 | }
71 |
72 | @Test
73 | public void RFC2045EncodefoobaVector() {
74 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(foobaVector));
75 |
76 | assertEquals("Zm9vYmE=", jdzRes);
77 | }
78 |
79 | @Test
80 | public void RFC2045EncodefoobarVector() {
81 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(foobarVector));
82 |
83 | assertEquals("Zm9vYmFy", jdzRes);
84 | }
85 | @Test
86 | public void RFC2045EncodeZeroMod() {
87 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataZeroMod));
88 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(randomDataZeroMod));
89 |
90 | assertEquals(javaRes, joadRes);
91 | }
92 |
93 | @Test
94 | public void RFC2045EncodeOneMod() {
95 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataOneMod));
96 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(randomDataOneMod));
97 |
98 | assertEquals(javaRes, joadRes);
99 | }
100 |
101 | @Test
102 | public void RFC2045EncodeTwoMod() {
103 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataTwoMod));
104 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(randomDataTwoMod));
105 |
106 | assertEquals(javaRes, joadRes);
107 | }
108 |
109 | @Test
110 | public void RFC2045EncodeThreeMod() {
111 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataThreeMod));
112 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(randomDataThreeMod));
113 |
114 | assertEquals(javaRes, joadRes);
115 | }
116 |
117 | @Test
118 | public void RFC2045EncodeSeventySix() {
119 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataSeventySix));
120 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(randomDataSeventySix));
121 |
122 | assertEquals(javaRes, joadRes);
123 | }
124 | }
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/scalar/RFC4648FastScalarDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648FastScalarDecodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getEncoder().encode(randomDataZeroMod);
36 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getEncoder().encode(randomDataOneMod);
37 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getEncoder().encode(randomDataTwoMod);
38 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getEncoder().encode(randomDataThreeMod);
39 |
40 | @Test
41 | public void RFC4648DecodeEmptyVector() {
42 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(emptyVector));
43 |
44 | assertEquals("", jdzRes);
45 | }
46 |
47 | @Test
48 | public void RFC4648DecodefVector() {
49 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(fVector));
50 |
51 | assertEquals("f", jdzRes);
52 | }
53 |
54 | @Test
55 | public void RFC4648DecodefoVector() {
56 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(foVector));
57 |
58 | assertEquals("fo", jdzRes);
59 | }
60 |
61 | @Test
62 | public void RFC4648DecodefooVector() {
63 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(fooVector));
64 |
65 | assertEquals("foo", jdzRes);
66 | }
67 |
68 | @Test
69 | public void RFC4648DecodefoobVector() {
70 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(foobVector));
71 |
72 | assertEquals("foob", jdzRes);
73 | }
74 |
75 | @Test
76 | public void RFC4648DecodefoobaVector() {
77 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(foobaVector));
78 |
79 | assertEquals("fooba", jdzRes);
80 | }
81 |
82 | @Test
83 | public void RFC4648DecodefoobarVector() {
84 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(foobarVector));
85 |
86 | assertEquals("foobar", jdzRes);
87 | }
88 |
89 | @Test
90 | public void RFC4648DecodeZeroMod() {
91 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataZeroMod));
92 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(base64RandomDataZeroMod));
93 |
94 | assertEquals(javaRes, jdzRes);
95 | }
96 |
97 | @Test
98 | public void RFC4648DecodeOneMod() {
99 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataOneMod));
100 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(base64RandomDataOneMod));
101 |
102 | assertEquals(javaRes, jdzRes);
103 | }
104 |
105 | @Test
106 | public void RFC4648DecodeTwoMod() {
107 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataTwoMod));
108 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(base64RandomDataTwoMod));
109 |
110 | assertEquals(javaRes, jdzRes);
111 | }
112 |
113 | @Test
114 | public void RFC4648DecodeThreeMod() {
115 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataThreeMod));
116 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(base64RandomDataThreeMod));
117 |
118 | assertEquals(javaRes, jdzRes);
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/scalar/RFC4648ScalarDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648ScalarDecodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getEncoder().encode(randomDataZeroMod);
36 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getEncoder().encode(randomDataOneMod);
37 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getEncoder().encode(randomDataTwoMod);
38 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getEncoder().encode(randomDataThreeMod);
39 | private static final byte[] base64InvalidData = java.util.Base64.getEncoder().encode(randomDataZeroMod);
40 |
41 | @Test
42 | public void RFC4648DecodeEmptyVector() {
43 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(emptyVector));
44 |
45 | assertEquals("", jdzRes);
46 | }
47 |
48 | @Test
49 | public void RFC4648DecodefVector() {
50 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(fVector));
51 |
52 | assertEquals("f", jdzRes);
53 | }
54 |
55 | @Test
56 | public void RFC4648DecodefoVector() {
57 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(foVector));
58 |
59 | assertEquals("fo", jdzRes);
60 | }
61 |
62 | @Test
63 | public void RFC4648DecodefooVector() {
64 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(fooVector));
65 |
66 | assertEquals("foo", jdzRes);
67 | }
68 |
69 | @Test
70 | public void RFC4648DecodefoobVector() {
71 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(foobVector));
72 |
73 | assertEquals("foob", jdzRes);
74 | }
75 |
76 | @Test
77 | public void RFC4648DecodefoobaVector() {
78 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(foobaVector));
79 |
80 | assertEquals("fooba", jdzRes);
81 | }
82 |
83 | @Test
84 | public void RFC4648DecodefoobarVector() {
85 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(foobarVector));
86 |
87 | assertEquals("foobar", jdzRes);
88 | }
89 |
90 | @Test
91 | public void RFC4648DecodeZeroMod() {
92 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataZeroMod));
93 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(base64RandomDataZeroMod));
94 |
95 | assertEquals(javaRes, jdzRes);
96 | }
97 |
98 | @Test
99 | public void RFC4648DecodeOneMod() {
100 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataOneMod));
101 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(base64RandomDataOneMod));
102 |
103 | assertEquals(javaRes, jdzRes);
104 | }
105 |
106 | @Test
107 | public void RFC4648DecodeTwoMod() {
108 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataTwoMod));
109 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(base64RandomDataTwoMod));
110 |
111 | assertEquals(javaRes, jdzRes);
112 | }
113 |
114 | @Test
115 | public void RFC4648DecodeThreeMod() {
116 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataThreeMod));
117 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(base64RandomDataThreeMod));
118 |
119 | assertEquals(javaRes, jdzRes);
120 | }
121 |
122 | @Test
123 | public void RFC4648InvalidInputDecode() {
124 | base64InvalidData[100] = (byte) '$';
125 | base64InvalidData[101] = (byte) '$';
126 | base64InvalidData[102] = (byte) '$';
127 | base64InvalidData[103] = (byte) '$';
128 |
129 | String exception = "No exception";
130 |
131 | try {
132 | com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(base64InvalidData);
133 | }
134 | catch (Exception e) {
135 | exception = e.getMessage();
136 | }
137 |
138 | assertEquals("Illegal base64 character 24 at position 100", exception);
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/scalar/RFC4648ScalarEncodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648ScalarEncodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "f".getBytes();
14 | private static final byte[] foVector = "fo".getBytes();
15 | private static final byte[] fooVector = "foo".getBytes();
16 | private static final byte[] foobVector = "foob".getBytes();
17 | private static final byte[] foobaVector = "fooba".getBytes();
18 | private static final byte[] foobarVector = "foobar".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | @Test
36 | public void RFC4648EncodeEmptyVector() {
37 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(emptyVector));
38 |
39 | assertEquals("", jdzRes);
40 | }
41 |
42 | @Test
43 | public void RFC4648EncodefVector() {
44 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(fVector));
45 |
46 | assertEquals("Zg==", jdzRes);
47 | }
48 |
49 | @Test
50 | public void RFC4648EncodefoVector() {
51 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(foVector));
52 |
53 | assertEquals("Zm8=", jdzRes);
54 | }
55 |
56 | @Test
57 | public void RFC4648EncodefooVector() {
58 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(fooVector));
59 |
60 | assertEquals("Zm9v", jdzRes);
61 | }
62 |
63 | @Test
64 | public void RFC4648EncodefoobVector() {
65 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(foobVector));
66 |
67 | assertEquals("Zm9vYg==", jdzRes);
68 | }
69 |
70 | @Test
71 | public void RFC4648EncodefoobaVector() {
72 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(foobaVector));
73 |
74 | assertEquals("Zm9vYmE=", jdzRes);
75 | }
76 |
77 | @Test
78 | public void RFC4648EncodefoobarVector() {
79 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(foobarVector));
80 |
81 | assertEquals("Zm9vYmFy", jdzRes);
82 | }
83 | @Test
84 | public void RFC4648EncodeZeroMod() {
85 | String javaRes = new String(java.util.Base64.getEncoder().encode(randomDataZeroMod));
86 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(randomDataZeroMod));
87 |
88 | assertEquals(javaRes, joadRes);
89 | }
90 |
91 | @Test
92 | public void RFC4648EncodeOneMod() {
93 | String javaRes = new String(java.util.Base64.getEncoder().encode(randomDataOneMod));
94 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(randomDataOneMod));
95 |
96 | assertEquals(javaRes, joadRes);
97 | }
98 |
99 | @Test
100 | public void RFC4648EncodeTwoMod() {
101 | String javaRes = new String(java.util.Base64.getEncoder().encode(randomDataTwoMod));
102 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(randomDataTwoMod));
103 |
104 | assertEquals(javaRes, joadRes);
105 | }
106 |
107 | @Test
108 | public void RFC4648EncodeThreeMod() {
109 | String javaRes = new String(java.util.Base64.getEncoder().encode(randomDataThreeMod));
110 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(randomDataThreeMod));
111 |
112 | assertEquals(javaRes, joadRes);
113 | }
114 | }
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/scalar/RFC4648URLFastScalarDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648URLFastScalarDecodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 |
29 | static {
30 | new Random().nextBytes(randomDataZeroMod);
31 | new Random().nextBytes(randomDataOneMod);
32 | new Random().nextBytes(randomDataTwoMod);
33 | new Random().nextBytes(randomDataThreeMod);
34 | }
35 |
36 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getUrlEncoder().encode(randomDataZeroMod);
37 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getUrlEncoder().encode(randomDataOneMod);
38 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getUrlEncoder().encode(randomDataTwoMod);
39 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getUrlEncoder().encode(randomDataThreeMod);
40 |
41 | @Test
42 | public void RFC4648URLDecodeEmptyVector() {
43 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(emptyVector));
44 |
45 | assertEquals("", jdzRes);
46 | }
47 |
48 | @Test
49 | public void RFC4648URLDecodefVector() {
50 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(fVector));
51 |
52 | assertEquals("f", jdzRes);
53 | }
54 |
55 | @Test
56 | public void RFC4648URLDecodefoVector() {
57 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(foVector));
58 |
59 | assertEquals("fo", jdzRes);
60 | }
61 |
62 | @Test
63 | public void RFC4648URLDecodefooVector() {
64 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(fooVector));
65 |
66 | assertEquals("foo", jdzRes);
67 | }
68 |
69 | @Test
70 | public void RFC4648URLDecodefoobVector() {
71 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(foobVector));
72 |
73 | assertEquals("foob", jdzRes);
74 | }
75 |
76 | @Test
77 | public void RFC4648URLDecodefoobaVector() {
78 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(foobaVector));
79 |
80 | assertEquals("fooba", jdzRes);
81 | }
82 |
83 | @Test
84 | public void RFC4648URLDecodefoobarVector() {
85 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(foobarVector));
86 |
87 | assertEquals("foobar", jdzRes);
88 | }
89 |
90 | @Test
91 | public void RFC4648URLDecodeZeroMod() {
92 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataZeroMod));
93 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(base64RandomDataZeroMod));
94 |
95 | assertEquals(javaRes, jdzRes);
96 | }
97 |
98 | @Test
99 | public void RFC4648URLDecodeOneMod() {
100 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataOneMod));
101 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(base64RandomDataOneMod));
102 |
103 | assertEquals(javaRes, jdzRes);
104 | }
105 |
106 | @Test
107 | public void RFC4648URLDecodeTwoMod() {
108 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataTwoMod));
109 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(base64RandomDataTwoMod));
110 |
111 | assertEquals(javaRes, jdzRes);
112 | }
113 |
114 | @Test
115 | public void RFC4648URLDecodeThreeMod() {
116 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataThreeMod));
117 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decodeFast(base64RandomDataThreeMod));
118 |
119 | assertEquals(javaRes, jdzRes);
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/scalar/RFC4648URLScalarDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648URLScalarDecodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 |
29 | static {
30 | new Random().nextBytes(randomDataZeroMod);
31 | new Random().nextBytes(randomDataOneMod);
32 | new Random().nextBytes(randomDataTwoMod);
33 | new Random().nextBytes(randomDataThreeMod);
34 | }
35 |
36 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getUrlEncoder().encode(randomDataZeroMod);
37 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getUrlEncoder().encode(randomDataOneMod);
38 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getUrlEncoder().encode(randomDataTwoMod);
39 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getUrlEncoder().encode(randomDataThreeMod);
40 | private static final byte[] base64InvalidData = java.util.Base64.getUrlEncoder().encode(randomDataZeroMod);
41 |
42 | @Test
43 | public void RFC4648URLDecodeEmptyVector() {
44 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(emptyVector));
45 |
46 | assertEquals("", jdzRes);
47 | }
48 |
49 | @Test
50 | public void RFC4648URLDecodefVector() {
51 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(fVector));
52 |
53 | assertEquals("f", jdzRes);
54 | }
55 |
56 | @Test
57 | public void RFC4648URLDecodefoVector() {
58 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(foVector));
59 |
60 | assertEquals("fo", jdzRes);
61 | }
62 |
63 | @Test
64 | public void RFC4648URLDecodefooVector() {
65 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(fooVector));
66 |
67 | assertEquals("foo", jdzRes);
68 | }
69 |
70 | @Test
71 | public void RFC4648URLDecodefoobVector() {
72 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(foobVector));
73 |
74 | assertEquals("foob", jdzRes);
75 | }
76 |
77 | @Test
78 | public void RFC4648URLDecodefoobaVector() {
79 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(foobaVector));
80 |
81 | assertEquals("fooba", jdzRes);
82 | }
83 |
84 | @Test
85 | public void RFC4648URLDecodefoobarVector() {
86 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(foobarVector));
87 |
88 | assertEquals("foobar", jdzRes);
89 | }
90 |
91 | @Test
92 | public void RFC4648URLDecodeZeroMod() {
93 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataZeroMod));
94 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(base64RandomDataZeroMod));
95 |
96 | assertEquals(javaRes, jdzRes);
97 | }
98 |
99 | @Test
100 | public void RFC4648URLDecodeOneMod() {
101 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataOneMod));
102 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(base64RandomDataOneMod));
103 |
104 | assertEquals(javaRes, jdzRes);
105 | }
106 |
107 | @Test
108 | public void RFC4648URLDecodeTwoMod() {
109 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataTwoMod));
110 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(base64RandomDataTwoMod));
111 |
112 | assertEquals(javaRes, jdzRes);
113 | }
114 |
115 | @Test
116 | public void RFC4648URLDecodeThreeMod() {
117 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataThreeMod));
118 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(base64RandomDataThreeMod));
119 |
120 | assertEquals(javaRes, jdzRes);
121 | }
122 |
123 | @Test
124 | public void RFC4648URLInvalidInputDecode() {
125 | base64InvalidData[100] = (byte) '$';
126 | base64InvalidData[101] = (byte) '$';
127 | base64InvalidData[102] = (byte) '$';
128 | base64InvalidData[103] = (byte) '$';
129 |
130 | String exception = "No exception";
131 |
132 | try {
133 | com.joad.jdz.base64.scalar.Base64Scalar.getUrlDecoder().decode(base64InvalidData);
134 | }
135 | catch (Exception e) {
136 | exception = e.getMessage();
137 | }
138 |
139 | assertEquals("Illegal base64 character 24 at position 100", exception);
140 | }
141 | }
142 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/scalar/RFC4648URLScalarEncodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.scalar;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648URLScalarEncodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "f".getBytes();
14 | private static final byte[] foVector = "fo".getBytes();
15 | private static final byte[] fooVector = "foo".getBytes();
16 | private static final byte[] foobVector = "foob".getBytes();
17 | private static final byte[] foobaVector = "fooba".getBytes();
18 | private static final byte[] foobarVector = "foobar".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | @Test
36 | public void RFC4648URLEncodeEmptyVector() {
37 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(emptyVector));
38 |
39 | assertEquals("", jdzRes);
40 | }
41 |
42 | @Test
43 | public void RFC4648URLEncodefVector() {
44 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(fVector));
45 |
46 | assertEquals("Zg==", jdzRes);
47 | }
48 |
49 | @Test
50 | public void RFC4648URLEncodefoVector() {
51 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(foVector));
52 |
53 | assertEquals("Zm8=", jdzRes);
54 | }
55 |
56 | @Test
57 | public void RFC4648URLEncodefooVector() {
58 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(fooVector));
59 |
60 | assertEquals("Zm9v", jdzRes);
61 | }
62 |
63 | @Test
64 | public void RFC4648URLEncodefoobVector() {
65 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(foobVector));
66 |
67 | assertEquals("Zm9vYg==", jdzRes);
68 | }
69 |
70 | @Test
71 | public void RFC4648URLEncodefoobaVector() {
72 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(foobaVector));
73 |
74 | assertEquals("Zm9vYmE=", jdzRes);
75 | }
76 |
77 | @Test
78 | public void RFC4648URLEncodefoobarVector() {
79 | String jdzRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(foobarVector));
80 |
81 | assertEquals("Zm9vYmFy", jdzRes);
82 | }
83 | @Test
84 | public void RFC4648URLEncodeZeroMod() {
85 | String javaRes = new String(java.util.Base64.getUrlEncoder().encode(randomDataZeroMod));
86 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(randomDataZeroMod));
87 |
88 | assertEquals(javaRes, joadRes);
89 | }
90 |
91 | @Test
92 | public void RFC4648URLEncodeOneMod() {
93 | String javaRes = new String(java.util.Base64.getUrlEncoder().encode(randomDataOneMod));
94 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(randomDataOneMod));
95 |
96 | assertEquals(javaRes, joadRes);
97 | }
98 |
99 | @Test
100 | public void RFC4648URLEncodeTwoMod() {
101 | String javaRes = new String(java.util.Base64.getUrlEncoder().encode(randomDataTwoMod));
102 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(randomDataTwoMod));
103 |
104 | assertEquals(javaRes, joadRes);
105 | }
106 |
107 | @Test
108 | public void RFC4648URLEncodeThreeMod() {
109 | String javaRes = new String(java.util.Base64.getUrlEncoder().encode(randomDataThreeMod));
110 | String joadRes = new String(com.joad.jdz.base64.scalar.Base64Scalar.getUrlEncoder().encode(randomDataThreeMod));
111 |
112 | assertEquals(javaRes, joadRes);
113 | }
114 | }
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/vector/RFC2045FastVectorDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC2045FastVectorDecodeTest {
9 | /*
10 | * RFC2045Fast test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 | private static final byte[] randomDataSixtyOne = new byte[61];
28 |
29 | static {
30 | new Random().nextBytes(randomDataZeroMod);
31 | new Random().nextBytes(randomDataOneMod);
32 | new Random().nextBytes(randomDataTwoMod);
33 | new Random().nextBytes(randomDataThreeMod);
34 | new Random().nextBytes(randomDataSixtyOne);
35 | }
36 |
37 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getMimeEncoder().encode(randomDataZeroMod);
38 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getMimeEncoder().encode(randomDataOneMod);
39 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getMimeEncoder().encode(randomDataTwoMod);
40 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getMimeEncoder().encode(randomDataThreeMod);
41 | private static final byte[] base64RandomDataSixtyOne = java.util.Base64.getMimeEncoder().encode(randomDataSixtyOne);
42 |
43 | @Test
44 | public void RFC2045FastDecodeEmptyVector() {
45 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(emptyVector));
46 |
47 | assertEquals("", jdzRes);
48 | }
49 |
50 | @Test
51 | public void RFC2045FastDecodefVector() {
52 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(fVector));
53 |
54 | assertEquals("f", jdzRes);
55 | }
56 |
57 | @Test
58 | public void RFC2045FastDecodefoVector() {
59 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(foVector));
60 |
61 | assertEquals("fo", jdzRes);
62 | }
63 |
64 | @Test
65 | public void RFC2045FastDecodefooVector() {
66 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(fooVector));
67 |
68 | assertEquals("foo", jdzRes);
69 | }
70 |
71 | @Test
72 | public void RFC2045FastDecodefoobVector() {
73 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(foobVector));
74 |
75 | assertEquals("foob", jdzRes);
76 | }
77 |
78 | @Test
79 | public void RFC2045FastDecodefoobaVector() {
80 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(foobaVector));
81 |
82 | assertEquals("fooba", jdzRes);
83 | }
84 |
85 | @Test
86 | public void RFC2045FastDecodefoobarVector() {
87 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(foobarVector));
88 |
89 | assertEquals("foobar", jdzRes);
90 | }
91 |
92 | @Test
93 | public void RFC2045FastDecodeZeroMod() {
94 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataZeroMod));
95 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(base64RandomDataZeroMod));
96 |
97 | assertEquals(javaRes, jdzRes);
98 | }
99 |
100 | @Test
101 | public void RFC2045FastDecodeOneMod() {
102 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataOneMod));
103 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(base64RandomDataOneMod));
104 |
105 | assertEquals(javaRes, jdzRes);
106 | }
107 |
108 | @Test
109 | public void RFC2045FastDecodeTwoMod() {
110 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataTwoMod));
111 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(base64RandomDataTwoMod));
112 |
113 | assertEquals(javaRes, jdzRes);
114 | }
115 |
116 | @Test
117 | public void RFC2045FastDecodeThreeMod() {
118 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataThreeMod));
119 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(base64RandomDataThreeMod));
120 |
121 | assertEquals(javaRes, jdzRes);
122 | }
123 |
124 | @Test
125 | public void RFC2045DecodeSixtyOne() {
126 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataSixtyOne));
127 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(base64RandomDataSixtyOne));
128 |
129 | assertEquals(javaRes, jdzRes);
130 | }
131 | }
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/vector/RFC2045VectorDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC2045VectorDecodeTest {
9 | /*
10 | * RFC2045 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 | private static final byte[] randomDataSixtyOne = new byte[61];
28 |
29 | static {
30 | new Random().nextBytes(randomDataZeroMod);
31 | new Random().nextBytes(randomDataOneMod);
32 | new Random().nextBytes(randomDataTwoMod);
33 | new Random().nextBytes(randomDataThreeMod);
34 | new Random().nextBytes(randomDataSixtyOne);
35 | }
36 |
37 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getMimeEncoder().encode(randomDataZeroMod);
38 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getMimeEncoder().encode(randomDataOneMod);
39 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getMimeEncoder().encode(randomDataTwoMod);
40 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getMimeEncoder().encode(randomDataThreeMod);
41 | private static final byte[] base64RandomDataSixtyOne = java.util.Base64.getMimeEncoder().encode(randomDataSixtyOne);
42 | private static final byte[] base64InvalidData = java.util.Base64.getMimeEncoder().encode(randomDataZeroMod);
43 |
44 | @Test
45 | public void RFC2045DecodeEmptyVector() {
46 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(emptyVector));
47 |
48 | assertEquals("", jdzRes);
49 | }
50 |
51 | @Test
52 | public void RFC2045DecodefVector() {
53 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(fVector));
54 |
55 | assertEquals("f", jdzRes);
56 | }
57 |
58 | @Test
59 | public void RFC2045DecodefoVector() {
60 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(foVector));
61 |
62 | assertEquals("fo", jdzRes);
63 | }
64 |
65 | @Test
66 | public void RFC2045DecodefooVector() {
67 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(fooVector));
68 |
69 | assertEquals("foo", jdzRes);
70 | }
71 |
72 | @Test
73 | public void RFC2045DecodefoobVector() {
74 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(foobVector));
75 |
76 | assertEquals("foob", jdzRes);
77 | }
78 |
79 | @Test
80 | public void RFC2045DecodefoobaVector() {
81 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(foobaVector));
82 |
83 | assertEquals("fooba", jdzRes);
84 | }
85 |
86 | @Test
87 | public void RFC2045DecodefoobarVector() {
88 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(foobarVector));
89 |
90 | assertEquals("foobar", jdzRes);
91 | }
92 |
93 | @Test
94 | public void RFC2045DecodeZeroMod() {
95 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataZeroMod));
96 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(base64RandomDataZeroMod));
97 |
98 | assertEquals(javaRes, jdzRes);
99 | }
100 |
101 | @Test
102 | public void RFC2045DecodeOneMod() {
103 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataOneMod));
104 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(base64RandomDataOneMod));
105 |
106 | assertEquals(javaRes, jdzRes);
107 | }
108 |
109 | @Test
110 | public void RFC2045DecodeTwoMod() {
111 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataTwoMod));
112 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(base64RandomDataTwoMod));
113 |
114 | assertEquals(javaRes, jdzRes);
115 | }
116 |
117 | @Test
118 | public void RFC2045DecodeThreeMod() {
119 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataThreeMod));
120 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(base64RandomDataThreeMod));
121 |
122 | assertEquals(javaRes, jdzRes);
123 | }
124 |
125 | @Test
126 | public void RFC2045DecodeSixtyOne() {
127 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64RandomDataSixtyOne));
128 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(base64RandomDataSixtyOne));
129 |
130 | assertEquals(javaRes, jdzRes);
131 | }
132 |
133 | @Test
134 | public void RFC2045InvalidInputDecode() {
135 | base64InvalidData[100] = (byte) '$';
136 | base64InvalidData[101] = (byte) '$';
137 | base64InvalidData[102] = (byte) '$';
138 | base64InvalidData[103] = (byte) '$';
139 |
140 | String javaRes = new String(java.util.Base64.getMimeDecoder().decode(base64InvalidData));
141 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(base64InvalidData));
142 |
143 | assertEquals(javaRes, jdzRes);
144 | }
145 | }
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/vector/RFC2045VectorEncodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC2045VectorEncodeTest {
9 | /*
10 | * RFC2045 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "f".getBytes();
14 | private static final byte[] foVector = "fo".getBytes();
15 | private static final byte[] fooVector = "foo".getBytes();
16 | private static final byte[] foobVector = "foob".getBytes();
17 | private static final byte[] foobaVector = "fooba".getBytes();
18 | private static final byte[] foobarVector = "foobar".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 | private static final byte[] randomDataSeventySix = new byte[55];
28 |
29 | static {
30 | new Random().nextBytes(randomDataZeroMod);
31 | new Random().nextBytes(randomDataOneMod);
32 | new Random().nextBytes(randomDataTwoMod);
33 | new Random().nextBytes(randomDataThreeMod);
34 | new Random().nextBytes(randomDataSeventySix);
35 | }
36 |
37 | @Test
38 | public void RFC2045EncodeEmptyVector() {
39 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(emptyVector));
40 |
41 | assertEquals("", jdzRes);
42 | }
43 |
44 | @Test
45 | public void RFC2045EncodefVector() {
46 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(fVector));
47 |
48 | assertEquals("Zg==", jdzRes);
49 | }
50 |
51 | @Test
52 | public void RFC2045EncodefoVector() {
53 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(foVector));
54 |
55 | assertEquals("Zm8=", jdzRes);
56 | }
57 |
58 | @Test
59 | public void RFC2045EncodefooVector() {
60 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(fooVector));
61 |
62 | assertEquals("Zm9v", jdzRes);
63 | }
64 |
65 | @Test
66 | public void RFC2045EncodefoobVector() {
67 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(foobVector));
68 |
69 | assertEquals("Zm9vYg==", jdzRes);
70 | }
71 |
72 | @Test
73 | public void RFC2045EncodefoobaVector() {
74 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(foobaVector));
75 |
76 | assertEquals("Zm9vYmE=", jdzRes);
77 | }
78 |
79 | @Test
80 | public void RFC2045EncodefoobarVector() {
81 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(foobarVector));
82 |
83 | assertEquals("Zm9vYmFy", jdzRes);
84 | }
85 | @Test
86 | public void RFC2045EncodeZeroMod() {
87 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataZeroMod));
88 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(randomDataZeroMod));
89 |
90 | assertEquals(javaRes, joadRes);
91 | }
92 |
93 | @Test
94 | public void RFC2045EncodeOneMod() {
95 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataOneMod));
96 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(randomDataOneMod));
97 |
98 | assertEquals(javaRes, joadRes);
99 | }
100 |
101 | @Test
102 | public void RFC2045EncodeTwoMod() {
103 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataTwoMod));
104 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(randomDataTwoMod));
105 |
106 | assertEquals(javaRes, joadRes);
107 | }
108 |
109 | @Test
110 | public void RFC2045EncodeThreeMod() {
111 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataThreeMod));
112 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(randomDataThreeMod));
113 |
114 | assertEquals(javaRes, joadRes);
115 | }
116 |
117 | @Test
118 | public void RFC2045EncodeSeventySix() {
119 | String javaRes = new String(java.util.Base64.getMimeEncoder().encode(randomDataSeventySix));
120 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(randomDataSeventySix));
121 |
122 | assertEquals(javaRes, joadRes);
123 | }
124 | }
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/vector/RFC4648FastVectorDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648FastVectorDecodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getEncoder().encode(randomDataZeroMod);
36 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getEncoder().encode(randomDataOneMod);
37 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getEncoder().encode(randomDataTwoMod);
38 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getEncoder().encode(randomDataThreeMod);
39 |
40 | @Test
41 | public void RFC4648DecodeEmptyVector() {
42 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(emptyVector));
43 |
44 | assertEquals("", jdzRes);
45 | }
46 |
47 | @Test
48 | public void RFC4648DecodefVector() {
49 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(fVector));
50 |
51 | assertEquals("f", jdzRes);
52 | }
53 |
54 | @Test
55 | public void RFC4648DecodefoVector() {
56 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(foVector));
57 |
58 | assertEquals("fo", jdzRes);
59 | }
60 |
61 | @Test
62 | public void RFC4648DecodefooVector() {
63 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(fooVector));
64 |
65 | assertEquals("foo", jdzRes);
66 | }
67 |
68 | @Test
69 | public void RFC4648DecodefoobVector() {
70 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(foobVector));
71 |
72 | assertEquals("foob", jdzRes);
73 | }
74 |
75 | @Test
76 | public void RFC4648DecodefoobaVector() {
77 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(foobaVector));
78 |
79 | assertEquals("fooba", jdzRes);
80 | }
81 |
82 | @Test
83 | public void RFC4648DecodefoobarVector() {
84 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(foobarVector));
85 |
86 | assertEquals("foobar", jdzRes);
87 | }
88 |
89 | @Test
90 | public void RFC4648DecodeZeroMod() {
91 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataZeroMod));
92 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(base64RandomDataZeroMod));
93 |
94 | assertEquals(javaRes, jdzRes);
95 | }
96 |
97 | @Test
98 | public void RFC4648DecodeOneMod() {
99 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataOneMod));
100 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(base64RandomDataOneMod));
101 |
102 | assertEquals(javaRes, jdzRes);
103 | }
104 |
105 | @Test
106 | public void RFC4648DecodeTwoMod() {
107 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataTwoMod));
108 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(base64RandomDataTwoMod));
109 |
110 | assertEquals(javaRes, jdzRes);
111 | }
112 |
113 | @Test
114 | public void RFC4648DecodeThreeMod() {
115 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataThreeMod));
116 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(base64RandomDataThreeMod));
117 |
118 | assertEquals(javaRes, jdzRes);
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/vector/RFC4648URLFastVectorDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648URLFastVectorDecodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getUrlEncoder().encode(randomDataZeroMod);
36 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getUrlEncoder().encode(randomDataOneMod);
37 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getUrlEncoder().encode(randomDataTwoMod);
38 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getUrlEncoder().encode(randomDataThreeMod);
39 |
40 | @Test
41 | public void RFC4648DecodeEmptyVector() {
42 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(emptyVector));
43 |
44 | assertEquals("", jdzRes);
45 | }
46 |
47 | @Test
48 | public void RFC4648DecodefVector() {
49 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(fVector));
50 |
51 | assertEquals("f", jdzRes);
52 | }
53 |
54 | @Test
55 | public void RFC4648DecodefoVector() {
56 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(foVector));
57 |
58 | assertEquals("fo", jdzRes);
59 | }
60 |
61 | @Test
62 | public void RFC4648DecodefooVector() {
63 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(fooVector));
64 |
65 | assertEquals("foo", jdzRes);
66 | }
67 |
68 | @Test
69 | public void RFC4648DecodefoobVector() {
70 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(foobVector));
71 |
72 | assertEquals("foob", jdzRes);
73 | }
74 |
75 | @Test
76 | public void RFC4648DecodefoobaVector() {
77 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(foobaVector));
78 |
79 | assertEquals("fooba", jdzRes);
80 | }
81 |
82 | @Test
83 | public void RFC4648DecodefoobarVector() {
84 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(foobarVector));
85 |
86 | assertEquals("foobar", jdzRes);
87 | }
88 |
89 | @Test
90 | public void RFC4648DecodeZeroMod() {
91 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataZeroMod));
92 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(base64RandomDataZeroMod));
93 |
94 | assertEquals(javaRes, jdzRes);
95 | }
96 |
97 | @Test
98 | public void RFC4648DecodeOneMod() {
99 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataOneMod));
100 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(base64RandomDataOneMod));
101 |
102 | assertEquals(javaRes, jdzRes);
103 | }
104 |
105 | @Test
106 | public void RFC4648DecodeTwoMod() {
107 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataTwoMod));
108 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(base64RandomDataTwoMod));
109 |
110 | assertEquals(javaRes, jdzRes);
111 | }
112 |
113 | @Test
114 | public void RFC4648DecodeThreeMod() {
115 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataThreeMod));
116 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decodeFast(base64RandomDataThreeMod));
117 |
118 | assertEquals(javaRes, jdzRes);
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/vector/RFC4648URLVectorDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648URLVectorDecodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getUrlEncoder().encode(randomDataZeroMod);
36 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getUrlEncoder().encode(randomDataOneMod);
37 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getUrlEncoder().encode(randomDataTwoMod);
38 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getUrlEncoder().encode(randomDataThreeMod);
39 | private static final byte[] base64InvalidData = java.util.Base64.getUrlEncoder().encode(randomDataZeroMod);
40 |
41 | @Test
42 | public void RFC4648URLDecodeEmptyVector() {
43 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(emptyVector));
44 |
45 | assertEquals("", jdzRes);
46 | }
47 |
48 | @Test
49 | public void RFC4648URLDecodefVector() {
50 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(fVector));
51 |
52 | assertEquals("f", jdzRes);
53 | }
54 |
55 | @Test
56 | public void RFC4648URLDecodefoVector() {
57 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(foVector));
58 |
59 | assertEquals("fo", jdzRes);
60 | }
61 |
62 | @Test
63 | public void RFC4648URLDecodefooVector() {
64 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(fooVector));
65 |
66 | assertEquals("foo", jdzRes);
67 | }
68 |
69 | @Test
70 | public void RFC4648URLDecodefoobVector() {
71 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(foobVector));
72 |
73 | assertEquals("foob", jdzRes);
74 | }
75 |
76 | @Test
77 | public void RFC4648URLDecodefoobaVector() {
78 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(foobaVector));
79 |
80 | assertEquals("fooba", jdzRes);
81 | }
82 |
83 | @Test
84 | public void RFC4648URLDecodefoobarVector() {
85 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(foobarVector));
86 |
87 | assertEquals("foobar", jdzRes);
88 | }
89 |
90 | @Test
91 | public void RFC4648URLDecodeZeroMod() {
92 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataZeroMod));
93 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(base64RandomDataZeroMod));
94 |
95 | assertEquals(javaRes, jdzRes);
96 | }
97 |
98 | @Test
99 | public void RFC4648URLDecodeOneMod() {
100 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataOneMod));
101 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(base64RandomDataOneMod));
102 |
103 | assertEquals(javaRes, jdzRes);
104 | }
105 |
106 | @Test
107 | public void RFC4648URLDecodeTwoMod() {
108 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataTwoMod));
109 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(base64RandomDataTwoMod));
110 |
111 | assertEquals(javaRes, jdzRes);
112 | }
113 |
114 | @Test
115 | public void RFC4648URLDecodeThreeMod() {
116 | String javaRes = new String(java.util.Base64.getUrlDecoder().decode(base64RandomDataThreeMod));
117 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(base64RandomDataThreeMod));
118 |
119 | assertEquals(javaRes, jdzRes);
120 | }
121 |
122 | @Test
123 | public void RFC4648URLInvalidInputDecode() {
124 | base64InvalidData[100] = (byte) '$';
125 | base64InvalidData[101] = (byte) '$';
126 | base64InvalidData[102] = (byte) '$';
127 | base64InvalidData[103] = (byte) '$';
128 |
129 | String exception = "No exception";
130 |
131 | try {
132 | com.joad.jdz.base64.vector.Base64Vector.getUrlDecoder().decode(base64InvalidData);
133 | }
134 | catch (Exception e) {
135 | exception = e.getMessage();
136 | }
137 |
138 | assertEquals("Illegal base64 character 24 at position 100", exception);
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/vector/RFC4648URLVectorEncodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648URLVectorEncodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "f".getBytes();
14 | private static final byte[] foVector = "fo".getBytes();
15 | private static final byte[] fooVector = "foo".getBytes();
16 | private static final byte[] foobVector = "foob".getBytes();
17 | private static final byte[] foobaVector = "fooba".getBytes();
18 | private static final byte[] foobarVector = "foobar".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | @Test
36 | public void RFC4648EncodeEmptyVector() {
37 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(emptyVector));
38 |
39 | assertEquals("", jdzRes);
40 | }
41 |
42 | @Test
43 | public void RFC4648EncodefVector() {
44 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(fVector));
45 |
46 | assertEquals("Zg==", jdzRes);
47 | }
48 |
49 | @Test
50 | public void RFC4648EncodefoVector() {
51 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(foVector));
52 |
53 | assertEquals("Zm8=", jdzRes);
54 | }
55 |
56 | @Test
57 | public void RFC4648EncodefooVector() {
58 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(fooVector));
59 |
60 | assertEquals("Zm9v", jdzRes);
61 | }
62 |
63 | @Test
64 | public void RFC4648EncodefoobVector() {
65 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(foobVector));
66 |
67 | assertEquals("Zm9vYg==", jdzRes);
68 | }
69 |
70 | @Test
71 | public void RFC4648EncodefoobaVector() {
72 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(foobaVector));
73 |
74 | assertEquals("Zm9vYmE=", jdzRes);
75 | }
76 |
77 | @Test
78 | public void RFC4648EncodefoobarVector() {
79 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(foobarVector));
80 |
81 | assertEquals("Zm9vYmFy", jdzRes);
82 | }
83 | @Test
84 | public void RFC4648EncodeZeroMod() {
85 | String javaRes = new String(java.util.Base64.getUrlEncoder().encode(randomDataZeroMod));
86 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(randomDataZeroMod));
87 |
88 | assertEquals(javaRes, joadRes);
89 | }
90 |
91 | @Test
92 | public void RFC4648EncodeOneMod() {
93 | String javaRes = new String(java.util.Base64.getUrlEncoder().encode(randomDataOneMod));
94 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(randomDataOneMod));
95 |
96 | assertEquals(javaRes, joadRes);
97 | }
98 |
99 | @Test
100 | public void RFC4648EncodeTwoMod() {
101 | String javaRes = new String(java.util.Base64.getUrlEncoder().encode(randomDataTwoMod));
102 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(randomDataTwoMod));
103 |
104 | assertEquals(javaRes, joadRes);
105 | }
106 |
107 | @Test
108 | public void RFC4648EncodeThreeMod() {
109 | String javaRes = new String(java.util.Base64.getUrlEncoder().encode(randomDataThreeMod));
110 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getUrlEncoder().encode(randomDataThreeMod));
111 |
112 | assertEquals(javaRes, joadRes);
113 | }
114 | }
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/vector/RFC4648VectorDecodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648VectorDecodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "Zg==".getBytes();
14 | private static final byte[] foVector = "Zm8=".getBytes();
15 | private static final byte[] fooVector = "Zm9v".getBytes();
16 | private static final byte[] foobVector = "Zm9vYg==".getBytes();
17 | private static final byte[] foobaVector = "Zm9vYmE=".getBytes();
18 | private static final byte[] foobarVector = "Zm9vYmFy".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | private static final byte[] base64RandomDataZeroMod = java.util.Base64.getEncoder().encode(randomDataZeroMod);
36 | private static final byte[] base64RandomDataOneMod = java.util.Base64.getEncoder().encode(randomDataOneMod);
37 | private static final byte[] base64RandomDataTwoMod = java.util.Base64.getEncoder().encode(randomDataTwoMod);
38 | private static final byte[] base64RandomDataThreeMod = java.util.Base64.getEncoder().encode(randomDataThreeMod);
39 | private static final byte[] base64InvalidData = java.util.Base64.getEncoder().encode(randomDataZeroMod);
40 |
41 | @Test
42 | public void RFC4648DecodeEmptyVector() {
43 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(emptyVector));
44 |
45 | assertEquals("", jdzRes);
46 | }
47 |
48 | @Test
49 | public void RFC4648DecodefVector() {
50 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(fVector));
51 |
52 | assertEquals("f", jdzRes);
53 | }
54 |
55 | @Test
56 | public void RFC4648DecodefoVector() {
57 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(foVector));
58 |
59 | assertEquals("fo", jdzRes);
60 | }
61 |
62 | @Test
63 | public void RFC4648DecodefooVector() {
64 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(fooVector));
65 |
66 | assertEquals("foo", jdzRes);
67 | }
68 |
69 | @Test
70 | public void RFC4648DecodefoobVector() {
71 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(foobVector));
72 |
73 | assertEquals("foob", jdzRes);
74 | }
75 |
76 | @Test
77 | public void RFC4648DecodefoobaVector() {
78 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(foobaVector));
79 |
80 | assertEquals("fooba", jdzRes);
81 | }
82 |
83 | @Test
84 | public void RFC4648DecodefoobarVector() {
85 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(foobarVector));
86 |
87 | assertEquals("foobar", jdzRes);
88 | }
89 |
90 | @Test
91 | public void RFC4648DecodeZeroMod() {
92 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataZeroMod));
93 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(base64RandomDataZeroMod));
94 |
95 | assertEquals(javaRes, jdzRes);
96 | }
97 |
98 | @Test
99 | public void RFC4648DecodeOneMod() {
100 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataOneMod));
101 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(base64RandomDataOneMod));
102 |
103 | assertEquals(javaRes, jdzRes);
104 | }
105 |
106 | @Test
107 | public void RFC4648DecodeTwoMod() {
108 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataTwoMod));
109 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(base64RandomDataTwoMod));
110 |
111 | assertEquals(javaRes, jdzRes);
112 | }
113 |
114 | @Test
115 | public void RFC4648DecodeThreeMod() {
116 | String javaRes = new String(java.util.Base64.getDecoder().decode(base64RandomDataThreeMod));
117 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(base64RandomDataThreeMod));
118 |
119 | assertEquals(javaRes, jdzRes);
120 | }
121 |
122 | @Test
123 | public void RFC4648InvalidInputDecode() {
124 | base64InvalidData[100] = (byte) '$';
125 | base64InvalidData[101] = (byte) '$';
126 | base64InvalidData[102] = (byte) '$';
127 | base64InvalidData[103] = (byte) '$';
128 |
129 | String exception = "No exception";
130 |
131 | try {
132 | com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(base64InvalidData);
133 | }
134 | catch (Exception e) {
135 | exception = e.getMessage();
136 | }
137 |
138 | assertEquals("Illegal base64 character 24 at position 100", exception);
139 | }
140 | }
--------------------------------------------------------------------------------
/base64/src/test/java/com/joad/jdz/base64/vector/RFC4648VectorEncodeTest.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.base64.vector;
2 |
3 | import static org.junit.Assert.*;
4 |
5 | import java.util.Random;
6 | import org.junit.Test;
7 |
8 | public class RFC4648VectorEncodeTest {
9 | /*
10 | * RFC4648 test vectors
11 | */
12 | private static final byte[] emptyVector = "".getBytes();
13 | private static final byte[] fVector = "f".getBytes();
14 | private static final byte[] foVector = "fo".getBytes();
15 | private static final byte[] fooVector = "foo".getBytes();
16 | private static final byte[] foobVector = "foob".getBytes();
17 | private static final byte[] foobaVector = "fooba".getBytes();
18 | private static final byte[] foobarVector = "foobar".getBytes();
19 |
20 | /*
21 | * Random data fuzz
22 | */
23 | private static final byte[] randomDataZeroMod = new byte[1000];
24 | private static final byte[] randomDataOneMod = new byte[1001];
25 | private static final byte[] randomDataTwoMod = new byte[1002];
26 | private static final byte[] randomDataThreeMod = new byte[1003];
27 |
28 | static {
29 | new Random().nextBytes(randomDataZeroMod);
30 | new Random().nextBytes(randomDataOneMod);
31 | new Random().nextBytes(randomDataTwoMod);
32 | new Random().nextBytes(randomDataThreeMod);
33 | }
34 |
35 | @Test
36 | public void RFC4648EncodeEmptyVector() {
37 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(emptyVector));
38 |
39 | assertEquals("", jdzRes);
40 | }
41 |
42 | @Test
43 | public void RFC4648EncodefVector() {
44 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(fVector));
45 |
46 | assertEquals("Zg==", jdzRes);
47 | }
48 |
49 | @Test
50 | public void RFC4648EncodefoVector() {
51 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(foVector));
52 |
53 | assertEquals("Zm8=", jdzRes);
54 | }
55 |
56 | @Test
57 | public void RFC4648EncodefooVector() {
58 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(fooVector));
59 |
60 | assertEquals("Zm9v", jdzRes);
61 | }
62 |
63 | @Test
64 | public void RFC4648EncodefoobVector() {
65 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(foobVector));
66 |
67 | assertEquals("Zm9vYg==", jdzRes);
68 | }
69 |
70 | @Test
71 | public void RFC4648EncodefoobaVector() {
72 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(foobaVector));
73 |
74 | assertEquals("Zm9vYmE=", jdzRes);
75 | }
76 |
77 | @Test
78 | public void RFC4648EncodefoobarVector() {
79 | String jdzRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(foobarVector));
80 |
81 | assertEquals("Zm9vYmFy", jdzRes);
82 | }
83 | @Test
84 | public void RFC4648EncodeZeroMod() {
85 | String javaRes = new String(java.util.Base64.getEncoder().encode(randomDataZeroMod));
86 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(randomDataZeroMod));
87 |
88 | assertEquals(javaRes, joadRes);
89 | }
90 |
91 | @Test
92 | public void RFC4648EncodeOneMod() {
93 | String javaRes = new String(java.util.Base64.getEncoder().encode(randomDataOneMod));
94 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(randomDataOneMod));
95 |
96 | assertEquals(javaRes, joadRes);
97 | }
98 |
99 | @Test
100 | public void RFC4648EncodeTwoMod() {
101 | String javaRes = new String(java.util.Base64.getEncoder().encode(randomDataTwoMod));
102 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(randomDataTwoMod));
103 |
104 | assertEquals(javaRes, joadRes);
105 | }
106 |
107 | @Test
108 | public void RFC4648EncodeThreeMod() {
109 | String javaRes = new String(java.util.Base64.getEncoder().encode(randomDataThreeMod));
110 | String joadRes = new String(com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(randomDataThreeMod));
111 |
112 | assertEquals(javaRes, joadRes);
113 | }
114 | }
--------------------------------------------------------------------------------
/bench/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | com.joad.jdz
6 | jdz-parent
7 | 1.0
8 | ../pom.xml
9 |
10 |
11 | jdz-base64-bench
12 |
13 | Base64 Performance Benchmarks
14 |
15 |
16 |
17 | com.joad.jdz
18 | jdz-base64
19 | 1.0
20 |
21 |
22 | org.openjdk.jmh
23 | jmh-core
24 | ${jmh.version}
25 |
26 |
27 | org.openjdk.jmh
28 | jmh-generator-annprocess
29 | ${jmh.version}
30 |
31 |
32 | com.brsanthu
33 | migbase64
34 | 2.2
35 |
36 |
37 | net.iharder
38 | base64
39 | 2.3.9
40 |
41 |
42 | commons-codec
43 | commons-codec
44 | 1.16.0
45 |
46 |
47 |
48 |
49 |
50 |
51 | org.apache.maven.plugins
52 | maven-shade-plugin
53 |
54 | false
55 | jdz-bench.jar
56 |
57 |
59 |
60 | org.openjdk.jmh.Main
61 | true
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/bench/src/main/java/com/joad/jdz/bench/BenchmarkBase.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.bench;
2 |
3 | import java.util.concurrent.TimeUnit;
4 | import org.openjdk.jmh.annotations.BenchmarkMode;
5 | import org.openjdk.jmh.annotations.Fork;
6 | import org.openjdk.jmh.annotations.Measurement;
7 | import org.openjdk.jmh.annotations.OutputTimeUnit;
8 | import org.openjdk.jmh.annotations.State;
9 | import org.openjdk.jmh.annotations.Warmup;
10 | import org.openjdk.jmh.annotations.Scope;
11 | import org.openjdk.jmh.annotations.Mode;
12 |
13 | @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
14 | @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
15 | @Fork(value = 3, jvmArgsAppend = {"--add-modules", "jdk.incubator.vector"})
16 | @State(Scope.Benchmark)
17 | @OutputTimeUnit(TimeUnit.SECONDS)
18 | @BenchmarkMode(Mode.Throughput)
19 | public abstract class BenchmarkBase {
20 | protected static final int ARR_LEN = 1000000;
21 | }
--------------------------------------------------------------------------------
/bench/src/main/java/com/joad/jdz/bench/base64/Base64DecodeBenchmark.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.bench.base64;
2 |
3 | import java.io.IOException;
4 | import java.util.Random;
5 | import org.openjdk.jmh.annotations.Benchmark;
6 | import com.joad.jdz.bench.BenchmarkBase;
7 |
8 | public class Base64DecodeBenchmark extends BenchmarkBase {
9 | private static final byte[] randomDataDec = new byte[ARR_LEN];
10 |
11 | static {
12 | new Random().nextBytes(randomDataDec);
13 | }
14 |
15 | private static final byte[] randomData = java.util.Base64.getEncoder().encode(randomDataDec);
16 |
17 | private static final byte[] dst = new byte[com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().getDecodedLength(randomData)];
18 |
19 | @Benchmark
20 | public byte[] jdzBase64ScalarDecode() {
21 | return com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(randomData);
22 | }
23 |
24 | @Benchmark
25 | public byte[] jdzBase64ScalarDecodeReuse() {
26 | com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decode(randomData, dst);
27 |
28 | return dst;
29 | }
30 |
31 | @Benchmark
32 | public byte[] jdzBase64VectorDecode() {
33 | return com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(randomData);
34 | }
35 |
36 | @Benchmark
37 | public byte[] jdzBase64VectorDecodeReuse() {
38 | com.joad.jdz.base64.vector.Base64Vector.getDecoder().decode(randomData, dst);
39 |
40 | return dst;
41 | }
42 |
43 | @Benchmark
44 | public byte[] jdzBase64ScalarDecodeFast() {
45 | return com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(randomData);
46 | }
47 |
48 | @Benchmark
49 | public byte[] jdzBase64ScalarDecodeReuseFast() {
50 | com.joad.jdz.base64.scalar.Base64Scalar.getDecoder().decodeFast(randomData, dst);
51 |
52 | return dst;
53 | }
54 |
55 | @Benchmark
56 | public byte[] jdzBase64VectorDecodeFast() {
57 | return com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(randomData);
58 | }
59 |
60 | @Benchmark
61 | public byte[] jdzBase64VectorDecodeReuseFast() {
62 | com.joad.jdz.base64.vector.Base64Vector.getDecoder().decodeFast(randomData, dst);
63 |
64 | return dst;
65 | }
66 |
67 | @Benchmark
68 | public byte[] javaUtilBase64Decode() {
69 | return java.util.Base64.getDecoder().decode(randomData);
70 | }
71 |
72 | @Benchmark
73 | public byte[] javaUtilBase64DecodeReuse() {
74 | java.util.Base64.getDecoder().decode(randomData, dst);
75 |
76 | return dst;
77 | }
78 |
79 | @Benchmark
80 | public byte[] migBase64Decode() {
81 | return com.migcomponents.migbase64.Base64.decode(randomData);
82 | }
83 |
84 | @Benchmark
85 | public byte[] migBase64DecodeFast() {
86 | return com.migcomponents.migbase64.Base64.decodeFast(randomData);
87 | }
88 |
89 | @Benchmark
90 | public byte[] iharderBase64Decode() throws IOException {
91 | return net.iharder.Base64.decode(randomData, 0, randomData.length, 0);
92 | }
93 |
94 | @Benchmark
95 | public byte[] apacheBase64Decode() {
96 | return org.apache.commons.codec.binary.Base64.decodeBase64(randomData);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/bench/src/main/java/com/joad/jdz/bench/base64/Base64EncodeBenchmark.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.bench.base64;
2 |
3 | import java.util.Random;
4 | import org.openjdk.jmh.annotations.Benchmark;
5 | import com.joad.jdz.bench.BenchmarkBase;
6 | import com.migcomponents.migbase64.Base64;
7 |
8 | public class Base64EncodeBenchmark extends BenchmarkBase {
9 | private static final byte[] randomData = new byte[ARR_LEN];
10 |
11 | private static final int dl = Math.multiplyExact(4, (Math.addExact(randomData.length, 2) / 3));
12 |
13 | private static final byte[] dst = new byte[dl];
14 |
15 | static {
16 | new Random().nextBytes(randomData);
17 | }
18 |
19 | @Benchmark
20 | public byte[] jdzBase64VectorEncode() {
21 | return com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(randomData);
22 | }
23 |
24 | @Benchmark
25 | public byte[] jdzBase64VectorEncodeReuse() {
26 | com.joad.jdz.base64.vector.Base64Vector.getEncoder().encode(randomData, dst);
27 |
28 | return dst;
29 | }
30 |
31 | @Benchmark
32 | public byte[] jdzBase64ScalarEncode() {
33 | return com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(randomData);
34 | }
35 |
36 | @Benchmark
37 | public byte[] jdzBase64ScalarEncodeReuse() {
38 | com.joad.jdz.base64.scalar.Base64Scalar.getEncoder().encode(randomData, dst);
39 |
40 | return dst;
41 | }
42 |
43 | @Benchmark
44 | public byte[] javaUtilBase64Encode() {
45 | return java.util.Base64.getEncoder().encode(randomData);
46 | }
47 |
48 | @Benchmark
49 | public byte[] javaUtilBase64EncodeReuse() {
50 | java.util.Base64.getEncoder().encode(randomData, dst);
51 |
52 | return dst;
53 | }
54 |
55 | @Benchmark
56 | public byte[] migBase64Encode() {
57 | return Base64.encodeToByte(randomData, false);
58 | }
59 |
60 | @Benchmark
61 | public byte[] iharderBase64Encode() {
62 | return net.iharder.Base64.encodeBytesToBytes(randomData);
63 | }
64 |
65 | @Benchmark
66 | public byte[] apacheBase64Encode() {
67 | return org.apache.commons.codec.binary.Base64.encodeBase64(randomData);
68 | }
69 | }
--------------------------------------------------------------------------------
/bench/src/main/java/com/joad/jdz/bench/base64/Base64MimeDecodeBenchmark.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.bench.base64;
2 |
3 | import java.io.IOException;
4 | import java.util.Random;
5 | import org.openjdk.jmh.annotations.Benchmark;
6 | import com.joad.jdz.bench.BenchmarkBase;
7 |
8 | public class Base64MimeDecodeBenchmark extends BenchmarkBase {
9 | private static final byte[] randomDataDec = new byte[ARR_LEN];
10 |
11 | static {
12 | new Random().nextBytes(randomDataDec);
13 | }
14 |
15 | private static final byte[] randomData = java.util.Base64.getMimeEncoder().encode(randomDataDec);
16 |
17 | private static final byte[] dst = new byte[com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().getDecodedLengthFast(randomData)];
18 |
19 | @Benchmark
20 | public byte[] jdzBase64FastMimeScalarDecode() {
21 | return com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(randomData);
22 | }
23 |
24 | @Benchmark
25 | public byte[] jdzBase64FastMimeScalarDecodeReuse() {
26 | com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decodeFast(randomData, dst);
27 |
28 | return dst;
29 | }
30 |
31 | @Benchmark
32 | public byte[] jdzBase64FastMimeVectorDecode() {
33 | return com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(randomData);
34 | }
35 |
36 | @Benchmark
37 | public byte[] jdzBase64FastMimeVectorDecodeReuse() {
38 | com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decodeFast(randomData, dst);
39 |
40 | return dst;
41 | }
42 |
43 | @Benchmark
44 | public byte[] jdzBase64MimeScalarDecode() {
45 | return com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(randomData);
46 | }
47 |
48 | @Benchmark
49 | public byte[] jdzBase64MimeScalarDecodeReuse() {
50 | com.joad.jdz.base64.scalar.Base64Scalar.getMimeDecoder().decode(randomData, dst);
51 |
52 | return dst;
53 | }
54 |
55 | @Benchmark
56 | public byte[] jdzBase64MimeVectorDecode() {
57 | return com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(randomData);
58 | }
59 |
60 | @Benchmark
61 | public byte[] jdzBase64MimeVectorDecodeReuse() {
62 | com.joad.jdz.base64.vector.Base64Vector.getMimeDecoder().decode(randomData, dst);
63 |
64 | return dst;
65 | }
66 |
67 | @Benchmark
68 | public byte[] javaUtilBase64MimeDecode() {
69 | return java.util.Base64.getMimeDecoder().decode(randomData);
70 | }
71 |
72 | @Benchmark
73 | public byte[] javaUtilBase64MimeDecodeReuse() {
74 | java.util.Base64.getMimeDecoder().decode(randomData, dst);
75 |
76 | return dst;
77 | }
78 |
79 | @Benchmark
80 | public byte[] migBase64MimeDecode() {
81 | return com.migcomponents.migbase64.Base64.decode(randomData);
82 | }
83 |
84 | @Benchmark
85 | public byte[] migBase64MimeDecodeFast() {
86 | return com.migcomponents.migbase64.Base64.decodeFast(randomData);
87 | }
88 |
89 | @Benchmark
90 | public byte[] iharderBase64MimeDecode() throws IOException {
91 | return net.iharder.Base64.decode(randomData, 0, randomData.length, 8);
92 | }
93 |
94 | @Benchmark
95 | public byte[] apacheBase64MimeDecode() {
96 | return org.apache.commons.codec.binary.Base64.decodeBase64(randomData);
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/bench/src/main/java/com/joad/jdz/bench/base64/Base64MimeEncodeBenchmark.java:
--------------------------------------------------------------------------------
1 | package com.joad.jdz.bench.base64;
2 |
3 | import java.io.IOException;
4 | import java.util.Random;
5 | import org.openjdk.jmh.annotations.Benchmark;
6 | import com.joad.jdz.bench.BenchmarkBase;
7 | import com.migcomponents.migbase64.Base64;
8 |
9 | public class Base64MimeEncodeBenchmark extends BenchmarkBase {
10 | private static final byte[] randomData = new byte[ARR_LEN];
11 |
12 | private static final int dl = com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().getEncodedLength(randomData);
13 |
14 | private static final byte[] dst = new byte[dl];
15 |
16 | static {
17 | new Random().nextBytes(randomData);
18 | }
19 |
20 | @Benchmark
21 | public byte[] jdzBase64MimeVectorEncode() {
22 | return com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(randomData);
23 | }
24 |
25 | @Benchmark
26 | public byte[] jdzBase64MimeVectorEncodeReuse() {
27 | com.joad.jdz.base64.vector.Base64Vector.getMimeEncoder().encode(randomData, dst);
28 |
29 | return dst;
30 | }
31 |
32 | @Benchmark
33 | public byte[] jdzBase64MimeScalarEncode() {
34 | return com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(randomData);
35 | }
36 |
37 | @Benchmark
38 | public byte[] jdzBase64MimeScalarEncodeReuse() {
39 | com.joad.jdz.base64.scalar.Base64Scalar.getMimeEncoder().encode(randomData, dst);
40 |
41 | return dst;
42 | }
43 |
44 | @Benchmark
45 | public byte[] javaUtilBase64MimeEncode() {
46 | return java.util.Base64.getMimeEncoder().encode(randomData);
47 | }
48 |
49 | @Benchmark
50 | public byte[] javaUtilBase64MimeEncodeReuse() {
51 | java.util.Base64.getMimeEncoder().encode(randomData, dst);
52 |
53 | return dst;
54 | }
55 |
56 | @Benchmark
57 | public byte[] migBase64MimeEncode() {
58 | return Base64.encodeToByte(randomData, true);
59 | }
60 |
61 | @Benchmark
62 | public byte[] iharderBase64MimeEncode() throws IOException {
63 | return net.iharder.Base64.encodeBytesToBytes(randomData, 0, randomData.length, 8);
64 | }
65 |
66 | @Benchmark
67 | public byte[] apacheBase64MimeEncode() {
68 | return org.apache.commons.codec.binary.Base64.encodeBase64Chunked(randomData);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | com.joad.jdz
6 | jdz-parent
7 | 1.0
8 | pom
9 |
10 | jdz
11 |
12 |
13 | UTF-8
14 | 16
15 | 1.21
16 | 4.12
17 |
18 |
19 |
20 | base64
21 | bench
22 |
23 |
24 |
25 |
26 |
27 |
28 | org.codehaus.mojo
29 | build-helper-maven-plugin
30 | 3.0.0
31 |
32 |
33 | org.apache.maven.plugins
34 | maven-compiler-plugin
35 | 3.10.1
36 |
37 |
38 | org.apache.maven.plugins
39 | maven-dependency-plugin
40 | 3.1.0
41 |
42 |
43 | org.apache.maven.plugins
44 | maven-jar-plugin
45 | 3.2.0
46 |
47 |
48 | org.apache.maven.plugins
49 | maven-javadoc-plugin
50 | 3.1.0
51 |
52 |
53 | org.codehaus.mojo
54 | flatten-maven-plugin
55 | 1.5.0
56 |
57 |
58 | org.apache.maven.plugins
59 | maven-shade-plugin
60 | 3.4.1
61 |
62 |
63 | package
64 |
65 | shade
66 |
67 |
68 |
69 |
70 | *:*
71 |
72 | META-INF/*.SF
73 | META-INF/*.DSA
74 | META-INF/*.RSA
75 | META-INF/versions/11/module-info.class
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | org.apache.maven.plugins
85 | maven-surefire-plugin
86 | 3.0.0
87 |
88 |
89 |
90 |
91 |
92 | org.apache.maven.plugins
93 | maven-compiler-plugin
94 |
95 | ${java.version}
96 |
97 | -Xlint:all
98 | --add-modules=jdk.incubator.vector
99 |
100 |
101 |
102 |
103 | org.apache.maven.plugins
104 | maven-surefire-plugin
105 |
106 |
107 | --add-modules=jdk.incubator.vector
108 |
109 |
110 |
111 |
112 | org.codehaus.mojo
113 | flatten-maven-plugin
114 |
115 |
116 |
117 | flatten
118 | process-resources
119 |
120 | flatten
121 |
122 |
123 |
124 |
125 | flatten.clean
126 | clean
127 |
128 | clean
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
--------------------------------------------------------------------------------