Base64Binary.java 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package gnu.kawa.xml;
  2. /** A BinaryObject whose lexical format is base64. */
  3. public class Base64Binary extends BinaryObject
  4. {
  5. public Base64Binary (byte[] data)
  6. {
  7. this.data = data;
  8. }
  9. public static final String ENCODING
  10. = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
  11. public static Base64Binary valueOf (String str)
  12. {
  13. return new Base64Binary(str);
  14. }
  15. public Base64Binary (String str)
  16. {
  17. int len = str.length();
  18. int blen = 0;
  19. for (int i = 0; i < len; i++)
  20. {
  21. char ch = str.charAt(i);
  22. if (! Character.isWhitespace(ch) && ch != '=')
  23. blen++;
  24. }
  25. blen = (3 * blen) / 4;
  26. byte[] bytes = new byte[blen];
  27. int value = 0;
  28. int buffered = 0;
  29. int padding = 0;
  30. blen = 0;
  31. for (int i = 0; i < len; i++)
  32. {
  33. char ch = str.charAt(i);
  34. int v;
  35. if (ch >= 'A' && ch <= 'Z')
  36. v = ch - 'A';
  37. else if (ch >= 'a' && ch <= 'z')
  38. v = ch - 'a' + 26;
  39. else if (ch >= '0' && ch <= '9')
  40. v = ch - '0' + 52;
  41. else if (ch == '+')
  42. v = 62;
  43. else if (ch == '/')
  44. v = 63;
  45. else if (Character.isWhitespace(ch))
  46. continue;
  47. else if (ch == '=')
  48. {
  49. padding++;
  50. continue;
  51. }
  52. else
  53. v = -1;
  54. if (v < 0 || padding > 0)
  55. throw new IllegalArgumentException("illegal character in base64Binary string at position "+i);
  56. value = (value << 6) + v;
  57. buffered++;
  58. if (buffered == 4)
  59. {
  60. bytes[blen++] = (byte) (value >> 16);
  61. bytes[blen++] = (byte) (value >> 8);
  62. bytes[blen++] = (byte) (value);
  63. buffered = 0;
  64. }
  65. /*
  66. if (buffered == 4 || ++i == len)
  67. {
  68. System.err.println("end bl:"+blen+" b:"+buffered+" val:"+Integer.toHexString(value)+" i:"+i);
  69. while (--buffered >= 0)
  70. {
  71. System.err.println("bl:"+blen+" buf:"+buffered);
  72. bytes[blen++] = (byte) (value >> (8 * buffered));
  73. }
  74. bytes[blen++] = (byte) (value >> 16);
  75. bytes[blen++] = (byte) (value >> 8);
  76. bytes[blen++] = (byte) (value);
  77. buffered = 0;
  78. }
  79. */
  80. }
  81. if (buffered+padding > 0
  82. ? (buffered + padding != 4
  83. || (value & ((1 << padding) - 1)) != 0
  84. || blen + 3 - padding != bytes.length)
  85. : blen != bytes.length)
  86. throw new IllegalArgumentException();
  87. switch (padding)
  88. {
  89. case 1:
  90. bytes[blen++] = (byte) (value << 10);
  91. bytes[blen++] = (byte) (value >> 2);
  92. break;
  93. case 2:
  94. bytes[blen++] = (byte) (value >> 4);
  95. break;
  96. }
  97. //System.err.println("end bl:"+blen+" b:"+buffered+" val:"+Integer.toHexString(value)+" pad:"+padding);
  98. this.data = bytes;
  99. }
  100. public StringBuffer toString (StringBuffer sbuf)
  101. {
  102. byte[] bb = data;
  103. int len = bb.length;
  104. int value = 0;
  105. for (int i = 0; i < len; )
  106. {
  107. byte b = bb[i];
  108. value = (value << 8) | (b & 0xFF);
  109. i++;
  110. if ((i % 3) == 0)
  111. {
  112. sbuf.append(ENCODING.charAt((value >> 18) & 63));
  113. sbuf.append(ENCODING.charAt((value >> 12) & 63));
  114. sbuf.append(ENCODING.charAt((value >> 6) & 63));
  115. sbuf.append(ENCODING.charAt(value & 63));
  116. }
  117. }
  118. switch (len % 3)
  119. {
  120. case 1:
  121. sbuf.append(ENCODING.charAt((value >> 2) & 63));
  122. sbuf.append(ENCODING.charAt((value << 4) & 63));
  123. sbuf.append("==");
  124. break;
  125. case 2:
  126. sbuf.append(ENCODING.charAt((value >> 10) & 63));
  127. sbuf.append(ENCODING.charAt((value >> 4) & 63));
  128. sbuf.append(ENCODING.charAt((value << 2) & 63));
  129. sbuf.append('=');
  130. break;
  131. }
  132. return sbuf;
  133. }
  134. public String toString ()
  135. {
  136. return toString(new StringBuffer()).toString();
  137. }
  138. }