KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > thaiopensource > datatype > xsd > Base64BinaryDatatype


1 package com.thaiopensource.datatype.xsd;
2
3 import org.relaxng.datatype.ValidationContext;
4
5 class Base64BinaryDatatype extends BinaryDatatype {
6   static private final byte[] weightTable = makeWeightTable();
7   static private final byte INVALID = (byte)-1;
8   static private final byte WHITESPACE = (byte)-2;
9   static private final byte PADDING = (byte)-3;
10
11   // for efficiency, don't assume whitespace normalized
12
boolean lexicallyAllows(String JavaDoc str) {
13     return byteCount(str) >= 0;
14   }
15
16   private static int byteCount(String JavaDoc str) {
17     int nChars = 0;
18     int nPadding = 0;
19     int lastCharWeight = -1;
20     for (int i = 0, len = str.length(); i < len; i++) {
21       char c = str.charAt(i);
22       if (c >= 128)
23         return -1;
24       int w = weightTable[c];
25       switch (w) {
26       case WHITESPACE:
27         break;
28       case PADDING:
29         if (++nPadding > 2)
30           return -1;
31         break;
32       case INVALID:
33         return -1;
34       default:
35         if (nPadding > 0)
36           return -1;
37         lastCharWeight = w;
38         nChars++;
39         break;
40       }
41     }
42     if (((nChars + nPadding) & 0x3) != 0)
43       return -1;
44     switch (nPadding) {
45     case 1:
46       // 1 padding char; last quartet specifies 2 bytes = 16 bits = 6 + 6 + 4 bits
47
// lastChar must have 6 - 4 = 2 unused bits
48
if ((lastCharWeight & 0x3) != 0)
49         return -1;
50       break;
51     case 2:
52       // 2 padding chars; last quartet specifies 1 byte = 8 bits = 6 + 2 bits
53
// lastChar must have 6 - 2 = 4 unused bits
54
if ((lastCharWeight & 0xF) != 0)
55         return -1;
56       break;
57     }
58     return ((nChars + nPadding) >> 2)*3 - nPadding;
59   }
60
61   Object JavaDoc getValue(String JavaDoc str, ValidationContext vc) {
62     int nBytes = byteCount(str);
63     byte[] value = new byte[nBytes];
64     int valueIndex = 0;
65     int nBytesAccum = 0;
66     int accum = 0;
67     for (int i = 0, len = str.length(); i < len; i++) {
68       int w = weightTable[str.charAt(i)];
69       if (w != WHITESPACE) {
70         accum <<= 6;
71         if (w != PADDING)
72           accum |= w;
73         if (++nBytesAccum == 4) {
74           for (int shift = 16; shift >= 0; shift -= 8) {
75             if (valueIndex < nBytes)
76               value[valueIndex++] = (byte)((accum >> shift) & 0xFF);
77           }
78           nBytesAccum = 0;
79           accum = 0;
80         }
81       }
82     }
83     return value;
84   }
85
86   static private byte[] makeWeightTable() {
87     byte[] w = new byte[128];
88     byte n = INVALID;
89     for (int i = 0; i < 128; i++)
90       w[i] = n;
91     n = 0;
92     for (int i = 'A'; i <= 'Z'; i++, n++)
93       w[i] = n;
94     for (int i = 'a'; i <= 'z'; i++, n++)
95       w[i] = n;
96     for (int i = '0'; i <= '9'; i++, n++)
97       w[i] = n;
98     w['+'] = n++;
99     w['/'] = n++;
100     w[' '] = w['\t'] = w['\r'] = w['\n'] = WHITESPACE;
101     w['='] = PADDING;
102     return w;
103   }
104
105 }
106
Popular Tags