001    package com.thaiopensource.datatype.xsd;
002    
003    import org.relaxng.datatype.ValidationContext;
004    
005    class HexBinaryDatatype extends BinaryDatatype {
006      static private final int INVALID = -1;
007      static private final int WHITESPACE = -2;
008    
009      boolean lexicallyAllows(String str) {
010        int len = str.length();
011        int i = 0;
012        while (i < len && weight(str.charAt(i)) == WHITESPACE)
013          i++;
014        while (i + 1 < len && weight(str.charAt(i)) >= 0 && weight(str.charAt(i + 1)) >= 0)
015          i += 2;
016        while (i < len && weight(str.charAt(i)) == WHITESPACE)
017          i++;
018        return i == len;
019      }
020    
021      Object getValue(String str, ValidationContext vc) {
022        int len = str.length();
023        int start = 0;
024        while (start < len && weight(str.charAt(start)) == WHITESPACE)
025          start++;
026        int end = len;
027        while (end > start && weight(str.charAt(end - 1)) == WHITESPACE)
028          end--;
029        byte[] value = new byte[(end - start) >> 1];
030        int j = 0;
031        for (int i = start; i < end; i += 2, j++)
032          value[j] = (byte)((weight(str.charAt(i)) << 4) | weight(str.charAt(i + 1)));
033        return value;
034      }
035    
036      static private int weight(char c) {
037        switch (c) {
038        case '0': case '1': case '2': case '3': case '4':
039        case '5': case '6': case '7': case '8': case '9':
040          return c - '0';
041        case 'A': case 'B': case 'C':
042        case 'D': case 'E': case 'F':
043          return c + (10 - 'A');
044        case 'a': case 'b': case 'c':
045        case 'd': case 'e': case 'f':
046          return c + (10 - 'a');
047        case ' ': case '\n': case '\r': case '\t':
048          return WHITESPACE;
049        }
050        return INVALID;
051      }
052    
053    }