001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.codec.binary; 019 020import java.util.Arrays; 021import java.util.Objects; 022 023import org.apache.commons.codec.BinaryDecoder; 024import org.apache.commons.codec.BinaryEncoder; 025import org.apache.commons.codec.CodecPolicy; 026import org.apache.commons.codec.DecoderException; 027import org.apache.commons.codec.EncoderException; 028 029/** 030 * Abstract superclass for Base-N encoders and decoders. 031 * 032 * <p> 033 * This class is thread-safe. 034 * </p> 035 * 036 * You can set the decoding behavior when the input bytes contain leftover trailing bits that cannot be created by a valid 037 * encoding. These can be bits that are unused from the final character or entire characters. The default mode is 038 * lenient decoding. 039 * <ul> 040 * <li>Lenient: Any trailing bits are composed into 8-bit bytes where possible. The remainder are discarded. 041 * <li>Strict: The decoding will raise an {@link IllegalArgumentException} if trailing bits are not part of a valid 042 * encoding. Any unused bits from the final character must be zero. Impossible counts of entire final characters are not 043 * allowed. 044 * </ul> 045 * <p> 046 * When strict decoding is enabled it is expected that the decoded bytes will be re-encoded to a byte array that matches 047 * the original, i.e. no changes occur on the final character. This requires that the input bytes use the same padding 048 * and alphabet as the encoder. 049 * </p> 050 */ 051public abstract class BaseNCodec implements BinaryEncoder, BinaryDecoder { 052 053 /** 054 * Holds thread context so classes can be thread-safe. 055 * 056 * This class is not itself thread-safe; each thread must allocate its own copy. 057 * 058 * @since 1.7 059 */ 060 static class Context { 061 062 /** 063 * Place holder for the bytes we're dealing with for our based logic. 064 * Bitwise operations store and extract the encoding or decoding from this variable. 065 */ 066 int ibitWorkArea; 067 068 /** 069 * Place holder for the bytes we're dealing with for our based logic. 070 * Bitwise operations store and extract the encoding or decoding from this variable. 071 */ 072 long lbitWorkArea; 073 074 /** 075 * Buffer for streaming. 076 */ 077 byte[] buffer; 078 079 /** 080 * Position where next character should be written in the buffer. 081 */ 082 int pos; 083 084 /** 085 * Position where next character should be read from the buffer. 086 */ 087 int readPos; 088 089 /** 090 * Boolean flag to indicate the EOF has been reached. Once EOF has been reached, this object becomes useless, 091 * and must be thrown away. 092 */ 093 boolean eof; 094 095 /** 096 * Variable tracks how many characters have been written to the current line. Only used when encoding. We use 097 * it to make sure each encoded line never goes beyond lineLength (if lineLength > 0). 098 */ 099 int currentLinePos; 100 101 /** 102 * Writes to the buffer only occur after every 3/5 reads when encoding, and every 4/8 reads when decoding. This 103 * variable helps track that. 104 */ 105 int modulus; 106 107 Context() { 108 } 109 110 /** 111 * Returns a String useful for debugging (especially within a debugger.) 112 * 113 * @return a String useful for debugging. 114 */ 115 @SuppressWarnings("boxing") // OK to ignore boxing here 116 @Override 117 public String toString() { 118 return String.format("%s[buffer=%s, currentLinePos=%s, eof=%s, ibitWorkArea=%s, lbitWorkArea=%s, " + 119 "modulus=%s, pos=%s, readPos=%s]", this.getClass().getSimpleName(), Arrays.toString(buffer), 120 currentLinePos, eof, ibitWorkArea, lbitWorkArea, modulus, pos, readPos); 121 } 122 } 123 124 /** 125 * EOF 126 * 127 * @since 1.7 128 */ 129 static final int EOF = -1; 130 131 /** 132 * MIME chunk size per RFC 2045 section 6.8. 133 * 134 * <p> 135 * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any 136 * equal signs. 137 * </p> 138 * 139 * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 6.8</a> 140 */ 141 public static final int MIME_CHUNK_SIZE = 76; 142 143 /** 144 * PEM chunk size per RFC 1421 section 4.3.2.4. 145 * 146 * <p> 147 * The {@value} character limit does not count the trailing CRLF, but counts all other characters, including any 148 * equal signs. 149 * </p> 150 * 151 * @see <a href="http://tools.ietf.org/html/rfc1421">RFC 1421 section 4.3.2.4</a> 152 */ 153 public static final int PEM_CHUNK_SIZE = 64; 154 155 private static final int DEFAULT_BUFFER_RESIZE_FACTOR = 2; 156 157 /** 158 * Defines the default buffer size - currently {@value} 159 * - must be large enough for at least one encoded block+separator 160 */ 161 private static final int DEFAULT_BUFFER_SIZE = 8192; 162 163 /** 164 * The maximum size buffer to allocate. 165 * 166 * <p>This is set to the same size used in the JDK {@code java.util.ArrayList}:</p> 167 * <blockquote> 168 * Some VMs reserve some header words in an array. 169 * Attempts to allocate larger arrays may result in 170 * OutOfMemoryError: Requested array size exceeds VM limit. 171 * </blockquote> 172 */ 173 private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8; 174 175 /** Mask used to extract 8 bits, used in decoding bytes */ 176 protected static final int MASK_8BITS = 0xff; 177 178 /** 179 * Byte used to pad output. 180 */ 181 protected static final byte PAD_DEFAULT = '='; // Allow static access to default 182 183 /** 184 * The default decoding policy. 185 * @since 1.15 186 */ 187 protected static final CodecPolicy DECODING_POLICY_DEFAULT = CodecPolicy.LENIENT; 188 189 /** 190 * Chunk separator per RFC 2045 section 2.1. 191 * 192 * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a> 193 */ 194 static final byte[] CHUNK_SEPARATOR = {'\r', '\n'}; 195 196 /** 197 * Compares two {@code int} values numerically treating the values 198 * as unsigned. Taken from JDK 1.8. 199 * 200 * <p>TODO: Replace with JDK 1.8 Integer::compareUnsigned(int, int).</p> 201 * 202 * @param x the first {@code int} to compare 203 * @param y the second {@code int} to compare 204 * @return the value {@code 0} if {@code x == y}; a value less 205 * than {@code 0} if {@code x < y} as unsigned values; and 206 * a value greater than {@code 0} if {@code x > y} as 207 * unsigned values 208 */ 209 private static int compareUnsigned(final int x, final int y) { 210 return Integer.compare(x + Integer.MIN_VALUE, y + Integer.MIN_VALUE); 211 } 212 213 /** 214 * Create a positive capacity at least as large the minimum required capacity. 215 * If the minimum capacity is negative then this throws an OutOfMemoryError as no array 216 * can be allocated. 217 * 218 * @param minCapacity the minimum capacity 219 * @return the capacity 220 * @throws OutOfMemoryError if the {@code minCapacity} is negative 221 */ 222 private static int createPositiveCapacity(final int minCapacity) { 223 if (minCapacity < 0) { 224 // overflow 225 throw new OutOfMemoryError("Unable to allocate array size: " + (minCapacity & 0xffffffffL)); 226 } 227 // This is called when we require buffer expansion to a very big array. 228 // Use the conservative maximum buffer size if possible, otherwise the biggest required. 229 // 230 // Note: In this situation JDK 1.8 java.util.ArrayList returns Integer.MAX_VALUE. 231 // This excludes some VMs that can exceed MAX_BUFFER_SIZE but not allocate a full 232 // Integer.MAX_VALUE length array. 233 // The result is that we may have to allocate an array of this size more than once if 234 // the capacity must be expanded again. 235 return (minCapacity > MAX_BUFFER_SIZE) ? 236 minCapacity : 237 MAX_BUFFER_SIZE; 238 } 239 240 /** 241 * Gets a copy of the chunk separator per RFC 2045 section 2.1. 242 * 243 * @return the chunk separator 244 * @see <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045 section 2.1</a> 245 * @since 1.15 246 */ 247 public static byte[] getChunkSeparator() { 248 return CHUNK_SEPARATOR.clone(); 249 } 250 251 /** 252 * Checks if a byte value is whitespace or not. 253 * Whitespace is taken to mean: space, tab, CR, LF 254 * @param byteToCheck 255 * the byte to check 256 * @return true if byte is whitespace, false otherwise 257 */ 258 protected static boolean isWhiteSpace(final byte byteToCheck) { 259 switch (byteToCheck) { 260 case ' ' : 261 case '\n' : 262 case '\r' : 263 case '\t' : 264 return true; 265 default : 266 return false; 267 } 268 } 269 270 /** 271 * Increases our buffer by the {@link #DEFAULT_BUFFER_RESIZE_FACTOR}. 272 * @param context the context to be used 273 * @param minCapacity the minimum required capacity 274 * @return the resized byte[] buffer 275 * @throws OutOfMemoryError if the {@code minCapacity} is negative 276 */ 277 private static byte[] resizeBuffer(final Context context, final int minCapacity) { 278 // Overflow-conscious code treats the min and new capacity as unsigned. 279 final int oldCapacity = context.buffer.length; 280 int newCapacity = oldCapacity * DEFAULT_BUFFER_RESIZE_FACTOR; 281 if (compareUnsigned(newCapacity, minCapacity) < 0) { 282 newCapacity = minCapacity; 283 } 284 if (compareUnsigned(newCapacity, MAX_BUFFER_SIZE) > 0) { 285 newCapacity = createPositiveCapacity(minCapacity); 286 } 287 288 final byte[] b = new byte[newCapacity]; 289 System.arraycopy(context.buffer, 0, b, 0, context.buffer.length); 290 context.buffer = b; 291 return b; 292 } 293 294 /** 295 * @deprecated Use {@link #pad}. Will be removed in 2.0. 296 */ 297 @Deprecated 298 protected final byte PAD = PAD_DEFAULT; // instance variable just in case it needs to vary later 299 300 protected final byte pad; // instance variable just in case it needs to vary later 301 302 /** Number of bytes in each full block of unencoded data, e.g. 4 for Base64 and 5 for Base32 */ 303 private final int unencodedBlockSize; 304 305 /** Number of bytes in each full block of encoded data, e.g. 3 for Base64 and 8 for Base32 */ 306 private final int encodedBlockSize; 307 308 /** 309 * Chunksize for encoding. Not used when decoding. 310 * A value of zero or less implies no chunking of the encoded data. 311 * Rounded down to nearest multiple of encodedBlockSize. 312 */ 313 protected final int lineLength; 314 315 /** 316 * Size of chunk separator. Not used unless {@link #lineLength} > 0. 317 */ 318 private final int chunkSeparatorLength; 319 320 /** 321 * Defines the decoding behavior when the input bytes contain leftover trailing bits that 322 * cannot be created by a valid encoding. These can be bits that are unused from the final 323 * character or entire characters. The default mode is lenient decoding. Set this to 324 * {@code true} to enable strict decoding. 325 * <ul> 326 * <li>Lenient: Any trailing bits are composed into 8-bit bytes where possible. 327 * The remainder are discarded. 328 * <li>Strict: The decoding will raise an {@link IllegalArgumentException} if trailing bits 329 * are not part of a valid encoding. Any unused bits from the final character must 330 * be zero. Impossible counts of entire final characters are not allowed. 331 * </ul> 332 * 333 * <p>When strict decoding is enabled it is expected that the decoded bytes will be re-encoded 334 * to a byte array that matches the original, i.e. no changes occur on the final 335 * character. This requires that the input bytes use the same padding and alphabet 336 * as the encoder. 337 */ 338 private final CodecPolicy decodingPolicy; 339 340 /** 341 * Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size. 342 * If {@code chunkSeparatorLength} is zero, then chunking is disabled. 343 * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) 344 * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) 345 * @param lineLength if > 0, use chunking with a length {@code lineLength} 346 * @param chunkSeparatorLength the chunk separator length, if relevant 347 */ 348 protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, 349 final int lineLength, final int chunkSeparatorLength) { 350 this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, PAD_DEFAULT); 351 } 352 353 /** 354 * Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size. 355 * If {@code chunkSeparatorLength} is zero, then chunking is disabled. 356 * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) 357 * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) 358 * @param lineLength if > 0, use chunking with a length {@code lineLength} 359 * @param chunkSeparatorLength the chunk separator length, if relevant 360 * @param pad byte used as padding byte. 361 */ 362 protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, 363 final int lineLength, final int chunkSeparatorLength, final byte pad) { 364 this(unencodedBlockSize, encodedBlockSize, lineLength, chunkSeparatorLength, pad, DECODING_POLICY_DEFAULT); 365 } 366 367 /** 368 * Note {@code lineLength} is rounded down to the nearest multiple of the encoded block size. 369 * If {@code chunkSeparatorLength} is zero, then chunking is disabled. 370 * @param unencodedBlockSize the size of an unencoded block (e.g. Base64 = 3) 371 * @param encodedBlockSize the size of an encoded block (e.g. Base64 = 4) 372 * @param lineLength if > 0, use chunking with a length {@code lineLength} 373 * @param chunkSeparatorLength the chunk separator length, if relevant 374 * @param pad byte used as padding byte. 375 * @param decodingPolicy Decoding policy. 376 * @since 1.15 377 */ 378 protected BaseNCodec(final int unencodedBlockSize, final int encodedBlockSize, 379 final int lineLength, final int chunkSeparatorLength, final byte pad, final CodecPolicy decodingPolicy) { 380 this.unencodedBlockSize = unencodedBlockSize; 381 this.encodedBlockSize = encodedBlockSize; 382 final boolean useChunking = lineLength > 0 && chunkSeparatorLength > 0; 383 this.lineLength = useChunking ? (lineLength / encodedBlockSize) * encodedBlockSize : 0; 384 this.chunkSeparatorLength = chunkSeparatorLength; 385 this.pad = pad; 386 this.decodingPolicy = Objects.requireNonNull(decodingPolicy, "codecPolicy"); 387 } 388 389 /** 390 * Returns the amount of buffered data available for reading. 391 * 392 * @param context the context to be used 393 * @return The amount of buffered data available for reading. 394 */ 395 int available(final Context context) { // package protected for access from I/O streams 396 return context.buffer != null ? context.pos - context.readPos : 0; 397 } 398 399 /** 400 * Tests a given byte array to see if it contains any characters within the alphabet or PAD. 401 * 402 * Intended for use in checking line-ending arrays 403 * 404 * @param arrayOctet 405 * byte array to test 406 * @return {@code true} if any byte is a valid character in the alphabet or PAD; {@code false} otherwise 407 */ 408 protected boolean containsAlphabetOrPad(final byte[] arrayOctet) { 409 if (arrayOctet == null) { 410 return false; 411 } 412 for (final byte element : arrayOctet) { 413 if (pad == element || isInAlphabet(element)) { 414 return true; 415 } 416 } 417 return false; 418 } 419 420 /** 421 * Decodes a byte[] containing characters in the Base-N alphabet. 422 * 423 * @param pArray 424 * A byte array containing Base-N character data 425 * @return a byte array containing binary data 426 */ 427 @Override 428 public byte[] decode(final byte[] pArray) { 429 if (pArray == null || pArray.length == 0) { 430 return pArray; 431 } 432 final Context context = new Context(); 433 decode(pArray, 0, pArray.length, context); 434 decode(pArray, 0, EOF, context); // Notify decoder of EOF. 435 final byte[] result = new byte[context.pos]; 436 readResults(result, 0, result.length, context); 437 return result; 438 } 439 440 // package protected for access from I/O streams 441 abstract void decode(byte[] pArray, int i, int length, Context context); 442 443 /** 444 * Decodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of 445 * the Decoder interface, and will throw a DecoderException if the supplied object is not of type byte[] or String. 446 * 447 * @param obj 448 * Object to decode 449 * @return An object (of type byte[]) containing the binary data which corresponds to the byte[] or String 450 * supplied. 451 * @throws DecoderException 452 * if the parameter supplied is not of type byte[] 453 */ 454 @Override 455 public Object decode(final Object obj) throws DecoderException { 456 if (obj instanceof byte[]) { 457 return decode((byte[]) obj); 458 } else if (obj instanceof String) { 459 return decode((String) obj); 460 } else { 461 throw new DecoderException("Parameter supplied to Base-N decode is not a byte[] or a String"); 462 } 463 } 464 465 /** 466 * Decodes a String containing characters in the Base-N alphabet. 467 * 468 * @param pArray 469 * A String containing Base-N character data 470 * @return a byte array containing binary data 471 */ 472 public byte[] decode(final String pArray) { 473 return decode(StringUtils.getBytesUtf8(pArray)); 474 } 475 476 /** 477 * Encodes a byte[] containing binary data, into a byte[] containing characters in the alphabet. 478 * 479 * @param pArray 480 * a byte array containing binary data 481 * @return A byte array containing only the base N alphabetic character data 482 */ 483 @Override 484 public byte[] encode(final byte[] pArray) { 485 if (pArray == null || pArray.length == 0) { 486 return pArray; 487 } 488 return encode(pArray, 0, pArray.length); 489 } 490 491 /** 492 * Encodes a byte[] containing binary data, into a byte[] containing 493 * characters in the alphabet. 494 * 495 * @param pArray 496 * a byte array containing binary data 497 * @param offset 498 * initial offset of the subarray. 499 * @param length 500 * length of the subarray. 501 * @return A byte array containing only the base N alphabetic character data 502 * @since 1.11 503 */ 504 public byte[] encode(final byte[] pArray, final int offset, final int length) { 505 if (pArray == null || pArray.length == 0) { 506 return pArray; 507 } 508 final Context context = new Context(); 509 encode(pArray, offset, length, context); 510 encode(pArray, offset, EOF, context); // Notify encoder of EOF. 511 final byte[] buf = new byte[context.pos - context.readPos]; 512 readResults(buf, 0, buf.length, context); 513 return buf; 514 } 515 516 // package protected for access from I/O streams 517 abstract void encode(byte[] pArray, int i, int length, Context context); 518 519 /** 520 * Encodes an Object using the Base-N algorithm. This method is provided in order to satisfy the requirements of 521 * the Encoder interface, and will throw an EncoderException if the supplied object is not of type byte[]. 522 * 523 * @param obj 524 * Object to encode 525 * @return An object (of type byte[]) containing the Base-N encoded data which corresponds to the byte[] supplied. 526 * @throws EncoderException 527 * if the parameter supplied is not of type byte[] 528 */ 529 @Override 530 public Object encode(final Object obj) throws EncoderException { 531 if (!(obj instanceof byte[])) { 532 throw new EncoderException("Parameter supplied to Base-N encode is not a byte[]"); 533 } 534 return encode((byte[]) obj); 535 } 536 537 /** 538 * Encodes a byte[] containing binary data, into a String containing characters in the appropriate alphabet. 539 * Uses UTF8 encoding. 540 * 541 * @param pArray a byte array containing binary data 542 * @return String containing only character data in the appropriate alphabet. 543 * @since 1.5 544 * This is a duplicate of {@link #encodeToString(byte[])}; it was merged during refactoring. 545 */ 546 public String encodeAsString(final byte[] pArray){ 547 return StringUtils.newStringUtf8(encode(pArray)); 548 } 549 550 /** 551 * Encodes a byte[] containing binary data, into a String containing characters in the Base-N alphabet. 552 * Uses UTF8 encoding. 553 * 554 * @param pArray 555 * a byte array containing binary data 556 * @return A String containing only Base-N character data 557 */ 558 public String encodeToString(final byte[] pArray) { 559 return StringUtils.newStringUtf8(encode(pArray)); 560 } 561 562 /** 563 * Ensure that the buffer has room for {@code size} bytes 564 * 565 * @param size minimum spare space required 566 * @param context the context to be used 567 * @return the buffer 568 */ 569 protected byte[] ensureBufferSize(final int size, final Context context){ 570 if (context.buffer == null) { 571 context.buffer = new byte[Math.max(size, getDefaultBufferSize())]; 572 context.pos = 0; 573 context.readPos = 0; 574 575 // Overflow-conscious: 576 // x + y > z == x + y - z > 0 577 } else if (context.pos + size - context.buffer.length > 0) { 578 return resizeBuffer(context, context.pos + size); 579 } 580 return context.buffer; 581 } 582 583 /** 584 * Returns the decoding behavior policy. 585 * 586 * <p> 587 * The default is lenient. If the decoding policy is strict, then decoding will raise an 588 * {@link IllegalArgumentException} if trailing bits are not part of a valid encoding. Decoding will compose 589 * trailing bits into 8-bit bytes and discard the remainder. 590 * </p> 591 * 592 * @return true if using strict decoding 593 * @since 1.15 594 */ 595 public CodecPolicy getCodecPolicy() { 596 return decodingPolicy; 597 } 598 599 /** 600 * Get the default buffer size. Can be overridden. 601 * 602 * @return the default buffer size. 603 */ 604 protected int getDefaultBufferSize() { 605 return DEFAULT_BUFFER_SIZE; 606 } 607 608 /** 609 * Calculates the amount of space needed to encode the supplied array. 610 * 611 * @param pArray byte[] array which will later be encoded 612 * 613 * @return amount of space needed to encoded the supplied array. 614 * Returns a long since a max-len array will require > Integer.MAX_VALUE 615 */ 616 public long getEncodedLength(final byte[] pArray) { 617 // Calculate non-chunked size - rounded up to allow for padding 618 // cast to long is needed to avoid possibility of overflow 619 long len = ((pArray.length + unencodedBlockSize-1) / unencodedBlockSize) * (long) encodedBlockSize; 620 if (lineLength > 0) { // We're using chunking 621 // Round up to nearest multiple 622 len += ((len + lineLength-1) / lineLength) * chunkSeparatorLength; 623 } 624 return len; 625 } 626 627 /** 628 * Returns true if this object has buffered data for reading. 629 * 630 * @param context the context to be used 631 * @return true if there is data still available for reading. 632 */ 633 boolean hasData(final Context context) { // package protected for access from I/O streams 634 return context.buffer != null; 635 } 636 637 /** 638 * Returns whether or not the {@code octet} is in the current alphabet. 639 * Does not allow whitespace or pad. 640 * 641 * @param value The value to test 642 * 643 * @return {@code true} if the value is defined in the current alphabet, {@code false} otherwise. 644 */ 645 protected abstract boolean isInAlphabet(byte value); 646 647 /** 648 * Tests a given byte array to see if it contains only valid characters within the alphabet. 649 * The method optionally treats whitespace and pad as valid. 650 * 651 * @param arrayOctet byte array to test 652 * @param allowWSPad if {@code true}, then whitespace and PAD are also allowed 653 * 654 * @return {@code true} if all bytes are valid characters in the alphabet or if the byte array is empty; 655 * {@code false}, otherwise 656 */ 657 public boolean isInAlphabet(final byte[] arrayOctet, final boolean allowWSPad) { 658 for (final byte octet : arrayOctet) { 659 if (!isInAlphabet(octet) && 660 (!allowWSPad || (octet != pad) && !isWhiteSpace(octet))) { 661 return false; 662 } 663 } 664 return true; 665 } 666 667 /** 668 * Tests a given String to see if it contains only valid characters within the alphabet. 669 * The method treats whitespace and PAD as valid. 670 * 671 * @param basen String to test 672 * @return {@code true} if all characters in the String are valid characters in the alphabet or if 673 * the String is empty; {@code false}, otherwise 674 * @see #isInAlphabet(byte[], boolean) 675 */ 676 public boolean isInAlphabet(final String basen) { 677 return isInAlphabet(StringUtils.getBytesUtf8(basen), true); 678 } 679 680 /** 681 * Returns true if decoding behavior is strict. Decoding will raise an {@link IllegalArgumentException} if trailing 682 * bits are not part of a valid encoding. 683 * 684 * <p> 685 * The default is false for lenient decoding. Decoding will compose trailing bits into 8-bit bytes and discard the 686 * remainder. 687 * </p> 688 * 689 * @return true if using strict decoding 690 * @since 1.15 691 */ 692 public boolean isStrictDecoding() { 693 return decodingPolicy == CodecPolicy.STRICT; 694 } 695 696 /** 697 * Extracts buffered data into the provided byte[] array, starting at position bPos, up to a maximum of bAvail 698 * bytes. Returns how many bytes were actually extracted. 699 * <p> 700 * Package protected for access from I/O streams. 701 * 702 * @param b 703 * byte[] array to extract the buffered data into. 704 * @param bPos 705 * position in byte[] array to start extraction at. 706 * @param bAvail 707 * amount of bytes we're allowed to extract. We may extract fewer (if fewer are available). 708 * @param context 709 * the context to be used 710 * @return The number of bytes successfully extracted into the provided byte[] array. 711 */ 712 int readResults(final byte[] b, final int bPos, final int bAvail, final Context context) { 713 if (context.buffer != null) { 714 final int len = Math.min(available(context), bAvail); 715 System.arraycopy(context.buffer, context.readPos, b, bPos, len); 716 context.readPos += len; 717 if (context.readPos >= context.pos) { 718 context.buffer = null; // so hasData() will return false, and this method can return -1 719 } 720 return len; 721 } 722 return context.eof ? EOF : 0; 723 } 724}