1 /*
2 * Copyright 2004 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17 package org.apache.asn1.codec.stateful.examples;
18
19 import java.nio.ByteBuffer;
20
21 import org.apache.asn1.codec.DecoderException;
22 import org.apache.asn1.codec.stateful.AbstractStatefulDecoder;
23
24 /***
25 * Document me.
26 *
27 * @author <a href="mailto:dev@directory.apache.org"> Apache Directory
28 * Project</a> $Rev: 161723 $
29 */
30 public class HexDecoder extends AbstractStatefulDecoder
31 {
32 private ByteBuffer decoded = ByteBuffer.allocate( 128 ) ;
33 private byte lsn ;
34 private byte msn ;
35 private boolean expectingMsn = true ;
36
37
38 public void decode( Object chunk ) throws DecoderException
39 {
40 ByteBuffer encoded = ( ByteBuffer ) chunk;
41
42 if ( encoded == null || !encoded.hasRemaining() )
43 {
44 return;
45 }
46
47 while ( encoded.hasRemaining() )
48 {
49 if ( ! decoded.hasRemaining() )
50 {
51 decoded.flip();
52 super.decodeOccurred( decoded );
53 decoded.clear();
54 }
55
56 if ( expectingMsn )
57 {
58 msn = encoded.get();
59 expectingMsn = false;
60 }
61 else
62 {
63 lsn = encoded.get();
64 expectingMsn = true;
65 }
66
67 /* if we've hit the most significant nibble then we have two hex
68 * characters as bytes so we need to compute and add the byte to
69 * the buffer
70 */
71 if ( expectingMsn )
72 {
73 byte bite = getNibble( lsn );
74 bite |= ( getNibble( msn ) << 4 );
75 decoded.put( bite );
76 }
77 }
78
79 /* only trigger a decode callback if we have seen an even number of
80 * hex character bytes in which case we're in the expectingMsn state
81 * this will flush out what's siting in the buffer automatically
82 */
83 if ( expectingMsn )
84 {
85 decoded.flip();
86 super.decodeOccurred( decoded );
87 decoded.clear();
88 }
89 }
90
91
92
93 private byte getNibble( byte ch ) throws DecoderException
94 {
95 // lowercase the character if it is in upper case
96 if ( ch > 64 && ch < 91 )
97 {
98 ch -= 32;
99 }
100
101 switch(ch)
102 {
103 case 48:
104 return 0 ;
105 case 49:
106 return 1 ;
107 case 50:
108 return 2 ;
109 case 51:
110 return 3 ;
111 case 52:
112 return 4 ;
113 case 53:
114 return 5 ;
115 case 54:
116 return 6 ;
117 case 55:
118 return 7 ;
119 case 56:
120 return 8 ;
121 case 57:
122 return 9 ;
123 case 97:
124 return 10 ;
125 case 98:
126 return 11 ;
127 case 99:
128 return 12 ;
129 case 100:
130 return 13 ;
131 case 101:
132 return 14 ;
133 case 102:
134 return 15 ;
135 default:
136 throw new DecoderException( "non-hex character '" + (char) ch
137 + "' encountered" );
138 }
139 }
140 }