Skip to content

Package: Encoder

Encoder

nameinstructionbranchcomplexitylinemethod
Encoder()
M: 0 C: 57
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 17
100%
M: 0 C: 1
100%
Encoder(boolean)
M: 0 C: 60
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 18
100%
M: 0 C: 1
100%
_flush()
M: 0 C: 15
100%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 4
100%
M: 0 C: 1
100%
canAddAttributeToTable(int)
M: 0 C: 13
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
canAddCharacterContentToTable(int, CharArrayIntMap)
M: 0 C: 11
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
encodeAIIBuiltInAlgorithmData(int, Object, int, int)
M: 0 C: 44
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 10
100%
M: 0 C: 1
100%
encodeAIIObjectAlgorithmData(int, Object, EncodingAlgorithm)
M: 0 C: 35
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
encodeAIIOctetAlgorithmData(int, byte[], int, int)
M: 0 C: 25
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
encodeAlphabetCharacters(String, char[], int, int, boolean)
M: 24 C: 72
75%
M: 4 C: 6
60%
M: 4 C: 2
33%
M: 5 C: 19
79%
M: 0 C: 1
100%
encodeAttributeQualifiedNameOnSecondBit(String, String, String)
M: 61 C: 0
0%
M: 12 C: 0
0%
M: 7 C: 0
0%
M: 10 C: 0
0%
M: 1 C: 0
0%
encodeCIIBuiltInAlgorithmData(int, Object, int, int)
M: 0 C: 44
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 10
100%
M: 0 C: 1
100%
encodeCIIBuiltInAlgorithmDataAsCDATA(char[], int, int)
M: 0 C: 21
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
encodeCIIObjectAlgorithmData(int, Object, EncodingAlgorithm)
M: 0 C: 35
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
encodeCIIOctetAlgorithmData(int, byte[], int, int)
M: 0 C: 25
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
encodeCharacterAsUtf8FourByte(int, char[], int, int, int)
M: 91 C: 0
0%
M: 8 C: 0
0%
M: 5 C: 0
0%
M: 13 C: 0
0%
M: 1 C: 0
0%
encodeCharacters(char[], int, int)
M: 0 C: 15
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
encodeCharactersNoClone(char[], int, int)
M: 15 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
encodeComment(char[], int, int)
M: 0 C: 18
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
encodeCommentNoClone(char[], int, int)
M: 18 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
encodeDateTimeFourBitCharacters(char[], int, int, boolean)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
encodeDateTimeNonIdentifyingStringOnFirstBit(String, boolean, boolean)
M: 8 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
encodeDocumentTermination()
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
encodeDocumentTypeDeclaration(String, String)
M: 52 C: 0
0%
M: 16 C: 0
0%
M: 9 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
encodeElementQualifiedNameOnThirdBit(String, String, String)
M: 7 C: 53
88%
M: 4 C: 8
67%
M: 3 C: 4
57%
M: 1 C: 9
90%
M: 0 C: 1
100%
encodeElementTermination()
M: 0 C: 17
100%
M: 0 C: 3
100%
M: 0 C: 3
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
encodeFourBitCharacters(int, int[], char[], int, int, boolean)
M: 20 C: 47
70%
M: 4 C: 4
50%
M: 4 C: 1
20%
M: 5 C: 14
74%
M: 0 C: 1
100%
encodeHeader(boolean)
M: 6 C: 7
54%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 3
75%
M: 0 C: 1
100%
encodeIdentifyingNonEmptyStringOnFirstBit(String, StringIntMap)
M: 0 C: 15
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
encodeInitialVocabulary()
M: 36 C: 64
64%
M: 8 C: 10
56%
M: 6 C: 4
40%
M: 10 C: 17
63%
M: 0 C: 1
100%
encodeLiteralAttributeQualifiedNameOnSecondBit(String, String, String, LocalNameQualifiedNamesMap.Entry)
M: 41 C: 99
71%
M: 10 C: 14
58%
M: 8 C: 5
38%
M: 7 C: 26
79%
M: 0 C: 1
100%
encodeLiteralElementQualifiedNameOnThirdBit(String, String, String, LocalNameQualifiedNamesMap.Entry)
M: 26 C: 95
79%
M: 2 C: 16
89%
M: 2 C: 8
80%
M: 2 C: 25
93%
M: 0 C: 1
100%
encodeNamespaceAttribute(String, String)
M: 0 C: 44
100%
M: 2 C: 6
75%
M: 2 C: 3
60%
M: 0 C: 11
100%
M: 0 C: 1
100%
encodeNonEmptyCharacterStringOnFifthBit(String)
M: 3 C: 17
85%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 4
100%
M: 0 C: 1
100%
encodeNonEmptyCharacterStringOnFifthBit(char[], int, int)
M: 5 C: 19
79%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 4
100%
M: 0 C: 1
100%
encodeNonEmptyCharacterStringOnSeventhBit(char[], int, int)
M: 5 C: 19
79%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 4
100%
M: 0 C: 1
100%
encodeNonEmptyFourBitCharacterString(int[], char[], int, int, int)
M: 14 C: 72
84%
M: 2 C: 6
75%
M: 2 C: 3
60%
M: 2 C: 11
85%
M: 0 C: 1
100%
encodeNonEmptyFourBitCharacterStringOnSeventhBit(int[], char[], int, int)
M: 0 C: 21
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
encodeNonEmptyNBitCharacterStringOnSeventhBit(String, char[], int, int)
M: 7 C: 94
93%
M: 2 C: 12
86%
M: 2 C: 6
75%
M: 1 C: 22
96%
M: 0 C: 1
100%
encodeNonEmptyOctetStringOnSecondBit(String)
M: 0 C: 13
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
encodeNonEmptyUTF8StringAsOctetString(int, String, int[])
M: 12 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 3 C: 0
0%
M: 1 C: 0
0%
encodeNonEmptyUTF8StringAsOctetString(int, char[], int, int, int[])
M: 17 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
encodeNonIdentifyingStringOnFirstBit(String, CharArrayIntMap, boolean)
M: 27 C: 47
64%
M: 6 C: 6
50%
M: 6 C: 1
14%
M: 6 C: 15
71%
M: 0 C: 1
100%
encodeNonIdentifyingStringOnFirstBit(String, StringIntMap, boolean, boolean)
M: 4 C: 65
94%
M: 4 C: 14
78%
M: 4 C: 6
60%
M: 1 C: 18
95%
M: 0 C: 1
100%
encodeNonIdentifyingStringOnFirstBit(String, int, Object)
M: 72 C: 91
56%
M: 9 C: 14
61%
M: 7 C: 9
56%
M: 10 C: 31
76%
M: 0 C: 1
100%
encodeNonIdentifyingStringOnFirstBit(char[], int, int, CharArrayIntMap, boolean, boolean)
M: 31 C: 38
55%
M: 5 C: 5
50%
M: 5 C: 1
17%
M: 6 C: 13
68%
M: 0 C: 1
100%
encodeNonIdentifyingStringOnFirstBit(int, int[], String, boolean, boolean)
M: 100 C: 0
0%
M: 18 C: 0
0%
M: 10 C: 0
0%
M: 25 C: 0
0%
M: 1 C: 0
0%
encodeNonIdentifyingStringOnThirdBit(String, int, Object)
M: 135 C: 28
17%
M: 20 C: 3
13%
M: 15 C: 1
6%
M: 32 C: 9
22%
M: 0 C: 1
100%
encodeNonIdentifyingStringOnThirdBit(String, int, byte[], int, int)
M: 13 C: 19
59%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 1 C: 6
86%
M: 0 C: 1
100%
encodeNonIdentifyingStringOnThirdBit(char[], int, int, CharArrayIntMap, boolean, boolean)
M: 0 C: 66
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 18
100%
M: 0 C: 1
100%
encodeNonZeroInteger(int, int, int[])
M: 123 C: 0
0%
M: 8 C: 0
0%
M: 5 C: 0
0%
M: 19 C: 0
0%
M: 1 C: 0
0%
encodeNonZeroIntegerOnFourthBit(int)
M: 31 C: 66
68%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 6 C: 14
70%
M: 0 C: 1
100%
encodeNonZeroIntegerOnSecondBitFirstBitOne(int)
M: 63 C: 10
14%
M: 5 C: 1
17%
M: 3 C: 1
25%
M: 14 C: 3
18%
M: 0 C: 1
100%
encodeNonZeroIntegerOnSecondBitFirstBitZero(int)
M: 45 C: 8
15%
M: 3 C: 1
25%
M: 2 C: 1
33%
M: 10 C: 3
23%
M: 0 C: 1
100%
encodeNonZeroIntegerOnThirdBit(int)
M: 86 C: 11
11%
M: 5 C: 1
17%
M: 3 C: 1
25%
M: 17 C: 3
15%
M: 0 C: 1
100%
encodeNonZeroOctetStringLength(int, int, int[])
M: 71 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 12 C: 0
0%
M: 1 C: 0
0%
encodeNonZeroOctetStringLengthOnFifthBit(int)
M: 0 C: 59
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 12
100%
M: 0 C: 1
100%
encodeNonZeroOctetStringLengthOnSecondBit(int)
M: 40 C: 10
20%
M: 3 C: 1
25%
M: 2 C: 1
33%
M: 9 C: 3
25%
M: 0 C: 1
100%
encodeNonZeroOctetStringLengthOnSenventhBit(int)
M: 0 C: 59
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 12
100%
M: 0 C: 1
100%
encodeNumericFourBitCharacters(char[], int, int, boolean)
M: 0 C: 9
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
encodeNumericNonIdentifyingStringOnFirstBit(String, boolean, boolean)
M: 8 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
encodeProcessingInstruction(String, String)
M: 0 C: 22
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
encodeTermination()
M: 0 C: 14
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
encodeUTF8String(String)
M: 9 C: 22
71%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 2 C: 4
67%
M: 0 C: 1
100%
encodeUTF8String(char[], int, int)
M: 81 C: 30
27%
M: 9 C: 3
25%
M: 5 C: 2
29%
M: 11 C: 8
42%
M: 0 C: 1
100%
encodeUtf16String(String)
M: 31 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
encodeUtf16String(char[], int, int)
M: 40 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 8 C: 0
0%
M: 1 C: 0
0%
ensureEncodingBufferSizeForUtf16String(int)
M: 14 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
ensureEncodingBufferSizeForUtf8String(int)
M: 4 C: 10
71%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 3
75%
M: 0 C: 1
100%
ensureSize(int)
M: 0 C: 21
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
getAttributeValueMapMemoryLimit()
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getCharacterContentChunkMapMemoryLimit()
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getCharacterEncodingScheme()
M: 7 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getDefaultEncodingScheme()
M: 2 C: 10
83%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 3
75%
M: 0 C: 1
100%
getIgnoreComments()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getIgnoreDTD()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getIgnoreProcesingInstructions()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getIgnoreWhiteSpaceTextContent()
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
getMaxAttributeValueSize()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getMaxCharacterContentChunkSize()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getMinAttributeValueSize()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getMinCharacterContentChunkSize()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getPrefixFromQualifiedName(String)
M: 0 C: 16
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
getRegisteredEncodingAlgorithms()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
getVocabularyApplicationData()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
hasMark()
M: 8 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
isAttributeValueLengthMatchesLimit(int)
M: 0 C: 12
100%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 1
100%
M: 0 C: 1
100%
isCharacterContentChunkLengthMatchesLimit(int)
M: 0 C: 12
100%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 1
100%
M: 0 C: 1
100%
isWhiteSpace(String)
M: 1 C: 28
97%
M: 2 C: 6
75%
M: 2 C: 3
60%
M: 0 C: 5
100%
M: 0 C: 1
100%
isWhiteSpace(char[], int, int)
M: 1 C: 27
96%
M: 2 C: 6
75%
M: 2 C: 3
60%
M: 0 C: 4
100%
M: 0 C: 1
100%
mark()
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
maxCharacter(String)
M: 0 C: 21
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
reset()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
resetBits()
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
resetMark()
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
resize(int)
M: 0 C: 15
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
setAttributeValueMapMemoryLimit(int)
M: 2 C: 8
80%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 3
75%
M: 0 C: 1
100%
setCharacterContentChunkMapMemoryLimit(int)
M: 2 C: 8
80%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 3
75%
M: 0 C: 1
100%
setCharacterEncodingScheme(String)
M: 10 C: 14
58%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 3 C: 5
63%
M: 0 C: 1
100%
setExternalVocabulary(ExternalVocabulary)
M: 0 C: 24
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
setIgnoreComments(boolean)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
setIgnoreDTD(boolean)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
setIgnoreProcesingInstructions(boolean)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
setIgnoreWhiteSpaceTextContent(boolean)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
setMaxAttributeValueSize(int)
M: 2 C: 6
75%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 3
75%
M: 0 C: 1
100%
setMaxCharacterContentChunkSize(int)
M: 2 C: 6
75%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 3
75%
M: 0 C: 1
100%
setMinAttributeValueSize(int)
M: 8 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
setMinCharacterContentChunkSize(int)
M: 8 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
setOutputStream(OutputStream)
M: 0 C: 10
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
setRegisteredEncodingAlgorithms(Map)
M: 5 C: 7
58%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 1 C: 3
75%
M: 0 C: 1
100%
setVocabulary(SerializerVocabulary)
M: 0 C: 7
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
setVocabularyApplicationData(VocabularyApplicationData)
M: 4 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
static {...}
M: 0 C: 67
100%
M: 0 C: 8
100%
M: 0 C: 5
100%
M: 0 C: 12
100%
M: 0 C: 1
100%
write(byte[], int)
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
write(byte[], int, int)
M: 27 C: 46
63%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 3 C: 8
73%
M: 0 C: 1
100%
write(int)
M: 21 C: 39
65%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 2 C: 7
78%
M: 0 C: 1
100%
writeBits(int, int)
M: 0 C: 42
100%
M: 0 C: 6
100%
M: 0 C: 4
100%
M: 0 C: 9
100%
M: 0 C: 1
100%

Coverage

