Skip to content

Commit 68199f1

Browse files
committed
Internal refactoring
1 parent e7cc9d1 commit 68199f1

File tree

3 files changed

+93
-46
lines changed

3 files changed

+93
-46
lines changed

src/main/java/org/apache/commons/codec/binary/Base32.java

Lines changed: 33 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.apache.commons.codec.binary;
1919

20+
import java.util.Arrays;
2021
import java.util.Objects;
2122

2223
import org.apache.commons.codec.CodecPolicy;
@@ -85,11 +86,13 @@ public static class Builder extends AbstractBuilder<Base32, Builder> {
8586
*/
8687
public Builder() {
8788
super(ENCODE_TABLE);
89+
setEncodedBlockSize(BYTES_PER_ENCODED_BLOCK);
90+
setUnencodedBlockSize(BYTES_PER_UNENCODED_BLOCK);
8891
}
8992

9093
@Override
9194
public Base32 get() {
92-
return new Base32(getLineLength(), getLineSeparator(), getEncodeTable(), getPadding(), getDecodingPolicy());
95+
return new Base32(this);
9396
}
9497

9598
/**
@@ -338,6 +341,33 @@ public Base32(final boolean useHex, final byte padding) {
338341
this(0, null, useHex, padding);
339342
}
340343

344+
private Base32(final Builder builder) {
345+
super(builder);
346+
Objects.requireNonNull(builder.getEncodeTable(), "encodeTable");
347+
this.encodeTable = builder.getEncodeTable();
348+
this.decodeTable = builder.getEncodeTable() == HEX_ENCODE_TABLE || Arrays.equals(builder.getEncodeTable(), HEX_ENCODE_TABLE) ?
349+
HEX_DECODE_TABLE : DECODE_TABLE;
350+
if (builder.getLineLength() > 0) {
351+
if (builder.getLineSeparator() == null) {
352+
throw new IllegalArgumentException("lineLength " + lineLength + " > 0, but lineSeparator is null");
353+
}
354+
final byte[] lineSeparatorCopy = builder.getLineSeparator().clone();
355+
// Must be done after initializing the tables
356+
if (containsAlphabetOrPad(lineSeparatorCopy)) {
357+
final String sep = StringUtils.newStringUtf8(lineSeparatorCopy);
358+
throw new IllegalArgumentException("lineSeparator must not contain Base32 characters: [" + sep + "]");
359+
}
360+
this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparatorCopy.length;
361+
this.lineSeparator = lineSeparatorCopy;
362+
} else {
363+
this.encodeSize = BYTES_PER_ENCODED_BLOCK;
364+
this.lineSeparator = null;
365+
}
366+
if (isInAlphabet(builder.getPadding()) || Character.isWhitespace(builder.getPadding())) {
367+
throw new IllegalArgumentException("pad must not be in alphabet or whitespace");
368+
}
369+
}
370+
341371
/**
342372
* Constructs a Base32 codec used for decoding and encoding.
343373
* <p>
@@ -469,50 +499,8 @@ public Base32(final int lineLength, final byte[] lineSeparator, final boolean us
469499
*/
470500
@Deprecated
471501
public Base32(final int lineLength, final byte[] lineSeparator, final boolean useHex, final byte padding, final CodecPolicy decodingPolicy) {
472-
this(lineLength, lineSeparator, encodeTable(useHex), padding, decodingPolicy);
473-
}
474-
475-
/**
476-
* Constructs a Base32 / Base32 Hex codec used for decoding and encoding.
477-
* <p>
478-
* When encoding the line length and line separator are given in the constructor.
479-
* </p>
480-
* <p>
481-
* Line lengths that aren't multiples of 8 will still essentially end up being multiples of 8 in the encoded data.
482-
* </p>
483-
*
484-
* @param lineLength Each line of encoded data will be at most of the given length (rounded down to the nearest multiple of 8). If lineLength &lt;= 0,
485-
* then the output will not be divided into lines (chunks). Ignored when decoding.
486-
* @param lineSeparator Each line of encoded data will end with this sequence of bytes.
487-
* @param encodeTable A Base32 alphabet.
488-
* @param padding padding byte.
489-
* @param decodingPolicy The decoding policy.
490-
* @throws IllegalArgumentException Thrown when the {@code lineSeparator} contains Base32 characters. Or the lineLength &gt; 0 and lineSeparator is null.
491-
*/
492-
private Base32(final int lineLength, final byte[] lineSeparator, final byte[] encodeTable, final byte padding, final CodecPolicy decodingPolicy) {
493-
super(BYTES_PER_UNENCODED_BLOCK, BYTES_PER_ENCODED_BLOCK, lineLength, toLength(lineSeparator), padding, decodingPolicy);
494-
Objects.requireNonNull(encodeTable, "encodeTable");
495-
this.encodeTable = encodeTable;
496-
this.decodeTable = encodeTable == HEX_ENCODE_TABLE ? HEX_DECODE_TABLE : DECODE_TABLE;
497-
if (lineLength > 0) {
498-
if (lineSeparator == null) {
499-
throw new IllegalArgumentException("lineLength " + lineLength + " > 0, but lineSeparator is null");
500-
}
501-
final byte[] lineSeparatorCopy = lineSeparator.clone();
502-
// Must be done after initializing the tables
503-
if (containsAlphabetOrPad(lineSeparatorCopy)) {
504-
final String sep = StringUtils.newStringUtf8(lineSeparatorCopy);
505-
throw new IllegalArgumentException("lineSeparator must not contain Base32 characters: [" + sep + "]");
506-
}
507-
this.encodeSize = BYTES_PER_ENCODED_BLOCK + lineSeparatorCopy.length;
508-
this.lineSeparator = lineSeparatorCopy;
509-
} else {
510-
this.encodeSize = BYTES_PER_ENCODED_BLOCK;
511-
this.lineSeparator = null;
512-
}
513-
if (isInAlphabet(padding) || Character.isWhitespace(padding)) {
514-
throw new IllegalArgumentException("pad must not be in alphabet or whitespace");
515-
}
502+
this(builder().setLineLength(lineLength).setLineSeparator(lineSeparator).setEncodeTableRaw(encodeTable(useHex)).setPadding(padding)
503+
.setDecodingPolicy(decodingPolicy));
516504
}
517505

518506
/**

src/main/java/org/apache/commons/codec/binary/BaseNCodec.java

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder {
6161
*/
6262
public abstract static class AbstractBuilder<T, B extends AbstractBuilder<T, B>> implements Supplier<T> {
6363

64+
private int unencodedBlockSize;
65+
private int encodedBlockSize;
6466
private CodecPolicy decodingPolicy = DECODING_POLICY_DEFAULT;
6567
private int lineLength;
6668
private byte[] lineSeparator = CHUNK_SEPARATOR;
@@ -94,6 +96,10 @@ CodecPolicy getDecodingPolicy() {
9496
return decodingPolicy;
9597
}
9698

99+
int getEncodedBlockSize() {
100+
return encodedBlockSize;
101+
}
102+
97103
byte[] getEncodeTable() {
98104
return encodeTable;
99105
}
@@ -110,6 +116,10 @@ byte getPadding() {
110116
return padding;
111117
}
112118

119+
int getUnencodedBlockSize() {
120+
return unencodedBlockSize;
121+
}
122+
113123
/**
114124
* Sets the decoding policy.
115125
*
@@ -121,6 +131,17 @@ public B setDecodingPolicy(final CodecPolicy decodingPolicy) {
121131
return asThis();
122132
}
123133

134+
/**
135+
* Sets the encoded block size, subclasses normally set this on construction.
136+
*
137+
* @param encodedBlockSize the encoded block size, subclasses normally set this on construction.
138+
* @return this
139+
*/
140+
B setEncodedBlockSize(final int encodedBlockSize) {
141+
this.encodedBlockSize = encodedBlockSize;
142+
return asThis();
143+
}
144+
124145
/**
125146
* Sets the encode table.
126147
*
@@ -132,6 +153,17 @@ public B setEncodeTable(final byte... encodeTable) {
132153
return asThis();
133154
}
134155

156+
/**
157+
* Sets the encode table.
158+
*
159+
* @param encodeTable the encode table, null resets to the default.
160+
* @return {@code this} instance.
161+
*/
162+
B setEncodeTableRaw(final byte... encodeTable) {
163+
this.encodeTable = encodeTable != null ? encodeTable : defaultEncodeTable;
164+
return asThis();
165+
}
166+
135167
/**
136168
* Sets the line length.
137169
*
@@ -165,6 +197,17 @@ public B setPadding(final byte padding) {
165197
return asThis();
166198
}
167199

200+
/**
201+
* Sets the unencoded block size, subclasses normally set this on construction.
202+
*
203+
* @param unencodedBlockSize the unencoded block size, subclasses normally set this on construction.
204+
* @return this
205+
*/
206+
B setUnencodedBlockSize(final int unencodedBlockSize) {
207+
this.unencodedBlockSize = unencodedBlockSize;
208+
return asThis();
209+
}
210+
168211
}
169212

170213
/**
@@ -440,6 +483,22 @@ static int toLength(final byte[] array) {
440483
*/
441484
private final CodecPolicy decodingPolicy;
442485

486+
/**
487+
* Constructs a new instance for a subclass.
488+
*
489+
* @param builder How to build this portion of the instance.
490+
* @since 1.20.0
491+
*/
492+
protected BaseNCodec(final AbstractBuilder<?, ?> builder) {
493+
this.unencodedBlockSize = builder.unencodedBlockSize;
494+
this.encodedBlockSize = builder.encodedBlockSize;
495+
final boolean useChunking = builder.lineLength > 0 && builder.lineSeparator.length > 0;
496+
this.lineLength = useChunking ? builder.lineLength / builder.encodedBlockSize * builder.encodedBlockSize : 0;
497+
this.chunkSeparatorLength = builder.lineSeparator.length;
498+
this.pad = builder.padding;
499+
this.decodingPolicy = Objects.requireNonNull(builder.decodingPolicy, "codecPolicy");
500+
}
501+
443502
/**
444503
* Constructs a new instance.
445504
* <p>

src/test/java/org/apache/commons/codec/binary/Base32Test.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ void testConstructors() {
427427
// even when line length is negative.
428428
base32 = new Base32(-1, new byte[] { 'A' });
429429
base32 = new Base32(32, new byte[] { '$' }); // OK
430-
assertThrows(IllegalArgumentException.class, () -> new Base32(32, null), "null line separator");
430+
assertArrayEquals(BaseNCodec.CHUNK_SEPARATOR, new Base32(32, null).getLineSeparator(), "null line separator use the default");
431431
assertThrows(IllegalArgumentException.class, () -> new Base32(32, new byte[] { 'A' }), "'A' as a line separator");
432432
assertThrows(IllegalArgumentException.class, () -> new Base32(32, new byte[] { '=' }), "'=' as a line separator");
433433
assertThrows(IllegalArgumentException.class, () -> new Base32(32, new byte[] { 'A', '$' }), "'A$' as a line separator");

0 commit comments

Comments
 (0)