Rev 3408 |
Blame |
Compare with Previous |
Last modification |
View Log
| RSS feed
package uk.me.parabola.imgfmt.app.labelenc;
import java.io.ByteArrayOutputStream;
import java.nio.charset.Charset;
/**
* Convert the 6-bit label format back to a java string.
*/
public class Format6Decoder
implements CharacterDecoder
{
private final ByteArrayOutputStream out =
new ByteArrayOutputStream();
private boolean needReset
;
private boolean symbol
;
private boolean lowerCaseOrSeparator
;
private int store
;
private int nbits
;
private final Charset charset =
Charset.
forName("ascii");
public boolean addByte
(int in
) {
int b = 0xff
& in
; //wipe out high bits (in case of negative byte)
if (needReset
) {
needReset =
false;
out.
reset();
}
store
<<=
8;
store |= b
;
nbits +=
8;
while (nbits
>=
6) {
convertChar
((store
>> (nbits-
6)) & 0x3f
);
if (needReset
) {
// Skip until the next byte boundary. Note that may mean that
// we skip more or *less* than 6 bits.
if (nbits
> 8)
nbits =
8;
else
nbits =
0;
break;
} else
nbits -=
6;
}
return needReset
;
}
public DecodedText getText
() {
byte[] ba = out.
toByteArray();
DecodedText text =
new DecodedText
(ba, charset
);
assert nbits ==
0 || nbits ==
8;
// If there is a byte left inside the decoder then we have to let our
// caller know, so that they can adjust the offset of the next label
// appropriately.
if (nbits ==
8)
text.
setOffsetAdjustment(-
1);
return text
;
}
public void reset
() {
needReset =
false;
out.
reset();
store =
0;
nbits =
0;
}
/**
* Convert a single 6 bit quantity into a character.
* @param b The six bit int.
*/
private void convertChar
(int b
) {
if (b
> 0x2f
) {
needReset =
true;
return;
}
char c
;
if (symbol
) {
symbol =
false;
c = Format6Encoder.
SYMBOLS.
charAt(b
);
}
else if(lowerCaseOrSeparator
) {
lowerCaseOrSeparator =
false;
if(b == 0x2b || b == 0x2c
) {
c =
(char)(b - 0x10
); // "thin" separator
}
else if(Character.
isLetter(b
)) {
// lower case letter
c =
Character.
toLowerCase(Format6Encoder.
LETTERS.
charAt(b
));
}
else {
// not a letter so just use as is (could be a digit)
c = Format6Encoder.
LETTERS.
charAt(b
);
}
}
else {
switch(b
) {
case 0x1B:
// next char is lower case or a separator
lowerCaseOrSeparator =
true;
return;
case 0x1C:
// next char is symbol
symbol =
true;
return;
case 0x1D:
case 0x1E:
case 0x1F:
// these are separators - use as is
c =
(char)b
;
break;
default:
c = Format6Encoder.
LETTERS.
charAt(b
);
break;
}
}
out.
write(c
);
}
}