1 module hunt.http.codec.http.hpack.Huffman; 2 3 import hunt.Exceptions; 4 import hunt.text.Common; 5 import hunt.util.StringBuilder; 6 7 import hunt.io.ByteBuffer; 8 import hunt.logging; 9 10 /** 11 */ 12 class Huffman 13 { 14 15 // dfmt off 16 // Appendix C: Huffman Codes 17 // http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#appendix-C 18 enum int[][] CODES = 19 [ 20 /* ( 0) |11111111|11000 */ [0x1ff8,13], 21 /* ( 1) |11111111|11111111|1011000 */ [0x7fffd8,23], 22 /* ( 2) |11111111|11111111|11111110|0010 */ [0xfffffe2,28], 23 /* ( 3) |11111111|11111111|11111110|0011 */ [0xfffffe3,28], 24 /* ( 4) |11111111|11111111|11111110|0100 */ [0xfffffe4,28], 25 /* ( 5) |11111111|11111111|11111110|0101 */ [0xfffffe5,28], 26 /* ( 6) |11111111|11111111|11111110|0110 */ [0xfffffe6,28], 27 /* ( 7) |11111111|11111111|11111110|0111 */ [0xfffffe7,28], 28 /* ( 8) |11111111|11111111|11111110|1000 */ [0xfffffe8,28], 29 /* ( 9) |11111111|11111111|11101010 */ [0xffffea,24], 30 /* ( 10) |11111111|11111111|11111111|111100 */ [0x3ffffffc,30], 31 /* ( 11) |11111111|11111111|11111110|1001 */ [0xfffffe9,28], 32 /* ( 12) |11111111|11111111|11111110|1010 */ [0xfffffea,28], 33 /* ( 13) |11111111|11111111|11111111|111101 */ [0x3ffffffd,30], 34 /* ( 14) |11111111|11111111|11111110|1011 */ [0xfffffeb,28], 35 /* ( 15) |11111111|11111111|11111110|1100 */ [0xfffffec,28], 36 /* ( 16) |11111111|11111111|11111110|1101 */ [0xfffffed,28], 37 /* ( 17) |11111111|11111111|11111110|1110 */ [0xfffffee,28], 38 /* ( 18) |11111111|11111111|11111110|1111 */ [0xfffffef,28], 39 /* ( 19) |11111111|11111111|11111111|0000 */ [0xffffff0,28], 40 /* ( 20) |11111111|11111111|11111111|0001 */ [0xffffff1,28], 41 /* ( 21) |11111111|11111111|11111111|0010 */ [0xffffff2,28], 42 /* ( 22) |11111111|11111111|11111111|111110 */ [0x3ffffffe,30], 43 /* ( 23) |11111111|11111111|11111111|0011 */ [0xffffff3,28], 44 /* ( 24) |11111111|11111111|11111111|0100 */ [0xffffff4,28], 45 /* ( 25) |11111111|11111111|11111111|0101 */ [0xffffff5,28], 46 /* ( 26) |11111111|11111111|11111111|0110 */ [0xffffff6,28], 47 /* ( 27) |11111111|11111111|11111111|0111 */ [0xffffff7,28], 48 /* ( 28) |11111111|11111111|11111111|1000 */ [0xffffff8,28], 49 /* ( 29) |11111111|11111111|11111111|1001 */ [0xffffff9,28], 50 /* ( 30) |11111111|11111111|11111111|1010 */ [0xffffffa,28], 51 /* ( 31) |11111111|11111111|11111111|1011 */ [0xffffffb,28], 52 /*' ' ( 32) |010100 */ [0x14, 6], 53 /*'!' ( 33) |11111110|00 */ [0x3f8,10], 54 /*'"' ( 34) |11111110|01 */ [0x3f9,10], 55 /*'#' ( 35) |11111111|1010 */ [0xffa,12], 56 /*'$' ( 36) |11111111|11001 */ [0x1ff9,13], 57 /*'%' ( 37) |010101 */ [0x15, 6], 58 /*'&' ( 38) |11111000 */ [0xf8, 8], 59 /*''' ( 39) |11111111|010 */ [0x7fa,11], 60 /*'(' ( 40) |11111110|10 */ [0x3fa,10], 61 /*')' ( 41) |11111110|11 */ [0x3fb,10], 62 /*'*' ( 42) |11111001 */ [0xf9, 8], 63 /*'+' ( 43) |11111111|011 */ [0x7fb,11], 64 /*',' ( 44) |11111010 */ [0xfa, 8], 65 /*'-' ( 45) |010110 */ [0x16, 6], 66 /*'.' ( 46) |010111 */ [0x17, 6], 67 /*'/' ( 47) |011000 */ [0x18, 6], 68 /*'0' ( 48) |00000 */ [0x0, 5], 69 /*'1' ( 49) |00001 */ [0x1, 5], 70 /*'2' ( 50) |00010 */ [0x2, 5], 71 /*'3' ( 51) |011001 */ [0x19, 6], 72 /*'4' ( 52) |011010 */ [0x1a, 6], 73 /*'5' ( 53) |011011 */ [0x1b, 6], 74 /*'6' ( 54) |011100 */ [0x1c, 6], 75 /*'7' ( 55) |011101 */ [0x1d, 6], 76 /*'8' ( 56) |011110 */ [0x1e, 6], 77 /*'9' ( 57) |011111 */ [0x1f, 6], 78 /*':' ( 58) |1011100 */ [0x5c, 7], 79 /*';' ( 59) |11111011 */ [0xfb, 8], 80 /*'<' ( 60) |11111111|1111100 */ [0x7ffc,15], 81 /*'=' ( 61) |100000 */ [0x20, 6], 82 /*'>' ( 62) |11111111|1011 */ [0xffb,12], 83 /*'?' ( 63) |11111111|00 */ [0x3fc,10], 84 /*'@' ( 64) |11111111|11010 */ [0x1ffa,13], 85 /*'A' ( 65) |100001 */ [0x21, 6], 86 /*'B' ( 66) |1011101 */ [0x5d, 7], 87 /*'C' ( 67) |1011110 */ [0x5e, 7], 88 /*'D' ( 68) |1011111 */ [0x5f, 7], 89 /*'E' ( 69) |1100000 */ [0x60, 7], 90 /*'F' ( 70) |1100001 */ [0x61, 7], 91 /*'G' ( 71) |1100010 */ [0x62, 7], 92 /*'H' ( 72) |1100011 */ [0x63, 7], 93 /*'I' ( 73) |1100100 */ [0x64, 7], 94 /*'J' ( 74) |1100101 */ [0x65, 7], 95 /*'K' ( 75) |1100110 */ [0x66, 7], 96 /*'L' ( 76) |1100111 */ [0x67, 7], 97 /*'M' ( 77) |1101000 */ [0x68, 7], 98 /*'N' ( 78) |1101001 */ [0x69, 7], 99 /*'O' ( 79) |1101010 */ [0x6a, 7], 100 /*'P' ( 80) |1101011 */ [0x6b, 7], 101 /*'Q' ( 81) |1101100 */ [0x6c, 7], 102 /*'R' ( 82) |1101101 */ [0x6d, 7], 103 /*'S' ( 83) |1101110 */ [0x6e, 7], 104 /*'T' ( 84) |1101111 */ [0x6f, 7], 105 /*'U' ( 85) |1110000 */ [0x70, 7], 106 /*'V' ( 86) |1110001 */ [0x71, 7], 107 /*'W' ( 87) |1110010 */ [0x72, 7], 108 /*'X' ( 88) |11111100 */ [0xfc, 8], 109 /*'Y' ( 89) |1110011 */ [0x73, 7], 110 /*'Z' ( 90) |11111101 */ [0xfd, 8], 111 /*'[' ( 91) |11111111|11011 */ [0x1ffb,13], 112 /*'\' ( 92) |11111111|11111110|000 */ [0x7fff0,19], 113 /*']' ( 93) |11111111|11100 */ [0x1ffc,13], 114 /*'^' ( 94) |11111111|111100 */ [0x3ffc,14], 115 /*'_' ( 95) |100010 */ [0x22, 6], 116 /*'`' ( 96) |11111111|1111101 */ [0x7ffd,15], 117 /*'a' ( 97) |00011 */ [0x3, 5], 118 /*'b' ( 98) |100011 */ [0x23, 6], 119 /*'c' ( 99) |00100 */ [0x4, 5], 120 /*'d' (100) |100100 */ [0x24, 6], 121 /*'e' (101) |00101 */ [0x5, 5], 122 /*'f' (102) |100101 */ [0x25, 6], 123 /*'g' (103) |100110 */ [0x26, 6], 124 /*'h' (104) |100111 */ [0x27, 6], 125 /*'i' (105) |00110 */ [0x6, 5], 126 /*'j' (106) |1110100 */ [0x74, 7], 127 /*'k' (107) |1110101 */ [0x75, 7], 128 /*'l' (108) |101000 */ [0x28, 6], 129 /*'m' (109) |101001 */ [0x29, 6], 130 /*'n' (110) |101010 */ [0x2a, 6], 131 /*'o' (111) |00111 */ [0x7, 5], 132 /*'p' (112) |101011 */ [0x2b, 6], 133 /*'q' (113) |1110110 */ [0x76, 7], 134 /*'r' (114) |101100 */ [0x2c, 6], 135 /*'s' (115) |01000 */ [0x8, 5], 136 /*'t' (116) |01001 */ [0x9, 5], 137 /*'u' (117) |101101 */ [0x2d, 6], 138 /*'v' (118) |1110111 */ [0x77, 7], 139 /*'w' (119) |1111000 */ [0x78, 7], 140 /*'x' (120) |1111001 */ [0x79, 7], 141 /*'y' (121) |1111010 */ [0x7a, 7], 142 /*'z' (122) |1111011 */ [0x7b, 7], 143 /*'[' (123) |11111111|1111110 */ [0x7ffe,15], 144 /*'|' (124) |11111111|100 */ [0x7fc,11], 145 /*']' (125) |11111111|111101 */ [0x3ffd,14], 146 /*'~' (126) |11111111|11101 */ [0x1ffd,13], 147 /* (127) |11111111|11111111|11111111|1100 */ [0xffffffc,28], 148 /* (128) |11111111|11111110|0110 */ [0xfffe6,20], 149 /* (129) |11111111|11111111|010010 */ [0x3fffd2,22], 150 /* (130) |11111111|11111110|0111 */ [0xfffe7,20], 151 /* (131) |11111111|11111110|1000 */ [0xfffe8,20], 152 /* (132) |11111111|11111111|010011 */ [0x3fffd3,22], 153 /* (133) |11111111|11111111|010100 */ [0x3fffd4,22], 154 /* (134) |11111111|11111111|010101 */ [0x3fffd5,22], 155 /* (135) |11111111|11111111|1011001 */ [0x7fffd9,23], 156 /* (136) |11111111|11111111|010110 */ [0x3fffd6,22], 157 /* (137) |11111111|11111111|1011010 */ [0x7fffda,23], 158 /* (138) |11111111|11111111|1011011 */ [0x7fffdb,23], 159 /* (139) |11111111|11111111|1011100 */ [0x7fffdc,23], 160 /* (140) |11111111|11111111|1011101 */ [0x7fffdd,23], 161 /* (141) |11111111|11111111|1011110 */ [0x7fffde,23], 162 /* (142) |11111111|11111111|11101011 */ [0xffffeb,24], 163 /* (143) |11111111|11111111|1011111 */ [0x7fffdf,23], 164 /* (144) |11111111|11111111|11101100 */ [0xffffec,24], 165 /* (145) |11111111|11111111|11101101 */ [0xffffed,24], 166 /* (146) |11111111|11111111|010111 */ [0x3fffd7,22], 167 /* (147) |11111111|11111111|1100000 */ [0x7fffe0,23], 168 /* (148) |11111111|11111111|11101110 */ [0xffffee,24], 169 /* (149) |11111111|11111111|1100001 */ [0x7fffe1,23], 170 /* (150) |11111111|11111111|1100010 */ [0x7fffe2,23], 171 /* (151) |11111111|11111111|1100011 */ [0x7fffe3,23], 172 /* (152) |11111111|11111111|1100100 */ [0x7fffe4,23], 173 /* (153) |11111111|11111110|11100 */ [0x1fffdc,21], 174 /* (154) |11111111|11111111|011000 */ [0x3fffd8,22], 175 /* (155) |11111111|11111111|1100101 */ [0x7fffe5,23], 176 /* (156) |11111111|11111111|011001 */ [0x3fffd9,22], 177 /* (157) |11111111|11111111|1100110 */ [0x7fffe6,23], 178 /* (158) |11111111|11111111|1100111 */ [0x7fffe7,23], 179 /* (159) |11111111|11111111|11101111 */ [0xffffef,24], 180 /* (160) |11111111|11111111|011010 */ [0x3fffda,22], 181 /* (161) |11111111|11111110|11101 */ [0x1fffdd,21], 182 /* (162) |11111111|11111110|1001 */ [0xfffe9,20], 183 /* (163) |11111111|11111111|011011 */ [0x3fffdb,22], 184 /* (164) |11111111|11111111|011100 */ [0x3fffdc,22], 185 /* (165) |11111111|11111111|1101000 */ [0x7fffe8,23], 186 /* (166) |11111111|11111111|1101001 */ [0x7fffe9,23], 187 /* (167) |11111111|11111110|11110 */ [0x1fffde,21], 188 /* (168) |11111111|11111111|1101010 */ [0x7fffea,23], 189 /* (169) |11111111|11111111|011101 */ [0x3fffdd,22], 190 /* (170) |11111111|11111111|011110 */ [0x3fffde,22], 191 /* (171) |11111111|11111111|11110000 */ [0xfffff0,24], 192 /* (172) |11111111|11111110|11111 */ [0x1fffdf,21], 193 /* (173) |11111111|11111111|011111 */ [0x3fffdf,22], 194 /* (174) |11111111|11111111|1101011 */ [0x7fffeb,23], 195 /* (175) |11111111|11111111|1101100 */ [0x7fffec,23], 196 /* (176) |11111111|11111111|00000 */ [0x1fffe0,21], 197 /* (177) |11111111|11111111|00001 */ [0x1fffe1,21], 198 /* (178) |11111111|11111111|100000 */ [0x3fffe0,22], 199 /* (179) |11111111|11111111|00010 */ [0x1fffe2,21], 200 /* (180) |11111111|11111111|1101101 */ [0x7fffed,23], 201 /* (181) |11111111|11111111|100001 */ [0x3fffe1,22], 202 /* (182) |11111111|11111111|1101110 */ [0x7fffee,23], 203 /* (183) |11111111|11111111|1101111 */ [0x7fffef,23], 204 /* (184) |11111111|11111110|1010 */ [0xfffea,20], 205 /* (185) |11111111|11111111|100010 */ [0x3fffe2,22], 206 /* (186) |11111111|11111111|100011 */ [0x3fffe3,22], 207 /* (187) |11111111|11111111|100100 */ [0x3fffe4,22], 208 /* (188) |11111111|11111111|1110000 */ [0x7ffff0,23], 209 /* (189) |11111111|11111111|100101 */ [0x3fffe5,22], 210 /* (190) |11111111|11111111|100110 */ [0x3fffe6,22], 211 /* (191) |11111111|11111111|1110001 */ [0x7ffff1,23], 212 /* (192) |11111111|11111111|11111000|00 */ [0x3ffffe0,26], 213 /* (193) |11111111|11111111|11111000|01 */ [0x3ffffe1,26], 214 /* (194) |11111111|11111110|1011 */ [0xfffeb,20], 215 /* (195) |11111111|11111110|001 */ [0x7fff1,19], 216 /* (196) |11111111|11111111|100111 */ [0x3fffe7,22], 217 /* (197) |11111111|11111111|1110010 */ [0x7ffff2,23], 218 /* (198) |11111111|11111111|101000 */ [0x3fffe8,22], 219 /* (199) |11111111|11111111|11110110|0 */ [0x1ffffec,25], 220 /* (200) |11111111|11111111|11111000|10 */ [0x3ffffe2,26], 221 /* (201) |11111111|11111111|11111000|11 */ [0x3ffffe3,26], 222 /* (202) |11111111|11111111|11111001|00 */ [0x3ffffe4,26], 223 /* (203) |11111111|11111111|11111011|110 */ [0x7ffffde,27], 224 /* (204) |11111111|11111111|11111011|111 */ [0x7ffffdf,27], 225 /* (205) |11111111|11111111|11111001|01 */ [0x3ffffe5,26], 226 /* (206) |11111111|11111111|11110001 */ [0xfffff1,24], 227 /* (207) |11111111|11111111|11110110|1 */ [0x1ffffed,25], 228 /* (208) |11111111|11111110|010 */ [0x7fff2,19], 229 /* (209) |11111111|11111111|00011 */ [0x1fffe3,21], 230 /* (210) |11111111|11111111|11111001|10 */ [0x3ffffe6,26], 231 /* (211) |11111111|11111111|11111100|000 */ [0x7ffffe0,27], 232 /* (212) |11111111|11111111|11111100|001 */ [0x7ffffe1,27], 233 /* (213) |11111111|11111111|11111001|11 */ [0x3ffffe7,26], 234 /* (214) |11111111|11111111|11111100|010 */ [0x7ffffe2,27], 235 /* (215) |11111111|11111111|11110010 */ [0xfffff2,24], 236 /* (216) |11111111|11111111|00100 */ [0x1fffe4,21], 237 /* (217) |11111111|11111111|00101 */ [0x1fffe5,21], 238 /* (218) |11111111|11111111|11111010|00 */ [0x3ffffe8,26], 239 /* (219) |11111111|11111111|11111010|01 */ [0x3ffffe9,26], 240 /* (220) |11111111|11111111|11111111|1101 */ [0xffffffd,28], 241 /* (221) |11111111|11111111|11111100|011 */ [0x7ffffe3,27], 242 /* (222) |11111111|11111111|11111100|100 */ [0x7ffffe4,27], 243 /* (223) |11111111|11111111|11111100|101 */ [0x7ffffe5,27], 244 /* (224) |11111111|11111110|1100 */ [0xfffec,20], 245 /* (225) |11111111|11111111|11110011 */ [0xfffff3,24], 246 /* (226) |11111111|11111110|1101 */ [0xfffed,20], 247 /* (227) |11111111|11111111|00110 */ [0x1fffe6,21], 248 /* (228) |11111111|11111111|101001 */ [0x3fffe9,22], 249 /* (229) |11111111|11111111|00111 */ [0x1fffe7,21], 250 /* (230) |11111111|11111111|01000 */ [0x1fffe8,21], 251 /* (231) |11111111|11111111|1110011 */ [0x7ffff3,23], 252 /* (232) |11111111|11111111|101010 */ [0x3fffea,22], 253 /* (233) |11111111|11111111|101011 */ [0x3fffeb,22], 254 /* (234) |11111111|11111111|11110111|0 */ [0x1ffffee,25], 255 /* (235) |11111111|11111111|11110111|1 */ [0x1ffffef,25], 256 /* (236) |11111111|11111111|11110100 */ [0xfffff4,24], 257 /* (237) |11111111|11111111|11110101 */ [0xfffff5,24], 258 /* (238) |11111111|11111111|11111010|10 */ [0x3ffffea,26], 259 /* (239) |11111111|11111111|1110100 */ [0x7ffff4,23], 260 /* (240) |11111111|11111111|11111010|11 */ [0x3ffffeb,26], 261 /* (241) |11111111|11111111|11111100|110 */ [0x7ffffe6,27], 262 /* (242) |11111111|11111111|11111011|00 */ [0x3ffffec,26], 263 /* (243) |11111111|11111111|11111011|01 */ [0x3ffffed,26], 264 /* (244) |11111111|11111111|11111100|111 */ [0x7ffffe7,27], 265 /* (245) |11111111|11111111|11111101|000 */ [0x7ffffe8,27], 266 /* (246) |11111111|11111111|11111101|001 */ [0x7ffffe9,27], 267 /* (247) |11111111|11111111|11111101|010 */ [0x7ffffea,27], 268 /* (248) |11111111|11111111|11111101|011 */ [0x7ffffeb,27], 269 /* (249) |11111111|11111111|11111111|1110 */ [0xffffffe,28], 270 /* (250) |11111111|11111111|11111101|100 */ [0x7ffffec,27], 271 /* (251) |11111111|11111111|11111101|101 */ [0x7ffffed,27], 272 /* (252) |11111111|11111111|11111101|110 */ [0x7ffffee,27], 273 /* (253) |11111111|11111111|11111101|111 */ [0x7ffffef,27], 274 /* (254) |11111111|11111111|11111110|000 */ [0x7fffff0,27], 275 /* (255) |11111111|11111111|11111011|10 */ [0x3ffffee,26], 276 /*EOS (256) |11111111|11111111|11111111|111111 */ [0x3fffffff,30], 277 ]; 278 279 // dfmt on 280 281 __gshared int[][] LCCODES; // = new int[CODES.length][]; 282 283 // Huffman decode tree stored in a flattened char array for good 284 // locality of reference. 285 __gshared ubyte[] tree; 286 __gshared ubyte[] rowsym; 287 __gshared byte[] rowbits; 288 289 // Build the Huffman lookup tree and LC TABLE 290 shared static this() 291 { 292 // System.arraycopy(CODES,0,LCCODES,0,CODES.length); 293 LCCODES = new int[][CODES.length]; 294 for (size_t i=0; i<CODES.length; i++) 295 { 296 LCCODES[i] = CODES[i].dup; 297 } 298 299 for (size_t i='A';i<='Z';i++) 300 LCCODES[i]=LCCODES['a'+i-'A']; 301 302 int r=0; 303 for (size_t i=0;i<CODES.length;i++) 304 r+=(CODES[i][1]+7)/8; 305 tree=new ubyte[r*256]; 306 rowsym=new ubyte[r]; 307 rowbits=new byte[r]; 308 309 r=0; 310 for (int sym = 0; sym < CODES.length; sym++) 311 { 312 int code = CODES[sym][0]; 313 int len = CODES[sym][1]; 314 315 int current = 0; 316 317 while (len > 8) 318 { 319 len -= 8; 320 int i = ((code >>> len) & 0xFF); 321 322 int t=current*256+i; 323 current = tree[t]; 324 if (current == 0) 325 { 326 tree[t] = cast(char)++r; 327 current=r; 328 } 329 } 330 331 int terminal = ++r; 332 rowsym[r]=cast(char)sym; 333 int b = len & 0x07; 334 int terminalBits = b == 0?8:b; 335 336 rowbits[r]=cast(byte)terminalBits; 337 int shift = 8 - len; 338 int start = current*256 + ((code << shift) & 0xFF); 339 int end = start + (1<<shift); 340 for (int i = start; i < end; i++) 341 tree[i]=cast(char)terminal; 342 } 343 } 344 345 static string decode(ByteBuffer buffer) 346 { 347 return decode(buffer,buffer.remaining()); 348 } 349 350 static string decode(ByteBuffer buffer,int length) 351 { 352 StringBuilder r = new StringBuilder(length*2); 353 int node = 0; 354 int current = 0; 355 int bits = 0; 356 357 byte[] array = buffer.array(); 358 int position=buffer.position(); 359 int start=buffer.arrayOffset()+position; 360 int end=start+length; 361 buffer.position(position+length); 362 363 for (int i=start; i<end; i++) 364 { 365 int b = array[i]&0xFF; 366 current = (current << 8) | b; 367 bits += 8; 368 while (bits >= 8) 369 { 370 int c = (current >>> (bits - 8)) & 0xFF; 371 node = tree[node*256+c]; 372 if (rowbits[node]!=0) 373 { 374 // terminal node 375 // tracef("xx=>%s", rowsym[node]); 376 r.append(rowsym[node]); 377 bits -= rowbits[node]; 378 node = 0; 379 } 380 else 381 { 382 // non-terminal node 383 bits -= 8; 384 } 385 } 386 } 387 388 // tracef("bits=>%d", bits); 389 while (bits > 0) 390 { 391 int c = (current << (8 - bits)) & 0xFF; 392 // tracef("node=%d, c=%d", node, c); 393 node = tree[node*256+c]; 394 // tracef("rowbits[%d]=>%d", node, rowbits[node]); 395 if (rowbits[node]==0 || rowbits[node] > bits) 396 break; 397 398 // tracef("xx=>%s", rowsym[node]); 399 r.append(rowsym[node]); 400 bits -= rowbits[node]; 401 node = 0; 402 } 403 404 return r.toString(); 405 } 406 407 static int octetsNeeded(string s) 408 { 409 return octetsNeeded(CODES,s); 410 } 411 412 static void encode(ByteBuffer buffer,string s) 413 { 414 encode(CODES,buffer,s); 415 } 416 417 static int octetsNeededLC(string s) 418 { 419 return octetsNeeded(LCCODES,s); 420 } 421 422 static void encodeLC(ByteBuffer buffer, string s) 423 { 424 encode(LCCODES,buffer,s); 425 } 426 427 private static int octetsNeeded( int[][] table,string s) 428 { 429 int needed=0; 430 for (size_t i=0;i< s.length;i++) 431 { 432 char c=s[i]; 433 if (c>=128 || c<' ') 434 throw new IllegalArgumentException(""); 435 needed += table[c][1]; 436 } 437 438 return (needed+7) / 8; 439 } 440 441 private static void encode( int[][] table,ByteBuffer buffer,string s) 442 { 443 long current = 0; 444 int n = 0; 445 446 byte[] array = buffer.array(); 447 int p=buffer.arrayOffset()+buffer.position(); 448 449 for (size_t i=0;i<s.length;i++) 450 { 451 char c=s[i]; 452 if (c>=128 || c<' ') 453 throw new IllegalArgumentException(""); 454 int code = table[c][0]; 455 int bits = table[c][1]; 456 457 current <<= bits; 458 current |= code; 459 n += bits; 460 461 while (n >= 8) 462 { 463 n -= 8; 464 array[p++]=cast(byte)(current >> n); 465 } 466 } 467 468 if (n > 0) 469 { 470 current <<= (8 - n); 471 current |= (0xFF >>> n); 472 array[p++]=cast(byte)current; 473 } 474 475 buffer.position(p-buffer.arrayOffset()); 476 } 477 478 }