1: /*
2: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3: *
4: * Copyright (c) 2004-2019 Oracle and/or its affiliates. All rights reserved.
5: *
6: * Oracle licenses this file to You under the Apache License, Version 2.0
7: * (the "License"); you may not use this file except in compliance with
8: * the License. You may obtain a copy of the License at
9: *
10: * http://www.apache.org/licenses/LICENSE-2.0
11: *
12: * Unless required by applicable law or agreed to in writing, software
13: * distributed under the License is distributed on an "AS IS" BASIS,
14: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15: * See the License for the specific language governing permissions and
16: * limitations under the License.
17: */
18:
19: package com.sun.xml.fastinfoset;
20:
21: import com.sun.xml.fastinfoset.algorithm.BuiltInEncodingAlgorithmFactory;
22: import com.sun.xml.fastinfoset.org.apache.xerces.util.XMLChar;
23: import com.sun.xml.fastinfoset.util.CharArrayIntMap;
24: import com.sun.xml.fastinfoset.util.KeyIntMap;
25: import com.sun.xml.fastinfoset.util.LocalNameQualifiedNamesMap;
26: import com.sun.xml.fastinfoset.util.StringIntMap;
27: import com.sun.xml.fastinfoset.vocab.SerializerVocabulary;
28: import java.io.IOException;
29: import java.io.OutputStream;
30: import java.util.HashMap;
31: import java.util.Map;
32: import org.jvnet.fastinfoset.EncodingAlgorithm;
33: import org.jvnet.fastinfoset.EncodingAlgorithmException;
34: import org.jvnet.fastinfoset.EncodingAlgorithmIndexes;
35: import org.jvnet.fastinfoset.ExternalVocabulary;
36: import org.jvnet.fastinfoset.FastInfosetException;
37: import org.jvnet.fastinfoset.FastInfosetSerializer;
38: import org.jvnet.fastinfoset.RestrictedAlphabet;
39: import org.jvnet.fastinfoset.VocabularyApplicationData;
40: import org.xml.sax.helpers.DefaultHandler;
41:
42: /**
43: * Abstract encoder for developing concrete encoders.
44: *
45: * Concrete implementations extending Encoder will utilize methods on Encoder
46: * to encode XML infoset according to the Fast Infoset standard. It is the
47: * responsibility of the concrete implementation to ensure that methods are
48: * invoked in the correct order to produce a valid fast infoset document.
49: *
50: * <p>
51: * This class extends org.sax.xml.DefaultHandler so that concrete SAX
52: * implementations can be used with javax.xml.parsers.SAXParser and the parse
53: * methods that take org.sax.xml.DefaultHandler as a parameter.
54: *
55: * <p>
56: * Buffering of octets that are written to an {@link java.io.OutputStream} is
57: * supported in a similar manner to a {@link java.io.BufferedOutputStream}.
58: * Combining buffering with encoding enables better performance.
59: *
60: * <p>
61: * More than one fast infoset document may be encoded to the
62: * {@link java.io.OutputStream}.
63: *
64: */
65: public abstract class Encoder extends DefaultHandler implements FastInfosetSerializer {
66:
67: /**
68: * Character encoding scheme system property for the encoding
69: * of content and attribute values.
70: */
71: public static final String CHARACTER_ENCODING_SCHEME_SYSTEM_PROPERTY =
72: "com.sun.xml.fastinfoset.serializer.character-encoding-scheme";
73:
74: /**
75: * Default character encoding scheme system property for the encoding
76: * of content and attribute values.
77: */
78: protected static final String _characterEncodingSchemeSystemDefault = getDefaultEncodingScheme();
79:
80: private static String getDefaultEncodingScheme() {
81: String p = System.getProperty(CHARACTER_ENCODING_SCHEME_SYSTEM_PROPERTY,
82: UTF_8);
83:• if (p.equals(UTF_16BE)) {
84: return UTF_16BE;
85: } else {
86: return UTF_8;
87: }
88: }
89:
90: private static int[] NUMERIC_CHARACTERS_TABLE;
91:
92: private static int[] DATE_TIME_CHARACTERS_TABLE;
93:
94: static {
95: NUMERIC_CHARACTERS_TABLE = new int[maxCharacter(RestrictedAlphabet.NUMERIC_CHARACTERS) + 1];
96: DATE_TIME_CHARACTERS_TABLE = new int[maxCharacter(RestrictedAlphabet.DATE_TIME_CHARACTERS) + 1];
97:
98:• for (int i = 0; i < NUMERIC_CHARACTERS_TABLE.length ; i++) {
99: NUMERIC_CHARACTERS_TABLE[i] = -1;
100: }
101:• for (int i = 0; i < DATE_TIME_CHARACTERS_TABLE.length ; i++) {
102: DATE_TIME_CHARACTERS_TABLE[i] = -1;
103: }
104:
105:• for (int i = 0; i < RestrictedAlphabet.NUMERIC_CHARACTERS.length() ; i++) {
106: NUMERIC_CHARACTERS_TABLE[RestrictedAlphabet.NUMERIC_CHARACTERS.charAt(i)] = i;
107: }
108:• for (int i = 0; i < RestrictedAlphabet.DATE_TIME_CHARACTERS.length() ; i++) {
109: DATE_TIME_CHARACTERS_TABLE[RestrictedAlphabet.DATE_TIME_CHARACTERS.charAt(i)] = i;
110: }
111: }
112:
113: private static int maxCharacter(String alphabet) {
114: int c = 0;
115:• for (int i = 0; i < alphabet.length() ; i++) {
116:• if (c < alphabet.charAt(i)) {
117: c = alphabet.charAt(i);
118: }
119: }
120:
121: return c;
122: }
123:
124: /**
125: * True if DTD and internal subset shall be ignored.
126: */
127: private boolean _ignoreDTD;
128:
129: /**
130: * True if comments shall be ignored.
131: */
132: private boolean _ignoreComments;
133:
134: /**
135: * True if procesing instructions shall be ignored.
136: */
137: private boolean _ignoreProcessingInstructions;
138:
139: /**
140: * True if white space characters for text content shall be ignored.
141: */
142: private boolean _ignoreWhiteSpaceTextContent;
143:
144: /**
145: * True, if the local name string is used as the key to find the
146: * associated set of qualified names.
147: * <p>
148: * False, if the <prefix>:<local name> string is used as the key
149: * to find the associated set of qualified names.
150: */
151: private boolean _useLocalNameAsKeyForQualifiedNameLookup;
152:
153: /**
154: * True if strings for text content and attribute values will be
155: * UTF-8 encoded otherwise they will be UTF-16 encoded.
156: */
157: private boolean _encodingStringsAsUtf8 = true;
158:
159: /**
160: * Encoding constant generated from the string encoding.
161: */
162: private int _nonIdentifyingStringOnThirdBitCES;
163:
164: /**
165: * Encoding constant generated from the string encoding.
166: */
167: private int _nonIdentifyingStringOnFirstBitCES;
168:
169: /**
170: * The map of URIs to algorithms.
171: */
172: private Map _registeredEncodingAlgorithms = new HashMap();
173:
174: /**
175: * The vocabulary that is used by the encoder
176: */
177: protected SerializerVocabulary _v;
178:
179: /**
180: * The vocabulary application data that is used by the encoder
181: */
182: protected VocabularyApplicationData _vData;
183:
184: /**
185: * True if the vocubulary is internal to the encoder
186: */
187: private boolean _vIsInternal;
188:
189: /**
190: * True if terminatation of an information item is required
191: */
192: protected boolean _terminate = false;
193:
194: /**
195: * The current octet that is to be written.
196: */
197: protected int _b;
198:
199: /**
200: * The {@link java.io.OutputStream} that the encoded XML infoset (the
201: * fast infoset document) is written to.
202: */
203: protected OutputStream _s;
204:
205: /**
206: * The internal buffer of characters used for the UTF-8 or UTF-16 encoding
207: * of characters.
208: */
209: protected char[] _charBuffer = new char[512];
210:
211: /**
212: * The internal buffer of bytes.
213: */
214: protected byte[] _octetBuffer = new byte[1024];
215:
216: /**
217: * The current position in the internal buffer.
218: */
219: protected int _octetBufferIndex;
220:
221: /**
222: * The current mark in the internal buffer.
223: *
224: * <p>
225: * If the value of the mark is {@literal <} 0 then the mark is not set.
226: */
227: protected int _markIndex = -1;
228:
229: /**
230: * The minimum size of [normalized value] of Attribute Information
231: * Items that will be indexed.
232: */
233: protected int minAttributeValueSize = FastInfosetSerializer.MIN_ATTRIBUTE_VALUE_SIZE;
234:
235: /**
236: * The maximum size of [normalized value] of Attribute Information
237: * Items that will be indexed.
238: */
239: protected int maxAttributeValueSize = FastInfosetSerializer.MAX_ATTRIBUTE_VALUE_SIZE;
240:
241: /**
242: * The limit on the size of indexed Map for attribute values
243: * Limit is measured in characters number
244: */
245: protected int attributeValueMapTotalCharactersConstraint = FastInfosetSerializer.ATTRIBUTE_VALUE_MAP_MEMORY_CONSTRAINT / 2;
246:
247: /**
248: * The minimum size of character content chunks
249: * of Character Information Items or Comment Information Items that
250: * will be indexed.
251: */
252: protected int minCharacterContentChunkSize = FastInfosetSerializer.MIN_CHARACTER_CONTENT_CHUNK_SIZE;
253:
254: /**
255: * The maximum size of character content chunks
256: * of Character Information Items or Comment Information Items that
257: * will be indexed.
258: */
259: protected int maxCharacterContentChunkSize = FastInfosetSerializer.MAX_CHARACTER_CONTENT_CHUNK_SIZE;
260:
261: /**
262: * The limit on the size of indexed Map for character content chunks
263: * Limit is measured in characters number
264: */
265: protected int characterContentChunkMapTotalCharactersConstraint = FastInfosetSerializer.CHARACTER_CONTENT_CHUNK_MAP_MEMORY_CONSTRAINT / 2;
266:
267: /**
268: * Default constructor for the Encoder.
269: */
270: protected Encoder() {
271: setCharacterEncodingScheme(_characterEncodingSchemeSystemDefault);
272: }
273:
274: protected Encoder(boolean useLocalNameAsKeyForQualifiedNameLookup) {
275: setCharacterEncodingScheme(_characterEncodingSchemeSystemDefault);
276: _useLocalNameAsKeyForQualifiedNameLookup = useLocalNameAsKeyForQualifiedNameLookup;
277: }
278:
279:
280: // FastInfosetSerializer interface
281:
282: /**
283: * {@inheritDoc}
284: */
285: public final void setIgnoreDTD(boolean ignoreDTD) {
286: _ignoreDTD = ignoreDTD;
287: }
288:
289: /**
290: * {@inheritDoc}
291: */
292: public final boolean getIgnoreDTD() {
293: return _ignoreDTD;
294: }
295:
296: /**
297: * {@inheritDoc}
298: */
299: public final void setIgnoreComments(boolean ignoreComments) {
300: _ignoreComments = ignoreComments;
301: }
302:
303: /**
304: * {@inheritDoc}
305: */
306: public final boolean getIgnoreComments() {
307: return _ignoreComments;
308: }
309:
310: /**
311: * {@inheritDoc}
312: */
313: public final void setIgnoreProcesingInstructions(boolean
314: ignoreProcesingInstructions) {
315: _ignoreProcessingInstructions = ignoreProcesingInstructions;
316: }
317:
318: /**
319: * {@inheritDoc}
320: */
321: public final boolean getIgnoreProcesingInstructions() {
322: return _ignoreProcessingInstructions;
323: }
324:
325: /**
326: * {@inheritDoc}
327: */
328: public final void setIgnoreWhiteSpaceTextContent(boolean ignoreWhiteSpaceTextContent) {
329: _ignoreWhiteSpaceTextContent = ignoreWhiteSpaceTextContent;
330: }
331:
332: /**
333: * {@inheritDoc}
334: */
335: public final boolean getIgnoreWhiteSpaceTextContent() {
336: return _ignoreWhiteSpaceTextContent;
337: }
338:
339: /**
340: * {@inheritDoc}
341: */
342: public void setCharacterEncodingScheme(String characterEncodingScheme) {
343:• if (characterEncodingScheme.equals(UTF_16BE)) {
344: _encodingStringsAsUtf8 = false;
345: _nonIdentifyingStringOnThirdBitCES = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_UTF_16_FLAG;
346: _nonIdentifyingStringOnFirstBitCES = EncodingConstants.NISTRING_UTF_16_FLAG;
347: } else {
348: _encodingStringsAsUtf8 = true;
349: _nonIdentifyingStringOnThirdBitCES = EncodingConstants.CHARACTER_CHUNK;
350: _nonIdentifyingStringOnFirstBitCES = 0;
351: }
352: }
353:
354: /**
355: * {@inheritDoc}
356: */
357: public String getCharacterEncodingScheme() {
358:• return (_encodingStringsAsUtf8) ? UTF_8 : UTF_16BE;
359: }
360:
361: /**
362: * {@inheritDoc}
363: */
364: public void setRegisteredEncodingAlgorithms(Map algorithms) {
365: _registeredEncodingAlgorithms = algorithms;
366:• if (_registeredEncodingAlgorithms == null) {
367: _registeredEncodingAlgorithms = new HashMap();
368: }
369: }
370:
371: /**
372: * {@inheritDoc}
373: */
374: public Map getRegisteredEncodingAlgorithms() {
375: return _registeredEncodingAlgorithms;
376: }
377:
378: /**
379: * {@inheritDoc}
380: */
381: public int getMinCharacterContentChunkSize() {
382: return minCharacterContentChunkSize;
383: }
384:
385: /**
386: * {@inheritDoc}
387: */
388: public void setMinCharacterContentChunkSize(int size) {
389:• if (size < 0 ) {
390: size = 0;
391: }
392:
393: minCharacterContentChunkSize = size;
394: }
395:
396: /**
397: * {@inheritDoc}
398: */
399: public int getMaxCharacterContentChunkSize() {
400: return maxCharacterContentChunkSize;
401: }
402:
403: /**
404: * {@inheritDoc}
405: */
406: public void setMaxCharacterContentChunkSize(int size) {
407:• if (size < 0 ) {
408: size = 0;
409: }
410:
411: maxCharacterContentChunkSize = size;
412: }
413:
414: /**
415: * {@inheritDoc}
416: */
417: public int getCharacterContentChunkMapMemoryLimit() {
418: return characterContentChunkMapTotalCharactersConstraint * 2;
419: }
420:
421: /**
422: * {@inheritDoc}
423: */
424: public void setCharacterContentChunkMapMemoryLimit(int size) {
425:• if (size < 0 ) {
426: size = 0;
427: }
428:
429: characterContentChunkMapTotalCharactersConstraint = size / 2;
430: }
431:
432: /**
433: * Checks whether character content chunk (its length) matches length limit
434: *
435: * @param length the length of character content chunk is checking to be added to Map.
436: * @return whether character content chunk length matches limit
437: */
438: public boolean isCharacterContentChunkLengthMatchesLimit(int length) {
439:• return length >= minCharacterContentChunkSize &&
440: length < maxCharacterContentChunkSize;
441: }
442:
443: /**
444: * Checks whether character content table has enough memory to
445: * store character content chunk with the given length
446: *
447: * @param length the length of character content chunk is checking to be added to Map.
448: * @param map the custom CharArrayIntMap, which memory limits will be checked.
449: * @return whether character content map has enough memory
450: */
451: public boolean canAddCharacterContentToTable(int length, CharArrayIntMap map) {
452:• return map.getTotalCharacterCount() + length <
453: characterContentChunkMapTotalCharactersConstraint;
454: }
455:
456: /**
457: * {@inheritDoc}
458: */
459: public int getMinAttributeValueSize() {
460: return minAttributeValueSize;
461: }
462:
463: /**
464: * {@inheritDoc}
465: */
466: public void setMinAttributeValueSize(int size) {
467:• if (size < 0 ) {
468: size = 0;
469: }
470:
471: minAttributeValueSize = size;
472: }
473:
474: /**
475: * {@inheritDoc}
476: */
477: public int getMaxAttributeValueSize() {
478: return maxAttributeValueSize;
479: }
480:
481: /**
482: * {@inheritDoc}
483: */
484: public void setMaxAttributeValueSize(int size) {
485:• if (size < 0 ) {
486: size = 0;
487: }
488:
489: maxAttributeValueSize = size;
490: }
491:
492: /**
493: * {@inheritDoc}
494: */
495: public void setAttributeValueMapMemoryLimit(int size) {
496:• if (size < 0 ) {
497: size = 0;
498: }
499:
500: attributeValueMapTotalCharactersConstraint = size / 2;
501:
502: }
503:
504: /**
505: * {@inheritDoc}
506: */
507: public int getAttributeValueMapMemoryLimit() {
508: return attributeValueMapTotalCharactersConstraint * 2;
509: }
510:
511: /**
512: * Checks whether attribute value (its length) matches length limit
513: *
514: * @param length the length of attribute
515: * @return whether attribute value matches limit
516: */
517: public boolean isAttributeValueLengthMatchesLimit(int length) {
518:• return length >= minAttributeValueSize &&
519: length < maxAttributeValueSize;
520: }
521:
522: /**
523: * Checks whether attribute table has enough memory to
524: * store attribute value with the given length
525: *
526: * @param length the length of attribute value is checking to be added to Map.
527: * @return whether attribute map has enough memory
528: */
529: public boolean canAddAttributeToTable(int length) {
530:• return _v.attributeValue.getTotalCharacterCount() + length <
531: attributeValueMapTotalCharactersConstraint;
532: }
533:
534: /**
535: * {@inheritDoc}
536: */
537: public void setExternalVocabulary(ExternalVocabulary v) {
538: // Create internal serializer vocabulary
539: _v = new SerializerVocabulary();
540: // Set the external vocabulary
541: SerializerVocabulary ev = new SerializerVocabulary(v.vocabulary,
542: _useLocalNameAsKeyForQualifiedNameLookup);
543: _v.setExternalVocabulary(v.URI,
544: ev, false);
545:
546: _vIsInternal = true;
547: }
548:
549: /**
550: * {@inheritDoc}
551: */
552: public void setVocabularyApplicationData(VocabularyApplicationData data) {
553: _vData = data;
554: }
555:
556: /**
557: * {@inheritDoc}
558: */
559: public VocabularyApplicationData getVocabularyApplicationData() {
560: return _vData;
561: }
562:
563: // End of FastInfosetSerializer interface
564:
565: /**
566: * Reset the encoder for reuse encoding another XML infoset.
567: */
568: public void reset() {
569: _terminate = false;
570: }
571:
572: /**
573: * Set the OutputStream to encode the XML infoset to a
574: * fast infoset document.
575: *
576: * @param s the OutputStream where the fast infoset document is written to.
577: */
578: public void setOutputStream(OutputStream s) {
579: _octetBufferIndex = 0;
580: _markIndex = -1;
581: _s = s;
582: }
583:
584: /**
585: * Set the SerializerVocabulary to be used for encoding.
586: *
587: * @param vocabulary the vocabulary to be used for encoding.
588: */
589: public void setVocabulary(SerializerVocabulary vocabulary) {
590: _v = vocabulary;
591: _vIsInternal = false;
592: }
593:
594: /**
595: * Encode the header of a fast infoset document.
596: *
597: * @param encodeXmlDecl true if the XML declaration should be encoded.
598: */
599: protected final void encodeHeader(boolean encodeXmlDecl) throws IOException {
600:• if (encodeXmlDecl) {
601: _s.write(EncodingConstants.XML_DECLARATION_VALUES[0]);
602: }
603: _s.write(EncodingConstants.BINARY_HEADER);
604: }
605:
606: /**
607: * Encode the initial vocabulary of a fast infoset document.
608: *
609: */
610: protected final void encodeInitialVocabulary() throws IOException {
611:• if (_v == null) {
612: _v = new SerializerVocabulary();
613: _vIsInternal = true;
614:• } else if (_vIsInternal) {
615: _v.clear();
616:• if (_vData != null)
617: _vData.clear();
618: }
619:
620:• if (!_v.hasInitialVocabulary() && !_v.hasExternalVocabulary()) {
621: write(0);
622:• } else if (_v.hasInitialVocabulary()) {
623: _b = EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG;
624: write(_b);
625:
626: SerializerVocabulary initialVocabulary = _v.getReadOnlyVocabulary();
627:
628: // TODO check for contents of vocabulary to assign bits
629:• if (initialVocabulary.hasExternalVocabulary()) {
630: _b = EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG;
631: write(_b);
632: write(0);
633: }
634:
635:• if (initialVocabulary.hasExternalVocabulary()) {
636: encodeNonEmptyOctetStringOnSecondBit(_v.getExternalVocabularyURI());
637: }
638:
639: // TODO check for contents of vocabulary to encode values
640:• } else if (_v.hasExternalVocabulary()) {
641: _b = EncodingConstants.DOCUMENT_INITIAL_VOCABULARY_FLAG;
642: write(_b);
643:
644: _b = EncodingConstants.INITIAL_VOCABULARY_EXTERNAL_VOCABULARY_FLAG;
645: write(_b);
646: write(0);
647:
648: encodeNonEmptyOctetStringOnSecondBit(_v.getExternalVocabularyURI());
649: }
650: }
651:
652: /**
653: * Encode the termination of the Document Information Item.
654: *
655: */
656: protected final void encodeDocumentTermination() throws IOException {
657: encodeElementTermination();
658: encodeTermination();
659: _flush();
660: _s.flush();
661: }
662:
663: /**
664: * Encode the termination of an Element Information Item.
665: *
666: */
667: protected final void encodeElementTermination() throws IOException {
668: _terminate = true;
669:• switch (_b) {
670: case EncodingConstants.TERMINATOR:
671: _b = EncodingConstants.DOUBLE_TERMINATOR;
672: break;
673: case EncodingConstants.DOUBLE_TERMINATOR:
674: write(EncodingConstants.DOUBLE_TERMINATOR);
675: default:
676: _b = EncodingConstants.TERMINATOR;
677: }
678: }
679:
680: /**
681: * Encode a termination if required.
682: *
683: */
684: protected final void encodeTermination() throws IOException {
685:• if (_terminate) {
686: write(_b);
687: _b = 0;
688: _terminate = false;
689: }
690: }
691:
692: /**
693: * Encode a Attribute Information Item that is a namespace declaration.
694: *
695: * @param prefix the prefix of the namespace declaration,
696: * if "" then there is no prefix for the namespace declaration.
697: * @param uri the URI of the namespace declaration,
698: * if "" then there is no URI for the namespace declaration.
699: */
700: protected final void encodeNamespaceAttribute(String prefix, String uri) throws IOException {
701: _b = EncodingConstants.NAMESPACE_ATTRIBUTE;
702:• if (prefix.length() > 0) {
703: _b |= EncodingConstants.NAMESPACE_ATTRIBUTE_PREFIX_FLAG;
704: }
705:• if (uri.length() > 0) {
706: _b |= EncodingConstants.NAMESPACE_ATTRIBUTE_NAME_FLAG;
707: }
708:
709: // NOTE a prefix with out a namespace name is an undeclaration
710: // of the namespace bound to the prefix
711: // TODO needs to investigate how the startPrefixMapping works in
712: // relation to undeclaration
713:
714: write(_b);
715:
716:• if (prefix.length() > 0) {
717: encodeIdentifyingNonEmptyStringOnFirstBit(prefix, _v.prefix);
718: }
719:• if (uri.length() > 0) {
720: encodeIdentifyingNonEmptyStringOnFirstBit(uri, _v.namespaceName);
721: }
722: }
723:
724: /**
725: * Encode a chunk of Character Information Items.
726: *
727: * @param ch the array of characters.
728: * @param offset the offset into the array of characters.
729: * @param length the length of characters.
730: * @throws ArrayIndexOutOfBoundsException
731: */
732: protected final void encodeCharacters(char[] ch, int offset, int length) throws IOException {
733: final boolean addToTable = isCharacterContentChunkLengthMatchesLimit(length);
734: encodeNonIdentifyingStringOnThirdBit(ch, offset, length, _v.characterContentChunk, addToTable, true);
735: }
736:
737: /**
738: * Encode a chunk of Character Information Items.
739: *
740: * If the array of characters is to be indexed (as determined by
741: * {@link #isCharacterContentChunkLengthMatchesLimit(int) } then the array is not cloned
742: * when adding the array to the vocabulary.
743: *
744: * @param ch the array of characters.
745: * @param offset the offset into the array of characters.
746: * @param length the length of characters.
747: * @throws ArrayIndexOutOfBoundsException
748: */
749: protected final void encodeCharactersNoClone(char[] ch, int offset, int length) throws IOException {
750: final boolean addToTable = isCharacterContentChunkLengthMatchesLimit(length);
751: encodeNonIdentifyingStringOnThirdBit(ch, offset, length, _v.characterContentChunk, addToTable, false);
752: }
753:
754: /**
755: * Encode a chunk of Character Information Items using a numeric
756: * alphabet that results in the encoding of a character in 4 bits
757: * (or two characters per octet).
758: *
759: * @param ch the array of characters.
760: * @param offset the offset into the array of characters.
761: * @param length the length of characters.
762: * @param addToTable if characters should be added to table.
763: * @throws ArrayIndexOutOfBoundsException
764: */
765: protected final void encodeNumericFourBitCharacters(char[] ch, int offset, int length,
766: boolean addToTable) throws FastInfosetException, IOException {
767: encodeFourBitCharacters(RestrictedAlphabet.NUMERIC_CHARACTERS_INDEX,
768: NUMERIC_CHARACTERS_TABLE, ch, offset, length, addToTable);
769: }
770:
771: /**
772: * Encode a chunk of Character Information Items using a date-time
773: * alphabet that results in the encoding of a character in 4 bits
774: * (or two characters per octet).
775: *
776: * @param ch the array of characters.
777: * @param offset the offset into the array of characters.
778: * @param length the length of characters.
779: * @param addToTable if characters should be added to table.
780: * @throws ArrayIndexOutOfBoundsException
781: */
782: protected final void encodeDateTimeFourBitCharacters(char[] ch, int offset, int length,
783: boolean addToTable) throws FastInfosetException, IOException {
784: encodeFourBitCharacters(RestrictedAlphabet.DATE_TIME_CHARACTERS_INDEX,
785: DATE_TIME_CHARACTERS_TABLE, ch, offset, length, addToTable);
786: }
787:
788: /**
789: * Encode a chunk of Character Information Items using a restricted
790: * alphabet that results in the encoding of a character in 4 bits
791: * (or two characters per octet).
792: *
793: * @param id the restricted alphabet identifier.
794: * @param table the table mapping characters to 4 bit values.
795: * @param ch the array of characters.
796: * @param offset the offset into the array of characters.
797: * @param length the length of characters.
798: * @param addToTable if characters should be added to table.
799: * @throws ArrayIndexOutOfBoundsException
800: */
801: protected final void encodeFourBitCharacters(int id, int[] table, char[] ch, int offset, int length,
802: boolean addToTable) throws FastInfosetException, IOException {
803:• if (addToTable) {
804: // if char array could be added to table
805: boolean canAddCharacterContentToTable =
806: canAddCharacterContentToTable(length, _v.characterContentChunk);
807:
808: // obtain/get index
809:• int index = canAddCharacterContentToTable ?
810: _v.characterContentChunk.obtainIndex(ch, offset, length, true) :
811: _v.characterContentChunk.get(ch, offset, length);
812:
813:• if (index != KeyIntMap.NOT_PRESENT) {
814: // if char array is in table
815: _b = EncodingConstants.CHARACTER_CHUNK | 0x20;
816: encodeNonZeroIntegerOnFourthBit(index);
817: return;
818:• } else if (canAddCharacterContentToTable) {
819: // if char array is not in table, but could be added
820: _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG | EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG;
821: } else {
822: // if char array is not in table and could not be added
823: _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG;
824: }
825: } else {
826: _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG;
827: }
828:
829: write (_b);
830:
831: // Encode bottom 6 bits of enoding algorithm id
832: _b = id << 2;
833:
834: encodeNonEmptyFourBitCharacterStringOnSeventhBit(table, ch, offset, length);
835: }
836:
837: /**
838: * Encode a chunk of Character Information Items using a restricted
839: * alphabet table.
840: *
841: * @param alphabet the alphabet defining the mapping between characters and
842: * integer values.
843: * @param ch the array of characters.
844: * @param offset the offset into the array of characters.
845: * @param length the length of characters.
846: * @param addToTable if characters should be added to table
847: * @throws ArrayIndexOutOfBoundsException
848: * @throws FastInfosetException if the alphabet is not present in the
849: * vocabulary.
850: */
851: protected final void encodeAlphabetCharacters(String alphabet, char[] ch, int offset, int length,
852: boolean addToTable) throws FastInfosetException, IOException {
853:• if (addToTable) {
854: // if char array could be added to table
855: boolean canAddCharacterContentToTable =
856: canAddCharacterContentToTable(length, _v.characterContentChunk);
857:
858: // obtain/get index
859:• int index = canAddCharacterContentToTable ?
860: _v.characterContentChunk.obtainIndex(ch, offset, length, true) :
861: _v.characterContentChunk.get(ch, offset, length);
862:
863:• if (index != KeyIntMap.NOT_PRESENT) {
864: // if char array is in table
865: _b = EncodingConstants.CHARACTER_CHUNK | 0x20;
866: encodeNonZeroIntegerOnFourthBit(index);
867: return;
868:• } else if (canAddCharacterContentToTable) {
869: // if char array is not in table, but could be added
870: _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG | EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG;
871: } else {
872: // if char array is not in table and could not be added
873: _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG;
874: }
875: } else {
876: _b = EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_RESTRICTED_ALPHABET_FLAG;
877: }
878:
879: int id = _v.restrictedAlphabet.get(alphabet);
880:• if (id == KeyIntMap.NOT_PRESENT) {
881: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.restrictedAlphabetNotPresent"));
882: }
883: id += EncodingConstants.RESTRICTED_ALPHABET_APPLICATION_START;
884:
885: _b |= (id & 0xC0) >> 6;
886: write(_b);
887:
888: // Encode bottom 6 bits of enoding algorithm id
889: _b = (id & 0x3F) << 2;
890:
891: encodeNonEmptyNBitCharacterStringOnSeventhBit(alphabet, ch, offset, length);
892: }
893:
894: /**
895: * Encode a Processing Instruction Information Item.
896: *
897: * @param target the target of the processing instruction.
898: * @param data the data of the processing instruction.
899: */
900: protected final void encodeProcessingInstruction(String target, String data) throws IOException {
901: write(EncodingConstants.PROCESSING_INSTRUCTION);
902:
903: // Target
904: encodeIdentifyingNonEmptyStringOnFirstBit(target, _v.otherNCName);
905:
906: // Data
907: boolean addToTable = isCharacterContentChunkLengthMatchesLimit(data.length());
908: encodeNonIdentifyingStringOnFirstBit(data, _v.otherString, addToTable);
909: }
910:
911: /**
912: * Encode a Document Type Declaration.
913: *
914: * @param systemId the system identifier of the external subset.
915: * @param publicId the public identifier of the external subset.
916: */
917: protected final void encodeDocumentTypeDeclaration(String systemId, String publicId) throws IOException {
918: _b = EncodingConstants.DOCUMENT_TYPE_DECLARATION;
919:• if (systemId != null && systemId.length() > 0) {
920: _b |= EncodingConstants.DOCUMENT_TYPE_SYSTEM_IDENTIFIER_FLAG;
921: }
922:• if (publicId != null && publicId.length() > 0) {
923: _b |= EncodingConstants.DOCUMENT_TYPE_PUBLIC_IDENTIFIER_FLAG;
924: }
925: write(_b);
926:
927:• if (systemId != null && systemId.length() > 0) {
928: encodeIdentifyingNonEmptyStringOnFirstBit(systemId, _v.otherURI);
929: }
930:• if (publicId != null && publicId.length() > 0) {
931: encodeIdentifyingNonEmptyStringOnFirstBit(publicId, _v.otherURI);
932: }
933: }
934:
935: /**
936: * Encode a Comment Information Item.
937: *
938: * @param ch the array of characters that is as comment.
939: * @param offset the offset into the array of characters.
940: * @param length the length of characters.
941: * @throws ArrayIndexOutOfBoundsException
942: */
943: protected final void encodeComment(char[] ch, int offset, int length) throws IOException {
944: write(EncodingConstants.COMMENT);
945:
946: boolean addToTable = isCharacterContentChunkLengthMatchesLimit(length);
947: encodeNonIdentifyingStringOnFirstBit(ch, offset, length, _v.otherString, addToTable, true);
948: }
949:
950: /**
951: * Encode a Comment Information Item.
952: *
953: * If the array of characters that is a comment is to be indexed (as
954: * determined by {@link #isCharacterContentChunkLengthMatchesLimit(int) }) then
955: * the array is not cloned when adding the array to the vocabulary.
956: *
957: * @param ch the array of characters.
958: * @param offset the offset into the array of characters.
959: * @param length the length of characters.
960: * @throws ArrayIndexOutOfBoundsException
961: */
962: protected final void encodeCommentNoClone(char[] ch, int offset, int length) throws IOException {
963: write(EncodingConstants.COMMENT);
964:
965: boolean addToTable = isCharacterContentChunkLengthMatchesLimit(length);
966: encodeNonIdentifyingStringOnFirstBit(ch, offset, length, _v.otherString, addToTable, false);
967: }
968:
969: /**
970: * Encode a qualified name of an Element Informaiton Item on the third bit
971: * of an octet.
972: * Implementation of clause C.18 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
973: *
974: * <p>
975: * The index of the qualified name will be encoded if the name is present
976: * in the vocabulary otherwise the qualified name will be encoded literally
977: * (see {@link #encodeLiteralElementQualifiedNameOnThirdBit}).
978: *
979: * @param namespaceURI the namespace URI of the qualified name.
980: * @param prefix the prefix of the qualified name.
981: * @param localName the local name of the qualified name.
982: */
983: protected final void encodeElementQualifiedNameOnThirdBit(String namespaceURI, String prefix, String localName) throws IOException {
984: LocalNameQualifiedNamesMap.Entry entry = _v.elementName.obtainEntry(localName);
985:• if (entry._valueIndex > 0) {
986: QualifiedName[] names = entry._value;
987:• for (int i = 0; i < entry._valueIndex; i++) {
988:• if ((prefix == names[i].prefix || prefix.equals(names[i].prefix))
989:• && (namespaceURI == names[i].namespaceName || namespaceURI.equals(names[i].namespaceName))) {
990: encodeNonZeroIntegerOnThirdBit(names[i].index);
991: return;
992: }
993: }
994: }
995:
996: encodeLiteralElementQualifiedNameOnThirdBit(namespaceURI, prefix,
997: localName, entry);
998: }
999:
1000: /**
1001: * Encode a literal qualified name of an Element Informaiton Item on the
1002: * third bit of an octet.
1003: * Implementation of clause C.18 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1004: *
1005: * @param namespaceURI the namespace URI of the qualified name.
1006: * @param prefix the prefix of the qualified name.
1007: * @param localName the local name of the qualified name.
1008: */
1009: protected final void encodeLiteralElementQualifiedNameOnThirdBit(String namespaceURI, String prefix, String localName,
1010: LocalNameQualifiedNamesMap.Entry entry) throws IOException {
1011: QualifiedName name = new QualifiedName(prefix, namespaceURI, localName, "", _v.elementName.getNextIndex());
1012: entry.addQualifiedName(name);
1013:
1014: int namespaceURIIndex = KeyIntMap.NOT_PRESENT;
1015: int prefixIndex = KeyIntMap.NOT_PRESENT;
1016:• if (namespaceURI.length() > 0) {
1017: namespaceURIIndex = _v.namespaceName.get(namespaceURI);
1018:• if (namespaceURIIndex == KeyIntMap.NOT_PRESENT) {
1019: throw new IOException(CommonResourceBundle.getInstance().getString("message.namespaceURINotIndexed", new Object[]{namespaceURI}));
1020: }
1021:
1022:• if (prefix.length() > 0) {
1023: prefixIndex = _v.prefix.get(prefix);
1024:• if (prefixIndex == KeyIntMap.NOT_PRESENT) {
1025: throw new IOException(CommonResourceBundle.getInstance().getString("message.prefixNotIndexed", new Object[]{prefix}));
1026: }
1027: }
1028: }
1029:
1030: int localNameIndex = _v.localName.obtainIndex(localName);
1031:
1032: _b |= EncodingConstants.ELEMENT_LITERAL_QNAME_FLAG;
1033:• if (namespaceURIIndex >= 0) {
1034: _b |= EncodingConstants.LITERAL_QNAME_NAMESPACE_NAME_FLAG;
1035:• if (prefixIndex >= 0) {
1036: _b |= EncodingConstants.LITERAL_QNAME_PREFIX_FLAG;
1037: }
1038: }
1039: write(_b);
1040:
1041:• if (namespaceURIIndex >= 0) {
1042:• if (prefixIndex >= 0) {
1043: encodeNonZeroIntegerOnSecondBitFirstBitOne(prefixIndex);
1044: }
1045: encodeNonZeroIntegerOnSecondBitFirstBitOne(namespaceURIIndex);
1046: }
1047:
1048:• if (localNameIndex >= 0) {
1049: encodeNonZeroIntegerOnSecondBitFirstBitOne(localNameIndex);
1050: } else {
1051: encodeNonEmptyOctetStringOnSecondBit(localName);
1052: }
1053: }
1054:
1055: /**
1056: * Encode a qualified name of an Attribute Informaiton Item on the third bit
1057: * of an octet.
1058: * Implementation of clause C.17 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1059: *
1060: * <p>
1061: * The index of the qualified name will be encoded if the name is present
1062: * in the vocabulary otherwise the qualified name will be encoded literally
1063: * (see {@link #encodeLiteralAttributeQualifiedNameOnSecondBit}).
1064: *
1065: * @param namespaceURI the namespace URI of the qualified name.
1066: * @param prefix the prefix of the qualified name.
1067: * @param localName the local name of the qualified name.
1068: */
1069: protected final void encodeAttributeQualifiedNameOnSecondBit(String namespaceURI, String prefix, String localName) throws IOException {
1070: LocalNameQualifiedNamesMap.Entry entry = _v.attributeName.obtainEntry(localName);
1071:• if (entry._valueIndex > 0) {
1072: QualifiedName[] names = entry._value;
1073:• for (int i = 0; i < entry._valueIndex; i++) {
1074:• if ((prefix == names[i].prefix || prefix.equals(names[i].prefix))
1075:• && (namespaceURI == names[i].namespaceName || namespaceURI.equals(names[i].namespaceName))) {
1076: encodeNonZeroIntegerOnSecondBitFirstBitZero(names[i].index);
1077: return;
1078: }
1079: }
1080: }
1081:
1082: encodeLiteralAttributeQualifiedNameOnSecondBit(namespaceURI, prefix,
1083: localName, entry);
1084: }
1085:
1086: /**
1087: * Encode a literal qualified name of an Attribute Informaiton Item on the
1088: * third bit of an octet.
1089: * Implementation of clause C.17 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1090: *
1091: * @param namespaceURI the namespace URI of the qualified name.
1092: * @param prefix the prefix of the qualified name.
1093: * @param localName the local name of the qualified name.
1094: */
1095: protected final boolean encodeLiteralAttributeQualifiedNameOnSecondBit(String namespaceURI, String prefix, String localName,
1096: LocalNameQualifiedNamesMap.Entry entry) throws IOException {
1097: int namespaceURIIndex = KeyIntMap.NOT_PRESENT;
1098: int prefixIndex = KeyIntMap.NOT_PRESENT;
1099:• if (namespaceURI.length() > 0) {
1100: namespaceURIIndex = _v.namespaceName.get(namespaceURI);
1101:• if (namespaceURIIndex == KeyIntMap.NOT_PRESENT) {
1102:• if (namespaceURI == EncodingConstants.XMLNS_NAMESPACE_NAME ||
1103:• namespaceURI.equals(EncodingConstants.XMLNS_NAMESPACE_NAME)) {
1104: return false;
1105: } else {
1106: throw new IOException(CommonResourceBundle.getInstance().getString("message.namespaceURINotIndexed", new Object[]{namespaceURI}));
1107: }
1108: }
1109:
1110:• if (prefix.length() > 0) {
1111: prefixIndex = _v.prefix.get(prefix);
1112:• if (prefixIndex == KeyIntMap.NOT_PRESENT) {
1113: throw new IOException(CommonResourceBundle.getInstance().getString("message.prefixNotIndexed", new Object[]{prefix}));
1114: }
1115: }
1116: }
1117:
1118: int localNameIndex = _v.localName.obtainIndex(localName);
1119:
1120: QualifiedName name = new QualifiedName(prefix, namespaceURI, localName, "", _v.attributeName.getNextIndex());
1121: entry.addQualifiedName(name);
1122:
1123: _b = EncodingConstants.ATTRIBUTE_LITERAL_QNAME_FLAG;
1124:• if (namespaceURI.length() > 0) {
1125: _b |= EncodingConstants.LITERAL_QNAME_NAMESPACE_NAME_FLAG;
1126:• if (prefix.length() > 0) {
1127: _b |= EncodingConstants.LITERAL_QNAME_PREFIX_FLAG;
1128: }
1129: }
1130:
1131: write(_b);
1132:
1133:• if (namespaceURIIndex >= 0) {
1134:• if (prefixIndex >= 0) {
1135: encodeNonZeroIntegerOnSecondBitFirstBitOne(prefixIndex);
1136: }
1137: encodeNonZeroIntegerOnSecondBitFirstBitOne(namespaceURIIndex);
1138:• } else if (namespaceURI != "") {
1139: // XML prefix and namespace name
1140: encodeNonEmptyOctetStringOnSecondBit("xml");
1141: encodeNonEmptyOctetStringOnSecondBit("http://www.w3.org/XML/1998/namespace");
1142: }
1143:
1144:• if (localNameIndex >= 0) {
1145: encodeNonZeroIntegerOnSecondBitFirstBitOne(localNameIndex);
1146: } else {
1147: encodeNonEmptyOctetStringOnSecondBit(localName);
1148: }
1149:
1150: return true;
1151: }
1152:
1153: /**
1154: * Encode a non identifying string on the first bit of an octet.
1155: * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1156: *
1157: * @param s the string to encode
1158: * @param map the vocabulary table of strings to indexes.
1159: * @param addToTable true if the string could be added to the vocabulary
1160: * table (if table has enough memory)
1161: * @param mustBeAddedToTable true if the string must be added to the vocabulary
1162: * table (if not already present in the table).
1163: */
1164: protected final void encodeNonIdentifyingStringOnFirstBit(String s, StringIntMap map,
1165: boolean addToTable, boolean mustBeAddedToTable) throws IOException {
1166:• if (s == null || s.length() == 0) {
1167: // C.26 an index (first bit '1') with seven '1' bits for an empty string
1168: write(0xFF);
1169: } else {
1170:• if (addToTable || mustBeAddedToTable) {
1171: // if attribute value could be added to table
1172:• boolean canAddAttributeToTable = mustBeAddedToTable ||
1173:• canAddAttributeToTable(s.length());
1174:
1175: // obtain/get index
1176:• int index = canAddAttributeToTable ?
1177: map.obtainIndex(s) :
1178: map.get(s);
1179:
1180:• if (index != KeyIntMap.NOT_PRESENT) {
1181: // if attribute value is in table
1182: encodeNonZeroIntegerOnSecondBitFirstBitOne(index);
1183:• } else if (canAddAttributeToTable) {
1184: // if attribute value is not in table, but could be added
1185: _b = EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG |
1186: _nonIdentifyingStringOnFirstBitCES;
1187: encodeNonEmptyCharacterStringOnFifthBit(s);
1188: } else {
1189: // if attribute value is not in table and could not be added
1190: _b = _nonIdentifyingStringOnFirstBitCES;
1191: encodeNonEmptyCharacterStringOnFifthBit(s);
1192: }
1193: } else {
1194: _b = _nonIdentifyingStringOnFirstBitCES;
1195: encodeNonEmptyCharacterStringOnFifthBit(s);
1196: }
1197: }
1198: }
1199:
1200: /**
1201: * Encode a non identifying string on the first bit of an octet.
1202: * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1203: *
1204: * @param s the string to encode
1205: * @param map the vocabulary table of character arrays to indexes.
1206: * @param addToTable true if the string should be added to the vocabulary
1207: * table (if not already present in the table).
1208: */
1209: protected final void encodeNonIdentifyingStringOnFirstBit(String s, CharArrayIntMap map, boolean addToTable) throws IOException {
1210:• if (s == null || s.length() == 0) {
1211: // C.26 an index (first bit '1') with seven '1' bits for an empty string
1212: write(0xFF);
1213: } else {
1214:• if (addToTable) {
1215: final char[] ch = s.toCharArray();
1216: final int length = s.length();
1217:
1218: // if char array could be added to table
1219: boolean canAddCharacterContentToTable =
1220: canAddCharacterContentToTable(length, map);
1221:
1222: // obtain/get index
1223:• int index = canAddCharacterContentToTable ?
1224: map.obtainIndex(ch, 0, length, false) :
1225: map.get(ch, 0, length);
1226:
1227:• if (index != KeyIntMap.NOT_PRESENT) {
1228: // if char array is in table
1229: encodeNonZeroIntegerOnSecondBitFirstBitOne(index);
1230:• } else if (canAddCharacterContentToTable) {
1231: // if char array is not in table, but could be added
1232: _b = EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG |
1233: _nonIdentifyingStringOnFirstBitCES;
1234: encodeNonEmptyCharacterStringOnFifthBit(ch, 0, length);
1235: } else {
1236: // if char array is not in table and could not be added
1237: _b = _nonIdentifyingStringOnFirstBitCES;
1238: encodeNonEmptyCharacterStringOnFifthBit(s);
1239: }
1240: } else {
1241: _b = _nonIdentifyingStringOnFirstBitCES;
1242: encodeNonEmptyCharacterStringOnFifthBit(s);
1243: }
1244: }
1245: }
1246:
1247: /**
1248: * Encode a non identifying string on the first bit of an octet.
1249: * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1250: *
1251: * @param ch the array of characters.
1252: * @param offset the offset into the array of characters.
1253: * @param length the length of characters.
1254: * @param map the vocabulary table of character arrays to indexes.
1255: * @param addToTable true if the string should be added to the vocabulary
1256: * table (if not already present in the table).
1257: * @param clone true if the array of characters should be cloned if added
1258: * to the vocabulary table.
1259: */
1260: protected final void encodeNonIdentifyingStringOnFirstBit(char[] ch, int offset, int length, CharArrayIntMap map,
1261: boolean addToTable, boolean clone) throws IOException {
1262:• if (length == 0) {
1263: // C.26 an index (first bit '1') with seven '1' bits for an empty string
1264: write(0xFF);
1265: } else {
1266:• if (addToTable) {
1267: // if char array could be added to table
1268: boolean canAddCharacterContentToTable =
1269: canAddCharacterContentToTable(length, map);
1270:
1271: // obtain/get index
1272:• int index = canAddCharacterContentToTable ?
1273: map.obtainIndex(ch, offset, length, clone) :
1274: map.get(ch, offset, length);
1275:
1276:• if (index != KeyIntMap.NOT_PRESENT) {
1277: // if char array is in table
1278: encodeNonZeroIntegerOnSecondBitFirstBitOne(index);
1279:• } else if (canAddCharacterContentToTable) {
1280: // if char array is not in table, but could be added
1281: _b = EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG |
1282: _nonIdentifyingStringOnFirstBitCES;
1283: encodeNonEmptyCharacterStringOnFifthBit(ch, offset, length);
1284: } else {
1285: // if char array is not in table and could not be added
1286: _b = _nonIdentifyingStringOnFirstBitCES;
1287: encodeNonEmptyCharacterStringOnFifthBit(ch, offset, length);
1288: }
1289: } else {
1290: _b = _nonIdentifyingStringOnFirstBitCES;
1291: encodeNonEmptyCharacterStringOnFifthBit(ch, offset, length);
1292: }
1293: }
1294: }
1295:
1296: protected final void encodeNumericNonIdentifyingStringOnFirstBit(
1297: String s, boolean addToTable, boolean mustBeAddedToTable)
1298: throws IOException, FastInfosetException {
1299: encodeNonIdentifyingStringOnFirstBit(
1300: RestrictedAlphabet.NUMERIC_CHARACTERS_INDEX,
1301: NUMERIC_CHARACTERS_TABLE, s, addToTable,
1302: mustBeAddedToTable);
1303: }
1304:
1305: protected final void encodeDateTimeNonIdentifyingStringOnFirstBit(
1306: String s, boolean addToTable, boolean mustBeAddedToTable)
1307: throws IOException, FastInfosetException {
1308: encodeNonIdentifyingStringOnFirstBit(
1309: RestrictedAlphabet.DATE_TIME_CHARACTERS_INDEX,
1310: DATE_TIME_CHARACTERS_TABLE, s, addToTable,
1311: mustBeAddedToTable);
1312: }
1313:
1314: protected final void encodeNonIdentifyingStringOnFirstBit(int id, int[] table,
1315: String s, boolean addToTable, boolean mustBeAddedToTable)
1316: throws IOException, FastInfosetException {
1317:• if (s == null || s.length() == 0) {
1318: // C.26 an index (first bit '1') with seven '1' bits for an empty string
1319: write(0xFF);
1320: return;
1321: }
1322:
1323:• if (addToTable || mustBeAddedToTable) {
1324: // if attribute value could be added to table
1325:• boolean canAddAttributeToTable = mustBeAddedToTable ||
1326:• canAddAttributeToTable(s.length());
1327:
1328: // obtain/get index
1329:• int index = canAddAttributeToTable ?
1330: _v.attributeValue.obtainIndex(s) :
1331: _v.attributeValue.get(s);
1332:
1333:• if (index != KeyIntMap.NOT_PRESENT) {
1334: // if attribute value is in table
1335: encodeNonZeroIntegerOnSecondBitFirstBitOne(index);
1336: return;
1337:• } else if (canAddAttributeToTable) {
1338: // if attribute value is not in table, but could be added
1339: _b = EncodingConstants.NISTRING_RESTRICTED_ALPHABET_FLAG |
1340: EncodingConstants.NISTRING_ADD_TO_TABLE_FLAG;
1341: } else {
1342: // if attribute value is not in table and could not be added
1343: _b = EncodingConstants.NISTRING_RESTRICTED_ALPHABET_FLAG;
1344: }
1345: } else {
1346: _b = EncodingConstants.NISTRING_RESTRICTED_ALPHABET_FLAG;
1347: }
1348:
1349: // Encode identification and top four bits of alphabet id
1350: write (_b | ((id & 0xF0) >> 4));
1351: // Encode bottom 4 bits of alphabet id
1352: _b = (id & 0x0F) << 4;
1353:
1354: final int length = s.length();
1355: final int octetPairLength = length / 2;
1356: final int octetSingleLength = length % 2;
1357: encodeNonZeroOctetStringLengthOnFifthBit(octetPairLength + octetSingleLength);
1358: encodeNonEmptyFourBitCharacterString(table, s.toCharArray(), 0, octetPairLength, octetSingleLength);
1359: }
1360:
1361: /**
1362: * Encode a non identifying string on the first bit of an octet as binary
1363: * data using an encoding algorithm.
1364: * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1365: *
1366: * @param URI the encoding algorithm URI. If the URI == null then the
1367: * encoding algorithm identifier takes precendence.
1368: * @param id the encoding algorithm identifier.
1369: * @param data the data to be encoded using an encoding algorithm.
1370: * @throws EncodingAlgorithmException if the encoding algorithm URI is not
1371: * present in the vocabulary, or the encoding algorithm identifier
1372: * is not with the required range.
1373: */
1374: protected final void encodeNonIdentifyingStringOnFirstBit(String URI, int id, Object data) throws FastInfosetException, IOException {
1375:• if (URI != null) {
1376: id = _v.encodingAlgorithm.get(URI);
1377:• if (id == KeyIntMap.NOT_PRESENT) {
1378: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.EncodingAlgorithmURI", new Object[]{URI}));
1379: }
1380: id += EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START;
1381:
1382: EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
1383:• if (ea != null) {
1384: encodeAIIObjectAlgorithmData(id, data, ea);
1385: } else {
1386:• if (data instanceof byte[]) {
1387: byte[] d = (byte[])data;
1388: encodeAIIOctetAlgorithmData(id, d, 0, d.length);
1389: } else {
1390: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI"));
1391: }
1392: }
1393:• } else if (id <= EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1394: int length = 0;
1395:• switch(id) {
1396: case EncodingAlgorithmIndexes.HEXADECIMAL:
1397: case EncodingAlgorithmIndexes.BASE64:
1398: length = ((byte[])data).length;
1399: break;
1400: case EncodingAlgorithmIndexes.SHORT:
1401: length = ((short[])data).length;
1402: break;
1403: case EncodingAlgorithmIndexes.INT:
1404: length = ((int[])data).length;
1405: break;
1406: case EncodingAlgorithmIndexes.LONG:
1407: case EncodingAlgorithmIndexes.UUID:
1408: length = ((long[])data).length;
1409: break;
1410: case EncodingAlgorithmIndexes.BOOLEAN:
1411: length = ((boolean[])data).length;
1412: break;
1413: case EncodingAlgorithmIndexes.FLOAT:
1414: length = ((float[])data).length;
1415: break;
1416: case EncodingAlgorithmIndexes.DOUBLE:
1417: length = ((double[])data).length;
1418: break;
1419: case EncodingAlgorithmIndexes.CDATA:
1420: throw new UnsupportedOperationException(CommonResourceBundle.getInstance().getString("message.CDATA"));
1421: default:
1422: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.UnsupportedBuiltInAlgorithm", new Object[]{Integer.valueOf(id)}));
1423: }
1424: encodeAIIBuiltInAlgorithmData(id, data, 0, length);
1425:• } else if (id >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1426:• if (data instanceof byte[]) {
1427: byte[] d = (byte[])data;
1428: encodeAIIOctetAlgorithmData(id, d, 0, d.length);
1429: } else {
1430: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI"));
1431: }
1432: } else {
1433: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
1434: }
1435: }
1436:
1437: /**
1438: * Encode the [normalized value] of an Attribute Information Item using
1439: * using an encoding algorithm.
1440: * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1441: *
1442: * @param id the encoding algorithm identifier.
1443: * @param d the data, as an array of bytes, to be encoded.
1444: * @param offset the offset into the array of bytes.
1445: * @param length the length of bytes.
1446: */
1447: protected final void encodeAIIOctetAlgorithmData(int id, byte[] d, int offset, int length) throws IOException {
1448: // Encode identification and top four bits of encoding algorithm id
1449: write (EncodingConstants.NISTRING_ENCODING_ALGORITHM_FLAG |
1450: ((id & 0xF0) >> 4));
1451:
1452: // Encode bottom 4 bits of enoding algorithm id
1453: _b = (id & 0x0F) << 4;
1454:
1455: // Encode the length
1456: encodeNonZeroOctetStringLengthOnFifthBit(length);
1457:
1458: write(d, offset, length);
1459: }
1460:
1461: /**
1462: * Encode the [normalized value] of an Attribute Information Item using
1463: * using an encoding algorithm.
1464: * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1465: *
1466: * @param id the encoding algorithm identifier.
1467: * @param data the data to be encoded using an encoding algorithm.
1468: * @param ea the encoding algorithm to use to encode the data into an
1469: * array of bytes.
1470: */
1471: protected final void encodeAIIObjectAlgorithmData(int id, Object data, EncodingAlgorithm ea) throws FastInfosetException, IOException {
1472: // Encode identification and top four bits of encoding algorithm id
1473: write (EncodingConstants.NISTRING_ENCODING_ALGORITHM_FLAG |
1474: ((id & 0xF0) >> 4));
1475:
1476: // Encode bottom 4 bits of enoding algorithm id
1477: _b = (id & 0x0F) << 4;
1478:
1479: _encodingBufferOutputStream.reset();
1480: ea.encodeToOutputStream(data, _encodingBufferOutputStream);
1481: encodeNonZeroOctetStringLengthOnFifthBit(_encodingBufferIndex);
1482: write(_encodingBuffer, _encodingBufferIndex);
1483: }
1484:
1485: /**
1486: * Encode the [normalized value] of an Attribute Information Item using
1487: * using a built in encoding algorithm.
1488: * Implementation of clause C.14 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1489: *
1490: * @param id the built in encoding algorithm identifier.
1491: * @param data the data to be encoded using an encoding algorithm. The data
1492: * represents an array of items specified by the encoding algorithm
1493: * identifier
1494: * @param offset the offset into the array of bytes.
1495: * @param length the length of bytes.
1496: */
1497: protected final void encodeAIIBuiltInAlgorithmData(int id, Object data, int offset, int length) throws IOException {
1498: // Encode identification and top four bits of encoding algorithm id
1499: write (EncodingConstants.NISTRING_ENCODING_ALGORITHM_FLAG |
1500: ((id & 0xF0) >> 4));
1501:
1502: // Encode bottom 4 bits of enoding algorithm id
1503: _b = (id & 0x0F) << 4;
1504:
1505: final int octetLength = BuiltInEncodingAlgorithmFactory.getAlgorithm(id).
1506: getOctetLengthFromPrimitiveLength(length);
1507:
1508: encodeNonZeroOctetStringLengthOnFifthBit(octetLength);
1509:
1510: ensureSize(octetLength);
1511: BuiltInEncodingAlgorithmFactory.getAlgorithm(id).
1512: encodeToBytes(data, offset, length, _octetBuffer, _octetBufferIndex);
1513: _octetBufferIndex += octetLength;
1514: }
1515:
1516: /**
1517: * Encode a non identifying string on the third bit of an octet.
1518: * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1519: *
1520: * @param ch the array of characters.
1521: * @param offset the offset into the array of characters.
1522: * @param length the length of characters.
1523: * @param map the vocabulary table of character arrays to indexes.
1524: * @param addToTable true if the array of characters should be added to the vocabulary
1525: * table (if not already present in the table).
1526: * @param clone true if the array of characters should be cloned if added
1527: * to the vocabulary table.
1528: */
1529: protected final void encodeNonIdentifyingStringOnThirdBit(char[] ch, int offset, int length,
1530: CharArrayIntMap map, boolean addToTable, boolean clone) throws IOException {
1531: // length cannot be zero since sequence of CIIs has to be > 0
1532:
1533:• if (addToTable) {
1534: // if char array could be added to table
1535: boolean canAddCharacterContentToTable =
1536: canAddCharacterContentToTable(length, map);
1537:
1538: // obtain/get index
1539:• int index = canAddCharacterContentToTable ?
1540: map.obtainIndex(ch, offset, length, clone) :
1541: map.get(ch, offset, length);
1542:
1543:• if (index != KeyIntMap.NOT_PRESENT) {
1544: // if char array is in table
1545: _b = EncodingConstants.CHARACTER_CHUNK | 0x20;
1546: encodeNonZeroIntegerOnFourthBit(index);
1547:• } else if (canAddCharacterContentToTable) {
1548: // if char array is not in table, but could be added
1549: _b = EncodingConstants.CHARACTER_CHUNK_ADD_TO_TABLE_FLAG |
1550: _nonIdentifyingStringOnThirdBitCES;
1551: encodeNonEmptyCharacterStringOnSeventhBit(ch, offset, length);
1552: } else {
1553: // if char array is not in table and could not be added
1554: _b = _nonIdentifyingStringOnThirdBitCES;
1555: encodeNonEmptyCharacterStringOnSeventhBit(ch, offset, length);
1556: }
1557: } else {
1558: // char array will not be added to map
1559: _b = _nonIdentifyingStringOnThirdBitCES;
1560: encodeNonEmptyCharacterStringOnSeventhBit(ch, offset, length);
1561: }
1562: }
1563:
1564: /**
1565: * Encode a non identifying string on the third bit of an octet as binary
1566: * data using an encoding algorithm.
1567: * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1568: *
1569: * @param URI the encoding algorithm URI. If the URI == null then the
1570: * encoding algorithm identifier takes precendence.
1571: * @param id the encoding algorithm identifier.
1572: * @param data the data to be encoded using an encoding algorithm.
1573: * @throws EncodingAlgorithmException if the encoding algorithm URI is not
1574: * present in the vocabulary, or the encoding algorithm identifier
1575: * is not with the required range.
1576: */
1577: protected final void encodeNonIdentifyingStringOnThirdBit(String URI, int id, Object data) throws FastInfosetException, IOException {
1578:• if (URI != null) {
1579: id = _v.encodingAlgorithm.get(URI);
1580:• if (id == KeyIntMap.NOT_PRESENT) {
1581: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.EncodingAlgorithmURI", new Object[]{URI}));
1582: }
1583: id += EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START;
1584:
1585: EncodingAlgorithm ea = (EncodingAlgorithm)_registeredEncodingAlgorithms.get(URI);
1586:• if (ea != null) {
1587: encodeCIIObjectAlgorithmData(id, data, ea);
1588: } else {
1589:• if (data instanceof byte[]) {
1590: byte[] d = (byte[])data;
1591: encodeCIIOctetAlgorithmData(id, d, 0, d.length);
1592: } else {
1593: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI"));
1594: }
1595: }
1596:• } else if (id <= EncodingConstants.ENCODING_ALGORITHM_BUILTIN_END) {
1597: int length = 0;
1598:• switch(id) {
1599: case EncodingAlgorithmIndexes.HEXADECIMAL:
1600: case EncodingAlgorithmIndexes.BASE64:
1601: length = ((byte[])data).length;
1602: break;
1603: case EncodingAlgorithmIndexes.SHORT:
1604: length = ((short[])data).length;
1605: break;
1606: case EncodingAlgorithmIndexes.INT:
1607: length = ((int[])data).length;
1608: break;
1609: case EncodingAlgorithmIndexes.LONG:
1610: case EncodingAlgorithmIndexes.UUID:
1611: length = ((long[])data).length;
1612: break;
1613: case EncodingAlgorithmIndexes.BOOLEAN:
1614: length = ((boolean[])data).length;
1615: break;
1616: case EncodingAlgorithmIndexes.FLOAT:
1617: length = ((float[])data).length;
1618: break;
1619: case EncodingAlgorithmIndexes.DOUBLE:
1620: length = ((double[])data).length;
1621: break;
1622: case EncodingAlgorithmIndexes.CDATA:
1623: throw new UnsupportedOperationException(CommonResourceBundle.getInstance().getString("message.CDATA"));
1624: default:
1625: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.UnsupportedBuiltInAlgorithm", new Object[]{Integer.valueOf(id)}));
1626: }
1627: encodeCIIBuiltInAlgorithmData(id, data, 0, length);
1628:• } else if (id >= EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START) {
1629:• if (data instanceof byte[]) {
1630: byte[] d = (byte[])data;
1631: encodeCIIOctetAlgorithmData(id, d, 0, d.length);
1632: } else {
1633: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.nullEncodingAlgorithmURI"));
1634: }
1635: } else {
1636: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.identifiers10to31Reserved"));
1637: }
1638: }
1639:
1640: /**
1641: * Encode a non identifying string on the third bit of an octet as binary
1642: * data using an encoding algorithm.
1643: * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1644: *
1645: * @param URI the encoding algorithm URI. If the URI == null then the
1646: * encoding algorithm identifier takes precendence.
1647: * @param id the encoding algorithm identifier.
1648: * @param d the data, as an array of bytes, to be encoded.
1649: * @param offset the offset into the array of bytes.
1650: * @param length the length of bytes.
1651: * @throws EncodingAlgorithmException if the encoding algorithm URI is not
1652: * present in the vocabulary.
1653: */
1654: protected final void encodeNonIdentifyingStringOnThirdBit(String URI, int id, byte[] d, int offset, int length) throws FastInfosetException, IOException {
1655:• if (URI != null) {
1656: id = _v.encodingAlgorithm.get(URI);
1657:• if (id == KeyIntMap.NOT_PRESENT) {
1658: throw new EncodingAlgorithmException(CommonResourceBundle.getInstance().getString("message.EncodingAlgorithmURI", new Object[]{URI}));
1659: }
1660: id += EncodingConstants.ENCODING_ALGORITHM_APPLICATION_START;
1661: }
1662:
1663: encodeCIIOctetAlgorithmData(id, d, offset, length);
1664: }
1665:
1666: /**
1667: * Encode a chunk of Character Information Items using
1668: * using an encoding algorithm.
1669: * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1670: *
1671: * @param id the encoding algorithm identifier.
1672: * @param d the data, as an array of bytes, to be encoded.
1673: * @param offset the offset into the array of bytes.
1674: * @param length the length of bytes.
1675: */
1676: protected final void encodeCIIOctetAlgorithmData(int id, byte[] d, int offset, int length) throws IOException {
1677: // Encode identification and top two bits of encoding algorithm id
1678: write (EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_ENCODING_ALGORITHM_FLAG |
1679: ((id & 0xC0) >> 6));
1680:
1681: // Encode bottom 6 bits of enoding algorithm id
1682: _b = (id & 0x3F) << 2;
1683:
1684: // Encode the length
1685: encodeNonZeroOctetStringLengthOnSenventhBit(length);
1686:
1687: write(d, offset, length);
1688: }
1689:
1690: /**
1691: * Encode a chunk of Character Information Items using
1692: * using an encoding algorithm.
1693: * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1694: *
1695: * @param id the encoding algorithm identifier.
1696: * @param data the data to be encoded using an encoding algorithm.
1697: * @param ea the encoding algorithm to use to encode the data into an
1698: * array of bytes.
1699: */
1700: protected final void encodeCIIObjectAlgorithmData(int id, Object data, EncodingAlgorithm ea) throws FastInfosetException, IOException {
1701: // Encode identification and top two bits of encoding algorithm id
1702: write (EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_ENCODING_ALGORITHM_FLAG |
1703: ((id & 0xC0) >> 6));
1704:
1705: // Encode bottom 6 bits of enoding algorithm id
1706: _b = (id & 0x3F) << 2;
1707:
1708: _encodingBufferOutputStream.reset();
1709: ea.encodeToOutputStream(data, _encodingBufferOutputStream);
1710: encodeNonZeroOctetStringLengthOnSenventhBit(_encodingBufferIndex);
1711: write(_encodingBuffer, _encodingBufferIndex);
1712: }
1713:
1714: /**
1715: * Encode a chunk of Character Information Items using
1716: * using an encoding algorithm.
1717: * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1718: *
1719: * @param id the built in encoding algorithm identifier.
1720: * @param data the data to be encoded using an encoding algorithm. The data
1721: * represents an array of items specified by the encoding algorithm
1722: * identifier
1723: * @param offset the offset into the array of bytes.
1724: * @param length the length of bytes.
1725: */
1726: protected final void encodeCIIBuiltInAlgorithmData(int id, Object data, int offset, int length) throws FastInfosetException, IOException {
1727: // Encode identification and top two bits of encoding algorithm id
1728: write (EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_ENCODING_ALGORITHM_FLAG |
1729: ((id & 0xC0) >> 6));
1730:
1731: // Encode bottom 6 bits of enoding algorithm id
1732: _b = (id & 0x3F) << 2;
1733:
1734: final int octetLength = BuiltInEncodingAlgorithmFactory.getAlgorithm(id).
1735: getOctetLengthFromPrimitiveLength(length);
1736:
1737: encodeNonZeroOctetStringLengthOnSenventhBit(octetLength);
1738:
1739: ensureSize(octetLength);
1740: BuiltInEncodingAlgorithmFactory.getAlgorithm(id).
1741: encodeToBytes(data, offset, length, _octetBuffer, _octetBufferIndex);
1742: _octetBufferIndex += octetLength;
1743: }
1744:
1745: /**
1746: * Encode a chunk of Character Information Items using
1747: * using the CDATA built in encoding algorithm.
1748: * Implementation of clause C.15 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1749: *
1750: * @param ch the array of characters.
1751: * @param offset the offset into the array of characters.
1752: * @param length the length of characters.
1753: */
1754: protected final void encodeCIIBuiltInAlgorithmDataAsCDATA(char[] ch, int offset, int length) throws FastInfosetException, IOException {
1755: // Encode identification and top two bits of encoding algorithm id
1756: write (EncodingConstants.CHARACTER_CHUNK | EncodingConstants.CHARACTER_CHUNK_ENCODING_ALGORITHM_FLAG);
1757:
1758: // Encode bottom 6 bits of enoding algorithm id
1759: _b = EncodingAlgorithmIndexes.CDATA << 2;
1760:
1761:
1762: length = encodeUTF8String(ch, offset, length);
1763: encodeNonZeroOctetStringLengthOnSenventhBit(length);
1764: write(_encodingBuffer, length);
1765: }
1766:
1767: /**
1768: * Encode a non empty identifying string on the first bit of an octet.
1769: * Implementation of clause C.13 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1770: *
1771: * @param s the identifying string.
1772: * @param map the vocabulary table to use to determin the index of the
1773: * identifying string
1774: */
1775: protected final void encodeIdentifyingNonEmptyStringOnFirstBit(String s, StringIntMap map) throws IOException {
1776: int index = map.obtainIndex(s);
1777:• if (index == KeyIntMap.NOT_PRESENT) {
1778: // _b = 0;
1779: encodeNonEmptyOctetStringOnSecondBit(s);
1780: } else {
1781: // _b = 0x80;
1782: encodeNonZeroIntegerOnSecondBitFirstBitOne(index);
1783: }
1784: }
1785:
1786: /**
1787: * Encode a non empty string on the second bit of an octet using the UTF-8
1788: * encoding.
1789: * Implementation of clause C.22 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1790: *
1791: * @param s the string.
1792: */
1793: protected final void encodeNonEmptyOctetStringOnSecondBit(String s) throws IOException {
1794: final int length = encodeUTF8String(s);
1795: encodeNonZeroOctetStringLengthOnSecondBit(length);
1796: write(_encodingBuffer, length);
1797: }
1798:
1799: /**
1800: * Encode the length of a UTF-8 encoded string on the second bit of an octet.
1801: * Implementation of clause C.22 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1802: *
1803: * @param length the length to encode.
1804: */
1805: protected final void encodeNonZeroOctetStringLengthOnSecondBit(int length) throws IOException {
1806:• if (length < EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT) {
1807: // [1, 64]
1808: write(length - 1);
1809:• } else if (length < EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT) {
1810: // [65, 320]
1811: write(EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_FLAG); // 010 00000
1812: write(length - EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_SMALL_LIMIT);
1813: } else {
1814: // [321, 4294967296]
1815: write(EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_LARGE_FLAG); // 0110 0000
1816: length -= EncodingConstants.OCTET_STRING_LENGTH_2ND_BIT_MEDIUM_LIMIT;
1817: write(length >>> 24);
1818: write((length >> 16) & 0xFF);
1819: write((length >> 8) & 0xFF);
1820: write(length & 0xFF);
1821: }
1822: }
1823:
1824: /**
1825: * Encode a non empty string on the fifth bit of an octet using the UTF-8
1826: * or UTF-16 encoding.
1827: * Implementation of clause C.23 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1828: *
1829: * @param s the string.
1830: */
1831: protected final void encodeNonEmptyCharacterStringOnFifthBit(String s) throws IOException {
1832:• final int length = (_encodingStringsAsUtf8) ? encodeUTF8String(s) : encodeUtf16String(s);
1833: encodeNonZeroOctetStringLengthOnFifthBit(length);
1834: write(_encodingBuffer, length);
1835: }
1836:
1837: /**
1838: * Encode a non empty string on the fifth bit of an octet using the UTF-8
1839: * or UTF-16 encoding.
1840: * Implementation of clause C.23 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1841: *
1842: * @param ch the array of characters.
1843: * @param offset the offset into the array of characters.
1844: * @param length the length of characters.
1845: */
1846: protected final void encodeNonEmptyCharacterStringOnFifthBit(char[] ch, int offset, int length) throws IOException {
1847:• length = (_encodingStringsAsUtf8) ? encodeUTF8String(ch, offset, length) : encodeUtf16String(ch, offset, length);
1848: encodeNonZeroOctetStringLengthOnFifthBit(length);
1849: write(_encodingBuffer, length);
1850: }
1851:
1852: /**
1853: * Encode the length of a UTF-8 or UTF-16 encoded string on the fifth bit
1854: * of an octet.
1855: * Implementation of clause C.23 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1856: *
1857: * @param length the length to encode.
1858: */
1859: protected final void encodeNonZeroOctetStringLengthOnFifthBit(int length) throws IOException {
1860:• if (length < EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT) {
1861: // [1, 8]
1862: write(_b | (length - 1));
1863:• } else if (length < EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT) {
1864: // [9, 264]
1865: write(_b | EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_FLAG); // 000010 00
1866: write(length - EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_SMALL_LIMIT);
1867: } else {
1868: // [265, 4294967296]
1869: write(_b | EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_LARGE_FLAG); // 000011 00
1870: length -= EncodingConstants.OCTET_STRING_LENGTH_5TH_BIT_MEDIUM_LIMIT;
1871: write(length >>> 24);
1872: write((length >> 16) & 0xFF);
1873: write((length >> 8) & 0xFF);
1874: write(length & 0xFF);
1875: }
1876: }
1877:
1878: /**
1879: * Encode a non empty string on the seventh bit of an octet using the UTF-8
1880: * or UTF-16 encoding.
1881: * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1882: *
1883: * @param ch the array of characters.
1884: * @param offset the offset into the array of characters.
1885: * @param length the length of characters.
1886: */
1887: protected final void encodeNonEmptyCharacterStringOnSeventhBit(char[] ch, int offset, int length) throws IOException {
1888:• length = (_encodingStringsAsUtf8) ? encodeUTF8String(ch, offset, length) : encodeUtf16String(ch, offset, length);
1889: encodeNonZeroOctetStringLengthOnSenventhBit(length);
1890: write(_encodingBuffer, length);
1891: }
1892:
1893: /**
1894: * Encode a non empty string on the seventh bit of an octet using a restricted
1895: * alphabet that results in the encoding of a character in 4 bits
1896: * (or two characters per octet).
1897: * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1898: *
1899: * @param table the table mapping characters to 4 bit values.
1900: * @param ch the array of characters.
1901: * @param offset the offset into the array of characters.
1902: * @param length the length of characters.
1903: */
1904: protected final void encodeNonEmptyFourBitCharacterStringOnSeventhBit(int[] table, char[] ch, int offset, int length) throws FastInfosetException, IOException {
1905: final int octetPairLength = length / 2;
1906: final int octetSingleLength = length % 2;
1907:
1908: // Encode the length
1909: encodeNonZeroOctetStringLengthOnSenventhBit(octetPairLength + octetSingleLength);
1910: encodeNonEmptyFourBitCharacterString(table, ch, offset, octetPairLength, octetSingleLength);
1911: }
1912:
1913: protected final void encodeNonEmptyFourBitCharacterString(int[] table, char[] ch, int offset,
1914: int octetPairLength, int octetSingleLength) throws FastInfosetException, IOException {
1915: ensureSize(octetPairLength + octetSingleLength);
1916: // Encode all pairs
1917: int v = 0;
1918:• for (int i = 0; i < octetPairLength; i++) {
1919: v = (table[ch[offset++]] << 4) | table[ch[offset++]];
1920:• if (v < 0) {
1921: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.characterOutofAlphabetRange"));
1922: }
1923: _octetBuffer[_octetBufferIndex++] = (byte)v;
1924: }
1925: // Encode single character at end with termination bits
1926:• if (octetSingleLength == 1) {
1927: v = (table[ch[offset]] << 4) | 0x0F;
1928:• if (v < 0) {
1929: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.characterOutofAlphabetRange"));
1930: }
1931: _octetBuffer[_octetBufferIndex++] = (byte)v;
1932: }
1933: }
1934:
1935: /**
1936: * Encode a non empty string on the seventh bit of an octet using a restricted
1937: * alphabet table.
1938: * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
1939: *
1940: * @param alphabet the alphabet defining the mapping between characters and
1941: * integer values.
1942: * @param ch the array of characters.
1943: * @param offset the offset into the array of characters.
1944: * @param length the length of characters.
1945: */
1946: protected final void encodeNonEmptyNBitCharacterStringOnSeventhBit(String alphabet, char[] ch, int offset, int length) throws FastInfosetException, IOException {
1947: int bitsPerCharacter = 1;
1948:• while ((1 << bitsPerCharacter) <= alphabet.length()) {
1949: bitsPerCharacter++;
1950: }
1951:
1952: final int bits = length * bitsPerCharacter;
1953: final int octets = bits / 8;
1954: final int bitsOfLastOctet = bits % 8;
1955:• final int totalOctets = octets + ((bitsOfLastOctet > 0) ? 1 : 0);
1956:
1957: // Encode the length
1958: encodeNonZeroOctetStringLengthOnSenventhBit(totalOctets);
1959:
1960: resetBits();
1961: ensureSize(totalOctets);
1962: int v = 0;
1963:• for (int i = 0; i < length; i++) {
1964: final char c = ch[offset + i];
1965: // This is grotesquely slow, need to use hash table of character to int value
1966:• for (v = 0; v < alphabet.length(); v++) {
1967:• if (c == alphabet.charAt(v)) {
1968: break;
1969: }
1970: }
1971:• if (v == alphabet.length()) {
1972: throw new FastInfosetException(CommonResourceBundle.getInstance().getString("message.characterOutofAlphabetRange"));
1973: }
1974: writeBits(bitsPerCharacter, v);
1975: }
1976:
1977:• if (bitsOfLastOctet > 0) {
1978: _b |= (1 << (8 - bitsOfLastOctet)) - 1;
1979: write(_b);
1980: }
1981: }
1982:
1983: private int _bitsLeftInOctet;
1984:
1985: private final void resetBits() {
1986: _bitsLeftInOctet = 8;
1987: _b = 0;
1988: }
1989:
1990: private final void writeBits(int bits, int v) throws IOException {
1991:• while (bits > 0) {
1992:• final int bit = (v & (1 << --bits)) > 0 ? 1 : 0;
1993: _b |= bit << (--_bitsLeftInOctet);
1994:• if (_bitsLeftInOctet == 0) {
1995: write(_b);
1996: _bitsLeftInOctet = 8;
1997: _b = 0;
1998: }
1999: }
2000: }
2001:
2002: /**
2003: * Encode the length of a encoded string on the seventh bit
2004: * of an octet.
2005: * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
2006: *
2007: * @param length the length to encode.
2008: */
2009: protected final void encodeNonZeroOctetStringLengthOnSenventhBit(int length) throws IOException {
2010:• if (length < EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT) {
2011: // [1, 2]
2012: write(_b | (length - 1));
2013:• } else if (length < EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT) {
2014: // [3, 258]
2015: write(_b | EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_FLAG); // 00000010
2016: write(length - EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_SMALL_LIMIT);
2017: } else {
2018: // [259, 4294967296]
2019: write(_b | EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_LARGE_FLAG); // 00000011
2020: length -= EncodingConstants.OCTET_STRING_LENGTH_7TH_BIT_MEDIUM_LIMIT;
2021: write(length >>> 24);
2022: write((length >> 16) & 0xFF);
2023: write((length >> 8) & 0xFF);
2024: write(length & 0xFF);
2025: }
2026: }
2027:
2028: /**
2029: * Encode a non zero integer on the second bit of an octet, setting
2030: * the first bit to 1.
2031: * Implementation of clause C.24 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
2032: *
2033: * <p>
2034: * The first bit of the first octet is set, as specified in clause C.13 of
2035: * ITU-T Rec. X.891 | ISO/IEC 24824-1
2036: *
2037: * @param i The integer to encode, which is a member of the interval
2038: * [0, 1048575]. In the specification the interval is [1, 1048576]
2039: *
2040: */
2041: protected final void encodeNonZeroIntegerOnSecondBitFirstBitOne(int i) throws IOException {
2042:• if (i < EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT) {
2043: // [1, 64] ( [0, 63] ) 6 bits
2044: write(0x80 | i);
2045:• } else if (i < EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT) {
2046: // [65, 8256] ( [64, 8255] ) 13 bits
2047: i -= EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
2048: _b = (0x80 | EncodingConstants.INTEGER_2ND_BIT_MEDIUM_FLAG) | (i >> 8); // 010 00000
2049: // _b = 0xC0 | (i >> 8); // 010 00000
2050: write(_b);
2051: write(i & 0xFF);
2052:• } else if (i < EncodingConstants.INTEGER_2ND_BIT_LARGE_LIMIT) {
2053: // [8257, 1048576] ( [8256, 1048575] ) 20 bits
2054: i -= EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
2055: _b = (0x80 | EncodingConstants.INTEGER_2ND_BIT_LARGE_FLAG) | (i >> 16); // 0110 0000
2056: // _b = 0xE0 | (i >> 16); // 0110 0000
2057: write(_b);
2058: write((i >> 8) & 0xFF);
2059: write(i & 0xFF);
2060: } else {
2061: throw new IOException(
2062: CommonResourceBundle.getInstance().getString("message.integerMaxSize",
2063: new Object[]{Integer.valueOf(EncodingConstants.INTEGER_2ND_BIT_LARGE_LIMIT)}));
2064: }
2065: }
2066:
2067: /**
2068: * Encode a non zero integer on the second bit of an octet, setting
2069: * the first bit to 0.
2070: * Implementation of clause C.25 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
2071: *
2072: * <p>
2073: * The first bit of the first octet is set, as specified in clause C.13 of
2074: * ITU-T Rec. X.891 | ISO/IEC 24824-1
2075: *
2076: * @param i The integer to encode, which is a member of the interval
2077: * [0, 1048575]. In the specification the interval is [1, 1048576]
2078: *
2079: */
2080: protected final void encodeNonZeroIntegerOnSecondBitFirstBitZero(int i) throws IOException {
2081:• if (i < EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT) {
2082: // [1, 64] ( [0, 63] ) 6 bits
2083: write(i);
2084:• } else if (i < EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT) {
2085: // [65, 8256] ( [64, 8255] ) 13 bits
2086: i -= EncodingConstants.INTEGER_2ND_BIT_SMALL_LIMIT;
2087: _b = EncodingConstants.INTEGER_2ND_BIT_MEDIUM_FLAG | (i >> 8); // 010 00000
2088: write(_b);
2089: write(i & 0xFF);
2090: } else {
2091: // [8257, 1048576] ( [8256, 1048575] ) 20 bits
2092: i -= EncodingConstants.INTEGER_2ND_BIT_MEDIUM_LIMIT;
2093: _b = EncodingConstants.INTEGER_2ND_BIT_LARGE_FLAG | (i >> 16); // 0110 0000
2094: write(_b);
2095: write((i >> 8) & 0xFF);
2096: write(i & 0xFF);
2097: }
2098: }
2099:
2100: /**
2101: * Encode a non zero integer on the third bit of an octet.
2102: * Implementation of clause C.27 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
2103: *
2104: * @param i The integer to encode, which is a member of the interval
2105: * [0, 1048575]. In the specification the interval is [1, 1048576]
2106: *
2107: */
2108: protected final void encodeNonZeroIntegerOnThirdBit(int i) throws IOException {
2109:• if (i < EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT) {
2110: // [1, 32] ( [0, 31] ) 5 bits
2111: write(_b | i);
2112:• } else if (i < EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT) {
2113: // [33, 2080] ( [32, 2079] ) 11 bits
2114: i -= EncodingConstants.INTEGER_3RD_BIT_SMALL_LIMIT;
2115: _b |= EncodingConstants.INTEGER_3RD_BIT_MEDIUM_FLAG | (i >> 8); // 00100 000
2116: write(_b);
2117: write(i & 0xFF);
2118:• } else if (i < EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT) {
2119: // [2081, 526368] ( [2080, 526367] ) 19 bits
2120: i -= EncodingConstants.INTEGER_3RD_BIT_MEDIUM_LIMIT;
2121: _b |= EncodingConstants.INTEGER_3RD_BIT_LARGE_FLAG | (i >> 16); // 00101 000
2122: write(_b);
2123: write((i >> 8) & 0xFF);
2124: write(i & 0xFF);
2125: } else {
2126: // [526369, 1048576] ( [526368, 1048575] ) 20 bits
2127: i -= EncodingConstants.INTEGER_3RD_BIT_LARGE_LIMIT;
2128: _b |= EncodingConstants.INTEGER_3RD_BIT_LARGE_LARGE_FLAG; // 00110 000
2129: write(_b);
2130: write(i >> 16);
2131: write((i >> 8) & 0xFF);
2132: write(i & 0xFF);
2133: }
2134: }
2135:
2136: /**
2137: * Encode a non zero integer on the fourth bit of an octet.
2138: * Implementation of clause C.28 of ITU-T Rec. X.891 | ISO/IEC 24824-1.
2139: *
2140: * @param i The integer to encode, which is a member of the interval
2141: * [0, 1048575]. In the specification the interval is [1, 1048576]
2142: *
2143: */
2144: protected final void encodeNonZeroIntegerOnFourthBit(int i) throws IOException {
2145:• if (i < EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT) {
2146: // [1, 16] ( [0, 15] ) 4 bits
2147: write(_b | i);
2148:• } else if (i < EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT) {
2149: // [17, 1040] ( [16, 1039] ) 10 bits
2150: i -= EncodingConstants.INTEGER_4TH_BIT_SMALL_LIMIT;
2151: _b |= EncodingConstants.INTEGER_4TH_BIT_MEDIUM_FLAG | (i >> 8); // 000 100 00
2152: write(_b);
2153: write(i & 0xFF);
2154:• } else if (i < EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT) {
2155: // [1041, 263184] ( [1040, 263183] ) 18 bits
2156: i -= EncodingConstants.INTEGER_4TH_BIT_MEDIUM_LIMIT;
2157: _b |= EncodingConstants.INTEGER_4TH_BIT_LARGE_FLAG | (i >> 16); // 000 101 00
2158: write(_b);
2159: write((i >> 8) & 0xFF);
2160: write(i & 0xFF);
2161: } else {
2162: // [263185, 1048576] ( [263184, 1048575] ) 20 bits
2163: i -= EncodingConstants.INTEGER_4TH_BIT_LARGE_LIMIT;
2164: _b |= EncodingConstants.INTEGER_4TH_BIT_LARGE_LARGE_FLAG; // 000 110 00
2165: write(_b);
2166: write(i >> 16);
2167: write((i >> 8) & 0xFF);
2168: write(i & 0xFF);
2169: }
2170: }
2171:
2172: /**
2173: * Encode a non empty string using the UTF-8 encoding.
2174: *
2175: * @param b the current octet that is being written.
2176: * @param s the string to be UTF-8 encoded.
2177: * @param constants the array of constants to use when encoding to determin
2178: * how the length of the UTF-8 encoded string is encoded.
2179: */
2180: protected final void encodeNonEmptyUTF8StringAsOctetString(int b, String s, int[] constants) throws IOException {
2181: final char[] ch = s.toCharArray();
2182: encodeNonEmptyUTF8StringAsOctetString(b, ch, 0, ch.length, constants);
2183: }
2184:
2185: /**
2186: * Encode a non empty string using the UTF-8 encoding.
2187: *
2188: * @param b the current octet that is being written.
2189: * @param ch the array of characters.
2190: * @param offset the offset into the array of characters.
2191: * @param length the length of characters.
2192: * how the length of the UTF-8 encoded string is encoded.
2193: * @param constants the array of constants to use when encoding to determin
2194: * how the length of the UTF-8 encoded string is encoded.
2195: */
2196: protected final void encodeNonEmptyUTF8StringAsOctetString(int b, char ch[], int offset, int length, int[] constants) throws IOException {
2197: length = encodeUTF8String(ch, offset, length);
2198: encodeNonZeroOctetStringLength(b, length, constants);
2199: write(_encodingBuffer, length);
2200: }
2201:
2202: /**
2203: * Encode the length of non empty UTF-8 encoded string.
2204: *
2205: * @param b the current octet that is being written.
2206: * @param length the length of the UTF-8 encoded string.
2207: * how the length of the UTF-8 encoded string is encoded.
2208: * @param constants the array of constants to use when encoding to determin
2209: * how the length of the UTF-8 encoded string is encoded.
2210: */
2211: protected final void encodeNonZeroOctetStringLength(int b, int length, int[] constants) throws IOException {
2212:• if (length < constants[EncodingConstants.OCTET_STRING_LENGTH_SMALL_LIMIT]) {
2213: write(b | (length - 1));
2214:• } else if (length < constants[EncodingConstants.OCTET_STRING_LENGTH_MEDIUM_LIMIT]) {
2215: write(b | constants[EncodingConstants.OCTET_STRING_LENGTH_MEDIUM_FLAG]);
2216: write(length - constants[EncodingConstants.OCTET_STRING_LENGTH_SMALL_LIMIT]);
2217: } else {
2218: write(b | constants[EncodingConstants.OCTET_STRING_LENGTH_LARGE_FLAG]);
2219: length -= constants[EncodingConstants.OCTET_STRING_LENGTH_MEDIUM_LIMIT];
2220: write(length >>> 24);
2221: write((length >> 16) & 0xFF);
2222: write((length >> 8) & 0xFF);
2223: write(length & 0xFF);
2224: }
2225: }
2226:
2227: /**
2228: * Encode a non zero integer.
2229: *
2230: * @param b the current octet that is being written.
2231: * @param i the non zero integer.
2232: * @param constants the array of constants to use when encoding to determin
2233: * how the non zero integer is encoded.
2234: */
2235: protected final void encodeNonZeroInteger(int b, int i, int[] constants) throws IOException {
2236:• if (i < constants[EncodingConstants.INTEGER_SMALL_LIMIT]) {
2237: write(b | i);
2238:• } else if (i < constants[EncodingConstants.INTEGER_MEDIUM_LIMIT]) {
2239: i -= constants[EncodingConstants.INTEGER_SMALL_LIMIT];
2240: write(b | constants[EncodingConstants.INTEGER_MEDIUM_FLAG] | (i >> 8));
2241: write(i & 0xFF);
2242:• } else if (i < constants[EncodingConstants.INTEGER_LARGE_LIMIT]) {
2243: i -= constants[EncodingConstants.INTEGER_MEDIUM_LIMIT];
2244: write(b | constants[EncodingConstants.INTEGER_LARGE_FLAG] | (i >> 16));
2245: write((i >> 8) & 0xFF);
2246: write(i & 0xFF);
2247:• } else if (i < EncodingConstants.INTEGER_MAXIMUM_SIZE) {
2248: i -= constants[EncodingConstants.INTEGER_LARGE_LIMIT];
2249: write(b | constants[EncodingConstants.INTEGER_LARGE_LARGE_FLAG]);
2250: write(i >> 16);
2251: write((i >> 8) & 0xFF);
2252: write(i & 0xFF);
2253: } else {
2254: throw new IOException(CommonResourceBundle.getInstance().getString("message.integerMaxSize", new Object[]{Integer.valueOf(EncodingConstants.INTEGER_MAXIMUM_SIZE)}));
2255: }
2256: }
2257:
2258: /**
2259: * Mark the current position in the buffered stream.
2260: */
2261: protected final void mark() {
2262: _markIndex = _octetBufferIndex;
2263: }
2264:
2265: /**
2266: * Reset the marked position in the buffered stream.
2267: */
2268: protected final void resetMark() {
2269: _markIndex = -1;
2270: }
2271:
2272: /**
2273: * @return true if the mark has been set, otherwise false if the mark
2274: * has not been set.
2275: */
2276: protected final boolean hasMark() {
2277:• return _markIndex != -1;
2278: }
2279:
2280: /**
2281: * Write a byte to the buffered stream.
2282: */
2283: protected final void write(int i) throws IOException {
2284:• if (_octetBufferIndex < _octetBuffer.length) {
2285: _octetBuffer[_octetBufferIndex++] = (byte)i;
2286: } else {
2287:• if (_markIndex == -1) {
2288: _s.write(_octetBuffer);
2289: _octetBufferIndex = 1;
2290: _octetBuffer[0] = (byte)i;
2291: } else {
2292: resize(_octetBuffer.length * 3 / 2);
2293: _octetBuffer[_octetBufferIndex++] = (byte)i;
2294: }
2295: }
2296: }
2297:
2298: /**
2299: * Write an array of bytes to the buffered stream.
2300: *
2301: * @param b the array of bytes.
2302: * @param length the length of bytes.
2303: */
2304: protected final void write(byte[] b, int length) throws IOException {
2305: write(b, 0, length);
2306: }
2307:
2308: /**
2309: * Write an array of bytes to the buffered stream.
2310: *
2311: * @param b the array of bytes.
2312: * @param offset the offset into the array of bytes.
2313: * @param length the length of bytes.
2314: */
2315: protected final void write(byte[] b, int offset, int length) throws IOException {
2316:• if ((_octetBufferIndex + length) < _octetBuffer.length) {
2317: System.arraycopy(b, offset, _octetBuffer, _octetBufferIndex, length);
2318: _octetBufferIndex += length;
2319: } else {
2320:• if (_markIndex == -1) {
2321: _s.write(_octetBuffer, 0, _octetBufferIndex);
2322: _s.write(b, offset, length);
2323: _octetBufferIndex = 0;
2324: } else {
2325: resize((_octetBuffer.length + length) * 3 / 2 + 1);
2326: System.arraycopy(b, offset, _octetBuffer, _octetBufferIndex, length);
2327: _octetBufferIndex += length;
2328: }
2329: }
2330: }
2331:
2332: private void ensureSize(int length) {
2333:• if ((_octetBufferIndex + length) > _octetBuffer.length) {
2334: resize((_octetBufferIndex + length) * 3 / 2 + 1);
2335: }
2336: }
2337:
2338: private void resize(int length) {
2339: byte[] b = new byte[length];
2340: System.arraycopy(_octetBuffer, 0, b, 0, _octetBufferIndex);
2341: _octetBuffer = b;
2342: }
2343:
2344: private void _flush() throws IOException {
2345:• if (_octetBufferIndex > 0) {
2346: _s.write(_octetBuffer, 0, _octetBufferIndex);
2347: _octetBufferIndex = 0;
2348: }
2349: }
2350:
2351:
2352: private EncodingBufferOutputStream _encodingBufferOutputStream = new EncodingBufferOutputStream();
2353:
2354: private byte[] _encodingBuffer = new byte[512];
2355:
2356: private int _encodingBufferIndex;
2357:
2358: private class EncodingBufferOutputStream extends OutputStream {
2359:
2360: public void write(int b) throws IOException {
2361: if (_encodingBufferIndex < _encodingBuffer.length) {
2362: _encodingBuffer[_encodingBufferIndex++] = (byte)b;
2363: } else {
2364: byte newbuf[] = new byte[Math.max(_encodingBuffer.length << 1, _encodingBufferIndex)];
2365: System.arraycopy(_encodingBuffer, 0, newbuf, 0, _encodingBufferIndex);
2366: _encodingBuffer = newbuf;
2367:
2368: _encodingBuffer[_encodingBufferIndex++] = (byte)b;
2369: }
2370: }
2371:
2372: public void write(byte b[], int off, int len) throws IOException {
2373: if ((off < 0) || (off > b.length) || (len < 0) ||
2374: ((off + len) > b.length) || ((off + len) < 0)) {
2375: throw new IndexOutOfBoundsException();
2376: } else if (len == 0) {
2377: return;
2378: }
2379: final int newoffset = _encodingBufferIndex + len;
2380: if (newoffset > _encodingBuffer.length) {
2381: byte newbuf[] = new byte[Math.max(_encodingBuffer.length << 1, newoffset)];
2382: System.arraycopy(_encodingBuffer, 0, newbuf, 0, _encodingBufferIndex);
2383: _encodingBuffer = newbuf;
2384: }
2385: System.arraycopy(b, off, _encodingBuffer, _encodingBufferIndex, len);
2386: _encodingBufferIndex = newoffset;
2387: }
2388:
2389: public int getLength() {
2390: return _encodingBufferIndex;
2391: }
2392:
2393: public void reset() {
2394: _encodingBufferIndex = 0;
2395: }
2396: }
2397:
2398: /**
2399: * Encode a string using the UTF-8 encoding.
2400: *
2401: * @param s the string to encode.
2402: */
2403: protected final int encodeUTF8String(String s) throws IOException {
2404: final int length = s.length();
2405:• if (length < _charBuffer.length) {
2406: s.getChars(0, length, _charBuffer, 0);
2407: return encodeUTF8String(_charBuffer, 0, length);
2408: } else {
2409: char[] ch = s.toCharArray();
2410: return encodeUTF8String(ch, 0, length);
2411: }
2412: }
2413:
2414: private void ensureEncodingBufferSizeForUtf8String(int length) {
2415: final int newLength = 4 * length;
2416:• if (_encodingBuffer.length < newLength) {
2417: _encodingBuffer = new byte[newLength];
2418: }
2419: }
2420:
2421: /**
2422: * Encode a string using the UTF-8 encoding.
2423: *
2424: * @param ch the array of characters.
2425: * @param offset the offset into the array of characters.
2426: * @param length the length of characters.
2427: */
2428: protected final int encodeUTF8String(char[] ch, int offset, int length) throws IOException {
2429: int bpos = 0;
2430:
2431: // Make sure buffer is large enough
2432: ensureEncodingBufferSizeForUtf8String(length);
2433:
2434: final int end = offset + length;
2435: int c;
2436:• while (end != offset) {
2437: c = ch[offset++];
2438:• if (c < 0x80) {
2439: // 1 byte, 7 bits
2440: _encodingBuffer[bpos++] = (byte) c;
2441:• } else if (c < 0x800) {
2442: // 2 bytes, 11 bits
2443: _encodingBuffer[bpos++] =
2444: (byte) (0xC0 | (c >> 6)); // first 5
2445: _encodingBuffer[bpos++] =
2446: (byte) (0x80 | (c & 0x3F)); // second 6
2447:• } else if (c <= '\uFFFF') {
2448:• if (!XMLChar.isHighSurrogate(c) && !XMLChar.isLowSurrogate(c)) {
2449: // 3 bytes, 16 bits
2450: _encodingBuffer[bpos++] =
2451: (byte) (0xE0 | (c >> 12)); // first 4
2452: _encodingBuffer[bpos++] =
2453: (byte) (0x80 | ((c >> 6) & 0x3F)); // second 6
2454: _encodingBuffer[bpos++] =
2455: (byte) (0x80 | (c & 0x3F)); // third 6
2456: } else {
2457: // 4 bytes, high and low surrogate
2458: encodeCharacterAsUtf8FourByte(c, ch, offset, end, bpos);
2459: bpos += 4;
2460: offset++;
2461: }
2462: }
2463: }
2464:
2465: return bpos;
2466: }
2467:
2468: private void encodeCharacterAsUtf8FourByte(int c, char[] ch, int chpos, int chend, int bpos) throws IOException {
2469:• if (chpos == chend) {
2470: throw new IOException("");
2471: }
2472:
2473: final char d = ch[chpos];
2474:• if (!XMLChar.isLowSurrogate(d)) {
2475: throw new IOException("");
2476: }
2477:
2478: final int uc = (((c & 0x3ff) << 10) | (d & 0x3ff)) + 0x10000;
2479:• if (uc < 0 || uc >= 0x200000) {
2480: throw new IOException("");
2481: }
2482:
2483: _encodingBuffer[bpos++] = (byte)(0xF0 | ((uc >> 18)));
2484: _encodingBuffer[bpos++] = (byte)(0x80 | ((uc >> 12) & 0x3F));
2485: _encodingBuffer[bpos++] = (byte)(0x80 | ((uc >> 6) & 0x3F));
2486: _encodingBuffer[bpos++] = (byte)(0x80 | (uc & 0x3F));
2487: }
2488:
2489: /**
2490: * Encode a string using the UTF-16 encoding.
2491: *
2492: * @param s the string to encode.
2493: */
2494: protected final int encodeUtf16String(String s) throws IOException {
2495: final int length = s.length();
2496:• if (length < _charBuffer.length) {
2497: s.getChars(0, length, _charBuffer, 0);
2498: return encodeUtf16String(_charBuffer, 0, length);
2499: } else {
2500: char[] ch = s.toCharArray();
2501: return encodeUtf16String(ch, 0, length);
2502: }
2503: }
2504:
2505: private void ensureEncodingBufferSizeForUtf16String(int length) {
2506: final int newLength = 2 * length;
2507:• if (_encodingBuffer.length < newLength) {
2508: _encodingBuffer = new byte[newLength];
2509: }
2510: }
2511:
2512: /**
2513: * Encode a string using the UTF-16 encoding.
2514: *
2515: * @param ch the array of characters.
2516: * @param offset the offset into the array of characters.
2517: * @param length the length of characters.
2518: */
2519: protected final int encodeUtf16String(char[] ch, int offset, int length) throws IOException {
2520: int byteLength = 0;
2521:
2522: // Make sure buffer is large enough
2523: ensureEncodingBufferSizeForUtf16String(length);
2524:
2525: final int n = offset + length;
2526:• for (int i = offset; i < n; i++) {
2527: final int c = (int) ch[i];
2528: _encodingBuffer[byteLength++] = (byte)(c >> 8);
2529: _encodingBuffer[byteLength++] = (byte)(c & 0xFF);
2530: }
2531:
2532: return byteLength;
2533: }
2534:
2535: /**
2536: * Obtain the prefix from a qualified name.
2537: *
2538: * @param qName the qualified name
2539: * @return the prefix, or "" if there is no prefix.
2540: */
2541: public static String getPrefixFromQualifiedName(String qName) {
2542: int i = qName.indexOf(':');
2543: String prefix = "";
2544:• if (i != -1) {
2545: prefix = qName.substring(0, i);
2546: }
2547: return prefix;
2548: }
2549:
2550: /**
2551: * Check if character array contains characters that are all white space.
2552: *
2553: * @param ch the character array
2554: * @param start the starting character index into the array to check from
2555: * @param length the number of characters to check
2556: * @return true if all characters are white space, false otherwise
2557: */
2558: public static boolean isWhiteSpace(final char[] ch, int start, final int length) {
2559:• if (!XMLChar.isSpace(ch[start])) return false;
2560:
2561: final int end = start + length;
2562:• while(++start < end && XMLChar.isSpace(ch[start]));
2563:
2564:• return start == end;
2565: }
2566:
2567: /**
2568: * Check if a String contains characters that are all white space.
2569: *
2570: * @param s the string
2571: * @return true if all characters are white space, false otherwise
2572: */
2573: public static boolean isWhiteSpace(String s) {
2574:• if (!XMLChar.isSpace(s.charAt(0))) return false;
2575:
2576: final int end = s.length();
2577: int start = 1;
2578:• while(start < end && XMLChar.isSpace(s.charAt(start++)));
2579:• return start == end;
2580: }
2581: }