1// Copyright 2018 The Wuffs Authors. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// https://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15// +build ignore 16 17package main 18 19// make-artificial.go makes test data in various formats. 20// 21// See test/data/artificial/*.make.txt for examples. 22// 23// Usage: go run make-artificial.go < foo.make.txt 24 25import ( 26 "bytes" 27 "compress/lzw" 28 "fmt" 29 "io/ioutil" 30 "os" 31 "strconv" 32 "strings" 33) 34 35type stateFunc func(line string) (stateFunc, error) 36 37type repeat struct { 38 count uint32 39 remaining string 40} 41 42var ( 43 state stateFunc 44 repeats []repeat 45 out []byte 46 formats = map[string]stateFunc{} 47) 48 49func main() { 50 if err := main1(); err != nil { 51 os.Stderr.WriteString(err.Error() + "\n") 52 os.Exit(1) 53 } 54} 55 56func main1() error { 57 stdin, err := ioutil.ReadAll(os.Stdin) 58 if err != nil { 59 return err 60 } 61 s := string(stdin) 62 for remaining := ""; len(s) > 0; s, remaining = remaining, "" { 63 if i := strings.IndexByte(s, '\n'); i >= 0 { 64 s, remaining = s[:i], s[i+1:] 65 } 66 s = strings.TrimSpace(s) 67 if s == "" || s[0] == '#' { 68 continue 69 } 70 71 if state == nil { 72 const m = "make " 73 if !strings.HasPrefix(s, m) { 74 return fmt.Errorf(`input must start with "make foo"`) 75 } 76 s = s[len(m):] 77 state = formats[s] 78 if state == nil { 79 return fmt.Errorf("unsupported format %q", s) 80 } 81 continue 82 } 83 84 const rep = "repeat " 85 if strings.HasPrefix(s, rep) { 86 args := s[len(rep):] 87 count, args, ok := parseNum(args) 88 if !ok || count <= 0 || args != "[" { 89 return fmt.Errorf("bad repeat command: %q", s) 90 } 91 repeats = append(repeats, repeat{ 92 count: count, 93 remaining: remaining, 94 }) 95 continue 96 } 97 98 if s == "]" { 99 if len(repeats) <= 0 { 100 return fmt.Errorf(`unbalanced close-repeat command: "]"`) 101 } 102 i := len(repeats) - 1 103 repeats[i].count-- 104 if repeats[i].count == 0 { 105 repeats = repeats[:i] 106 } else { 107 remaining = repeats[i].remaining 108 } 109 continue 110 } 111 112 state, err = state(s) 113 if err != nil { 114 return err 115 } 116 if state == nil { 117 return fmt.Errorf("bad state transition") 118 } 119 } 120 121 if state == nil { 122 return fmt.Errorf("no 'make' line") 123 } else { 124 state, err = state("") 125 if err != nil { 126 return err 127 } 128 } 129 130 _, err = os.Stdout.Write(out) 131 return err 132} 133 134// ---- 135 136func appendU16LE(b []byte, u uint16) []byte { 137 return append(b, uint8(u), uint8(u>>8)) 138} 139 140func log2(u uint32) (i int32) { 141 for i, pow := uint32(0), uint32(1); i < 32; i, pow = i+1, pow<<1 { 142 if u == pow { 143 return int32(i) 144 } 145 if u < pow { 146 break 147 } 148 } 149 return -1 150} 151 152func parseHex(s string) (num uint32, remaining string, ok bool) { 153 if i := strings.IndexByte(s, ' '); i >= 0 { 154 s, remaining = s[:i], s[i+1:] 155 for len(remaining) > 0 && remaining[0] == ' ' { 156 remaining = remaining[1:] 157 } 158 } 159 160 if len(s) < 2 || s[0] != '0' || s[1] != 'x' { 161 return 0, "", false 162 } 163 s = s[2:] 164 165 u, err := strconv.ParseUint(s, 16, 32) 166 if err != nil { 167 return 0, "", false 168 } 169 return uint32(u), remaining, true 170} 171 172func parseNum(s string) (num uint32, remaining string, ok bool) { 173 if i := strings.IndexByte(s, ' '); i >= 0 { 174 s, remaining = s[:i], s[i+1:] 175 for len(remaining) > 0 && remaining[0] == ' ' { 176 remaining = remaining[1:] 177 } 178 } 179 180 u, err := strconv.ParseUint(s, 10, 32) 181 if err != nil { 182 return 0, "", false 183 } 184 return uint32(u), remaining, true 185} 186 187func reverse(x uint32, n uint32) uint32 { 188 x = uint32(reverse8[0xFF&(x>>0)])<<24 | 189 uint32(reverse8[0xFF&(x>>8)])<<16 | 190 uint32(reverse8[0xFF&(x>>16)])<<8 | 191 uint32(reverse8[0xFF&(x>>24)])<<0 192 return x >> (32 - n) 193} 194 195var reverse8 = [256]byte{ 196 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, // 0x00 - 0x07 197 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, // 0x08 - 0x0F 198 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, // 0x10 - 0x17 199 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, // 0x18 - 0x1F 200 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, // 0x20 - 0x27 201 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, // 0x28 - 0x2F 202 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, // 0x30 - 0x37 203 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, // 0x38 - 0x3F 204 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, // 0x40 - 0x47 205 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, // 0x48 - 0x4F 206 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, // 0x50 - 0x57 207 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, // 0x58 - 0x5F 208 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, // 0x60 - 0x67 209 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, // 0x68 - 0x6F 210 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, // 0x70 - 0x77 211 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, // 0x78 - 0x7F 212 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, // 0x80 - 0x87 213 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, // 0x88 - 0x8F 214 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, // 0x90 - 0x97 215 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, // 0x98 - 0x9F 216 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, // 0xA0 - 0xA7 217 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, // 0xA8 - 0xAF 218 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, // 0xB0 - 0xB7 219 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, // 0xB8 - 0xBF 220 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, // 0xC0 - 0xC7 221 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, // 0xC8 - 0xCF 222 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, // 0xD0 - 0xD7 223 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, // 0xD8 - 0xDF 224 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, // 0xE0 - 0xE7 225 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, // 0xE8 - 0xEF 226 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, // 0xF0 - 0xF7 227 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF, // 0xF8 - 0xFF 228} 229 230// ---- 231 232func init() { 233 formats["deflate"] = stateDeflate 234} 235 236var deflateCodeOrder = [19]uint32{ 237 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, 238} 239 240type deflateHuffmanTable map[uint32]string 241 242var deflateGlobals struct { 243 bncData []byte 244 stream deflateBitStream 245 246 // Dynamic Huffman state. 247 whichHuffman uint32 248 // 0=Unused, 1=CodeLength, 2=Literal/Length, 3=Distance. 249 huffmans [4]deflateHuffmanTable 250 251 // DHH (Dynamic Huffman, inside a Huffman table) state. 252 prevLine string 253 etcetera bool 254} 255 256func deflateGlobalsClearDynamicHuffmanState() { 257 deflateGlobals.whichHuffman = 0 258 deflateGlobals.huffmans = [4]deflateHuffmanTable{} 259 deflateGlobals.prevLine = "" 260 deflateGlobals.etcetera = false 261} 262 263func deflateGlobalsCountCodes() (numLCodes uint32, numDCodes uint32, numCLCodeLengths uint32, retErr error) { 264 for k := range deflateGlobals.huffmans[2] { 265 if numLCodes < (k + 1) { 266 numLCodes = (k + 1) 267 } 268 } 269 270 for k := range deflateGlobals.huffmans[3] { 271 if numDCodes < (k + 1) { 272 numDCodes = (k + 1) 273 } 274 } 275 276 for k := range deflateGlobals.huffmans[1] { 277 if (k < 0) || (18 < k) { 278 return 0, 0, 0, fmt.Errorf("bad CodeLength: %d", k) 279 } 280 } 281 for i := len(deflateCodeOrder) - 1; i >= 0; i-- { 282 cl := deflateCodeOrder[i] 283 if _, ok := deflateGlobals.huffmans[1][cl]; ok { 284 numCLCodeLengths = uint32(i + 1) 285 break 286 } 287 } 288 if numCLCodeLengths < 4 { 289 numCLCodeLengths = 4 290 } 291 292 return numLCodes, numDCodes, numCLCodeLengths, nil 293} 294 295func deflateGlobalsWriteDynamicHuffmanTables() error { 296 g := &deflateGlobals 297 numLCodes, numDCodes, numCLCodeLengths, err := deflateGlobalsCountCodes() 298 if err != nil { 299 return err 300 } 301 if (numLCodes < 257) || (257+31 < numLCodes) { 302 return fmt.Errorf("bad numLCodes: %d", numLCodes) 303 } 304 g.stream.writeBits(numLCodes-257, 5) 305 if (numDCodes < 1) || (1+31 < numDCodes) { 306 return fmt.Errorf("bad numDCodes: %d", numDCodes) 307 } 308 g.stream.writeBits(numDCodes-1, 5) 309 if (numCLCodeLengths < 4) || (4+15 < numCLCodeLengths) { 310 return fmt.Errorf("bad numCLCodeLengths: %d", numCLCodeLengths) 311 } 312 g.stream.writeBits(numCLCodeLengths-4, 4) 313 314 // Write the Huffman table for CodeLength. 315 { 316 for i := uint32(0); i < numCLCodeLengths; i++ { 317 n := len(g.huffmans[1][deflateCodeOrder[i]]) 318 g.stream.writeBits(uint32(n), 3) 319 } 320 for i := numCLCodeLengths; i < uint32(len(deflateCodeOrder)); i++ { 321 n := len(g.huffmans[1][deflateCodeOrder[i]]) 322 if n > 0 { 323 return fmt.Errorf("short numCLCodeLengths: %d", numCLCodeLengths) 324 } 325 } 326 } 327 328 // Write the Huffman tables for Literal/Length and Distance. 329 { 330 numZeroes := uint32(0) 331 for i := uint32(0); i < numLCodes+numDCodes; i++ { 332 codeLen := uint32(0) 333 if i < numLCodes { 334 codeLen = uint32(len(g.huffmans[2][i])) 335 } else { 336 codeLen = uint32(len(g.huffmans[3][i-numLCodes])) 337 } 338 if codeLen == 0 { 339 numZeroes++ 340 continue 341 } 342 343 if err := deflateGlobalsWriteDynamicHuffmanZeroes(numZeroes); err != nil { 344 return err 345 } 346 numZeroes = 0 347 348 codeLenCode := g.huffmans[1][codeLen] 349 if codeLenCode == "" { 350 return fmt.Errorf("no code for code-length %d", codeLen) 351 } 352 deflateGlobalsWriteDynamicHuffmanBits(g.huffmans[1][codeLen]) 353 } 354 if err := deflateGlobalsWriteDynamicHuffmanZeroes(numZeroes); err != nil { 355 return err 356 } 357 } 358 359 return nil 360} 361 362func deflateGlobalsWriteDynamicHuffmanZeroes(numZeroes uint32) error { 363 g := &deflateGlobals 364 if numZeroes == 0 { 365 return nil 366 } 367 368 if s := g.huffmans[1][18]; s != "" { 369 for numZeroes >= 11 { 370 extra := numZeroes - 11 371 if extra > 127 { 372 extra = 127 373 } 374 deflateGlobalsWriteDynamicHuffmanBits(s) 375 g.stream.writeBits(extra, 7) 376 numZeroes -= 11 + extra 377 } 378 } 379 380 if s := g.huffmans[1][17]; s != "" { 381 for numZeroes >= 3 { 382 extra := numZeroes - 3 383 if extra > 7 { 384 extra = 7 385 } 386 deflateGlobalsWriteDynamicHuffmanBits(s) 387 g.stream.writeBits(extra, 3) 388 numZeroes -= 3 + extra 389 } 390 } 391 392 if s := g.huffmans[1][0]; s != "" { 393 for ; numZeroes > 0; numZeroes-- { 394 deflateGlobalsWriteDynamicHuffmanBits(s) 395 } 396 } 397 398 if numZeroes > 0 { 399 return fmt.Errorf("could not write a run of zero-valued code lengths") 400 } 401 return nil 402} 403 404func deflateGlobalsWriteDynamicHuffmanBits(s string) { 405 g := &deflateGlobals 406 for i := 0; i < len(s); i++ { 407 g.stream.writeBits(uint32(s[i]&1), 1) 408 } 409} 410 411func parseDeflateWhichHuffman(s string) (num uint32, remaining string, ok bool) { 412 if i := strings.IndexByte(s, ' '); i >= 0 { 413 s, remaining = s[:i], s[i+1:] 414 for len(remaining) > 0 && remaining[0] == ' ' { 415 remaining = remaining[1:] 416 } 417 } 418 419 switch s { 420 case "CodeLength": 421 return 1, remaining, true 422 case "Literal/Length": 423 return 2, remaining, true 424 case "Distance": 425 return 3, remaining, true 426 } 427 return 0, "", false 428} 429 430func stateDeflate(line string) (stateFunc, error) { 431 g := &deflateGlobals 432 const ( 433 cmdB = "bytes " 434 cmdBDH = "blockDynamicHuffman " 435 cmdBFH = "blockFixedHuffman " 436 cmdBNC = "blockNoCompression " 437 ) 438 bits := uint32(0) 439 s := "" 440 441 retState := stateFunc(nil) 442 switch { 443 case line == "": 444 g.stream.flush() 445 return stateDeflate, nil 446 447 case strings.HasPrefix(line, cmdB): 448 s := line[len(cmdB):] 449 for s != "" { 450 x, ok := uint32(0), false 451 x, s, ok = parseHex(s) 452 if !ok { 453 return nil, fmt.Errorf("bad stateDeflate command: %q", line) 454 } 455 out = append(out, uint8(x)) 456 } 457 return stateDeflate, nil 458 459 case strings.HasPrefix(line, cmdBNC): 460 s = line[len(cmdBNC):] 461 retState = stateDeflateNoCompression 462 bits |= 0 << 1 463 case strings.HasPrefix(line, cmdBFH): 464 s = line[len(cmdBFH):] 465 retState = stateDeflateFixedHuffman 466 bits |= 1 << 1 467 case strings.HasPrefix(line, cmdBDH): 468 s = line[len(cmdBDH):] 469 retState = stateDeflateDynamicHuffman 470 bits |= 2 << 1 471 default: 472 return nil, fmt.Errorf("bad stateDeflate command: %q", line) 473 } 474 475 switch s { 476 case "(final) {": 477 bits |= 1 478 case "(nonFinal) {": 479 // No-op. 480 default: 481 return nil, fmt.Errorf("bad stateDeflate command: %q", line) 482 } 483 484 g.stream.writeBits(bits, 3) 485 return retState, nil 486} 487 488func stateDeflateNoCompression(line string) (stateFunc, error) { 489 g := &deflateGlobals 490 if line == "}" { 491 if len(g.bncData) > 0xFFFF { 492 return nil, fmt.Errorf("bncData is too long") 493 } 494 n := uint32(len(g.bncData)) 495 g.stream.flush() 496 g.stream.writeBits(n, 16) 497 g.stream.writeBits(0xFFFF-n, 16) 498 g.stream.writeBytes(g.bncData) 499 g.bncData = g.bncData[:0] 500 return stateDeflate, nil 501 } 502 503 if lit, ok := deflateParseLiteral(line); ok { 504 g.bncData = append(g.bncData, lit...) 505 return stateDeflateNoCompression, nil 506 } 507 508 return nil, fmt.Errorf("bad blockNoCompression command: %q", line) 509} 510 511func stateDeflateFixedHuffman(line string) (stateFunc, error) { 512 g := &deflateGlobals 513 if line == "}" { 514 return stateDeflate, nil 515 } 516 517 if line == "endOfBlock" { 518 g.stream.writeBits(0, 7) 519 return stateDeflateFixedHuffman, nil 520 } 521 522 if lit, ok := deflateParseLiteral(line); ok { 523 for i := 0; i < len(lit); i++ { 524 g.stream.writeFixedHuffmanLCode(uint32(lit[i])) 525 } 526 return stateDeflateFixedHuffman, nil 527 } 528 529 if line == "len 3 distCode 31" { 530 lCode, lExtra, lNExtra := deflateEncodeLength(3) 531 g.stream.writeFixedHuffmanLCode(lCode) 532 g.stream.writeBits(lExtra, lNExtra) 533 dCode, dExtra, dNExtra := uint32(31), uint32(0), uint32(0) 534 g.stream.writeBits(reverse(dCode, 5), 5) 535 g.stream.writeBits(dExtra, dNExtra) 536 return stateDeflateFixedHuffman, nil 537 } 538 539 if l, d, ok := deflateParseLenDist(line); ok { 540 lCode, lExtra, lNExtra := deflateEncodeLength(l) 541 g.stream.writeFixedHuffmanLCode(lCode) 542 g.stream.writeBits(lExtra, lNExtra) 543 dCode, dExtra, dNExtra := deflateEncodeDistance(d) 544 g.stream.writeBits(reverse(dCode, 5), 5) 545 g.stream.writeBits(dExtra, dNExtra) 546 return stateDeflateFixedHuffman, nil 547 } 548 549 return nil, fmt.Errorf("bad stateDeflateFixedHuffman command: %q", line) 550} 551 552func stateDeflateDynamicHuffman(line string) (stateFunc, error) { 553 g := &deflateGlobals 554 const ( 555 cmdH = "huffman " 556 ) 557 switch { 558 case line == "}": 559 deflateGlobalsClearDynamicHuffmanState() 560 return stateDeflate, nil 561 562 case strings.HasPrefix(line, cmdH): 563 s := line[len(cmdH):] 564 n, s, ok := parseDeflateWhichHuffman(s) 565 if !ok { 566 break 567 } 568 g.whichHuffman = n 569 return stateDeflateDynamicHuffmanHuffman, nil 570 } 571 572 if lit, ok := deflateParseLiteral(line); ok { 573 for i := 0; i < len(lit); i++ { 574 s := g.huffmans[2][uint32(lit[i])] 575 if s == "" { 576 return nil, fmt.Errorf("no code for literal %q (%d)", lit[i:i+1], lit[i]) 577 } 578 deflateGlobalsWriteDynamicHuffmanBits(s) 579 } 580 return stateDeflateDynamicHuffman, nil 581 582 } else if l, d, ok := deflateParseLenDist(line); ok { 583 if (l != 3) || (d != 2) { 584 return nil, fmt.Errorf("TODO: support len/dist pairs for dynamic Huffman blocks") 585 } 586 // len 3 is code 257, with no extra bits. 587 if s := g.huffmans[2][257]; s != "" { 588 deflateGlobalsWriteDynamicHuffmanBits(s) 589 } else { 590 return nil, fmt.Errorf("no code for literal/length symbol 257") 591 } 592 // dist 2 is code 1, with no extra bits. 593 if s := g.huffmans[3][1]; s != "" { 594 deflateGlobalsWriteDynamicHuffmanBits(s) 595 } else { 596 return nil, fmt.Errorf("no code for distance symbol 2") 597 } 598 return stateDeflateDynamicHuffman, nil 599 600 } else if line == "endOfBlock" { 601 s := g.huffmans[2][256] 602 if s == "" { 603 return nil, fmt.Errorf("no code for end-of-block (256)") 604 } 605 deflateGlobalsWriteDynamicHuffmanBits(s) 606 return stateDeflateDynamicHuffman, nil 607 } 608 609 return nil, fmt.Errorf("bad stateDeflateDynamicHuffman command: %q", line) 610} 611 612func stateDeflateDynamicHuffmanHuffman(line string) (stateFunc, error) { 613 g := &deflateGlobals 614outer: 615 switch { 616 case line == "}": 617 g.whichHuffman = 0 618 g.prevLine = "" 619 g.etcetera = false 620 621 // If we have all three Huffman tables, write them. 622 for i := 1; ; i++ { 623 if i == 4 { 624 if err := deflateGlobalsWriteDynamicHuffmanTables(); err != nil { 625 return nil, err 626 } 627 break 628 } 629 if g.huffmans[i] == nil { 630 break 631 } 632 } 633 634 return stateDeflateDynamicHuffman, nil 635 636 case line == "etcetera": 637 g.etcetera = true 638 return stateDeflateDynamicHuffmanHuffman, nil 639 640 default: 641 s := line 642 n, s, ok := parseNum(s) 643 if !ok || s == "" { 644 break 645 } 646 for i := 0; i < len(s); i++ { 647 if c := s[i]; c != '0' && c != '1' { 648 break outer 649 } 650 } 651 if (len(s) < 1) || (15 < len(s)) { 652 return nil, fmt.Errorf("%q code length, %d, is out of range", s, len(s)) 653 } 654 655 if g.etcetera { 656 g.etcetera = false 657 n0, s0, ok := parseNum(g.prevLine) 658 if !ok { 659 return nil, fmt.Errorf("bad etcetera command") 660 } 661 if err := stateDeflateDHHEtcetera(n0, s0, n, s); err != nil { 662 return nil, err 663 } 664 } 665 666 if g.huffmans[g.whichHuffman] == nil { 667 g.huffmans[g.whichHuffman] = deflateHuffmanTable{} 668 } 669 g.huffmans[g.whichHuffman][n] = s 670 g.prevLine = line 671 return stateDeflateDynamicHuffmanHuffman, nil 672 } 673 674 return nil, fmt.Errorf("bad stateDeflateDynamicHuffmanHuffman command: %q", line) 675} 676 677// stateDeflateDHHEtcetera expands the "etcetera" line in: 678// 679// 0 0000 680// 1 0001 681// etcetera 682// 7 0111 683// 684// to produce the implicit lines: 685// 686// 0 0000 687// 1 0001 688// 2 0010 689// 3 0011 690// 4 0100 691// 5 0101 692// 6 0110 693// 7 0111 694func stateDeflateDHHEtcetera(n0 uint32, s0 string, n1 uint32, s1 string) error { 695 b := []byte(s0) 696 if !incrementBitstring(b) { 697 return fmt.Errorf("etcetera: could not increment bitstring") 698 } 699 for n := n0 + 1; n < n1; n++ { 700 line := fmt.Sprintf("%d %s", n, b) 701 if _, err := stateDeflateDynamicHuffmanHuffman(line); err != nil { 702 return err 703 } 704 if !incrementBitstring(b) { 705 return fmt.Errorf("etcetera: could not increment bitstring") 706 } 707 } 708 if string(b) != s1 { 709 return fmt.Errorf("etcetera: final bitstring: got %q, want %q", b, s1) 710 } 711 return nil 712} 713 714func incrementBitstring(b []byte) (ok bool) { 715 for i := len(b) - 1; i >= 0; i-- { 716 switch b[i] { 717 case '0': 718 b[i] = '1' 719 return true 720 case '1': 721 b[i] = '0' 722 default: 723 return false 724 } 725 } 726 return false 727} 728 729type deflateBitStream struct { 730 bits uint32 731 nBits uint32 // Always within [0, 7]. 732} 733 734// writeBits writes the low n bits of b to z. 735func (z *deflateBitStream) writeBits(b uint32, n uint32) { 736 if n > 24 { 737 panic("writeBits: n is too large") 738 } 739 z.bits |= b << z.nBits 740 z.nBits += n 741 for z.nBits >= 8 { 742 out = append(out, uint8(z.bits)) 743 z.bits >>= 8 744 z.nBits -= 8 745 } 746} 747 748func (z *deflateBitStream) writeBytes(b []byte) { 749 z.flush() 750 out = append(out, b...) 751} 752 753func (z *deflateBitStream) writeFixedHuffmanLCode(lCode uint32) { 754 switch { 755 case lCode < 144: // 0b._0011_0000 through 0b._1011_1111 756 lCode += 0x030 757 z.writeBits(reverse(lCode, 8), 8) 758 case lCode < 256: // 0b1_1001_0000 through 0b1_1111_1111 759 lCode += 0x190 - 144 760 z.writeBits(reverse(lCode, 9), 9) 761 case lCode < 280: // 0b._.000_0000 through 0b._.001_0111 762 lCode -= 256 - 0x000 763 z.writeBits(reverse(lCode, 7), 7) 764 default: // 0b._1100_0000 through 0b._1100_0111 765 lCode -= 280 - 0x0C0 766 z.writeBits(reverse(lCode, 8), 8) 767 } 768} 769 770func (z *deflateBitStream) flush() { 771 if z.nBits > 0 { 772 out = append(out, uint8(z.bits)) 773 z.bits = 0 774 z.nBits = 0 775 } 776} 777 778func deflateEncodeLength(l uint32) (code uint32, extra uint32, nExtra uint32) { 779 switch { 780 case l < 3: 781 // No-op. 782 case l < 11: 783 l -= 3 784 return (l >> 0) + 257, l & 0x0000, 0 785 case l < 19: 786 l -= 11 787 return (l >> 1) + 265, l & 0x0001, 1 788 case l < 35: 789 l -= 19 790 return (l >> 2) + 269, l & 0x0003, 2 791 case l < 67: 792 l -= 35 793 return (l >> 3) + 273, l & 0x0007, 3 794 case l < 131: 795 l -= 67 796 return (l >> 4) + 277, l & 0x000F, 4 797 case l < 258: 798 l -= 131 799 return (l >> 5) + 281, l & 0x001F, 5 800 case l == 258: 801 return 285, 0, 0 802 } 803 panic(fmt.Sprintf("deflateEncodeLength: l=%d", l)) 804} 805 806func deflateEncodeDistance(d uint32) (code uint32, extra uint32, nExtra uint32) { 807 switch { 808 case d < 1: 809 // No-op. 810 case d < 5: 811 d -= 1 812 return (d >> 0) + 0, d & 0x0000, 0 813 case d < 9: 814 d -= 5 815 return (d >> 1) + 4, d & 0x0001, 1 816 case d < 17: 817 d -= 9 818 return (d >> 2) + 6, d & 0x0003, 2 819 case d < 33: 820 d -= 17 821 return (d >> 3) + 8, d & 0x0007, 3 822 case d < 65: 823 d -= 33 824 return (d >> 4) + 10, d & 0x000F, 4 825 case d < 129: 826 d -= 65 827 return (d >> 5) + 12, d & 0x001F, 5 828 case d < 257: 829 d -= 129 830 return (d >> 6) + 14, d & 0x003F, 6 831 case d < 513: 832 d -= 257 833 return (d >> 7) + 16, d & 0x007F, 7 834 case d < 1025: 835 d -= 513 836 return (d >> 8) + 18, d & 0x00FF, 8 837 case d < 2049: 838 d -= 1025 839 return (d >> 9) + 20, d & 0x01FF, 9 840 case d < 4097: 841 d -= 2049 842 return (d >> 10) + 22, d & 0x03FF, 10 843 case d < 8193: 844 d -= 4097 845 return (d >> 11) + 24, d & 0x07FF, 11 846 case d < 16385: 847 d -= 8193 848 return (d >> 12) + 26, d & 0x0FFF, 12 849 case d < 32769: 850 d -= 16385 851 return (d >> 13) + 28, d & 0x1FFF, 13 852 } 853 panic(fmt.Sprintf("deflateEncodeDistance: d=%d", d)) 854} 855 856func deflateParseLiteral(s string) (lit string, ok bool) { 857 // TODO: support "\xAB" escape codes in the script? 858 const ( 859 prefix = `literal "` 860 suffix = `"` 861 ) 862 if strings.HasPrefix(s, prefix) { 863 s = s[len(prefix):] 864 if strings.HasSuffix(s, suffix) { 865 return s[:len(s)-len(suffix)], true 866 } 867 } 868 return "", false 869} 870 871func deflateParseLenDist(line string) (l uint32, d uint32, ok bool) { 872 const ( 873 lStr = "len " 874 dStr = "dist " 875 ) 876 s := line 877 if strings.HasPrefix(s, lStr) { 878 s = s[len(lStr):] 879 if l, s, ok := parseNum(s); ok && 3 <= l && l <= 258 { 880 if strings.HasPrefix(s, dStr) { 881 s = s[len(dStr):] 882 if d, s, ok := parseNum(s); ok && 1 <= d && d <= 32768 && s == "" { 883 return l, d, true 884 } 885 } 886 } 887 } 888 return 0, 0, false 889} 890 891// ---- 892 893func init() { 894 formats["gif"] = stateGif 895} 896 897var gifGlobals struct { 898 imageWidth uint32 899 imageHeight uint32 900 imageBackgroundColorIndex uint32 901 902 frameInterlaced bool 903 frameLeft uint32 904 frameTop uint32 905 frameWidth uint32 906 frameHeight uint32 907 908 globalPalette [][4]uint8 909 localPalette [][4]uint8 910} 911 912func stateGif(line string) (stateFunc, error) { 913 const ( 914 cmdB = "bytes " 915 cmdGC = "graphicControl " 916 cmdL = "lzw " 917 cmdLC = "loopCount " 918 ) 919outer: 920 switch { 921 case line == "": 922 return stateGif, nil 923 924 case line == "frame {": 925 gifGlobals.frameInterlaced = false 926 gifGlobals.frameLeft = 0 927 gifGlobals.frameTop = 0 928 gifGlobals.frameWidth = 0 929 gifGlobals.frameHeight = 0 930 gifGlobals.localPalette = nil 931 out = append(out, 0x2C) 932 return stateGifFrame, nil 933 934 case line == "header": 935 out = append(out, "GIF89a"...) 936 return stateGif, nil 937 938 case line == "image {": 939 return stateGifImage, nil 940 941 case line == "trailer": 942 out = append(out, 0x3B) 943 return stateGif, nil 944 945 case strings.HasPrefix(line, cmdB): 946 s := line[len(cmdB):] 947 for s != "" { 948 x, ok := uint32(0), false 949 x, s, ok = parseHex(s) 950 if !ok { 951 break outer 952 } 953 out = append(out, uint8(x)) 954 } 955 return stateGif, nil 956 957 case strings.HasPrefix(line, cmdGC): 958 s := line[len(cmdGC):] 959 960 flags := uint8(0) 961 if i := strings.IndexByte(s, ' '); i < 0 { 962 break 963 } else { 964 switch s[:i] { 965 case "animationDisposalNone": 966 flags |= 0x00 967 case "animationDisposalRestoreBackground": 968 flags |= 0x08 969 case "animationDisposalRestorePrevious": 970 flags |= 0x0C 971 default: 972 break outer 973 } 974 s = s[i+1:] 975 } 976 977 if !strings.HasSuffix(s, "ms") { 978 break 979 } 980 s = s[:len(s)-2] 981 duration, s, ok := parseNum(s) 982 if !ok || s != "" { 983 break 984 } 985 duration /= 10 // GIF's unit of time is 10ms. 986 987 transparentIndex := uint8(0) 988 989 out = append(out, 990 0x21, 0xF9, 0x04, 991 flags, 992 uint8(duration>>0), 993 uint8(duration>>8), 994 transparentIndex, 995 0x00, 996 ) 997 return stateGif, nil 998 999 case strings.HasPrefix(line, cmdL): 1000 s := line[len(cmdL):] 1001 litWidth, s, ok := parseNum(s) 1002 if !ok || litWidth < 2 || 8 < litWidth { 1003 break 1004 } 1005 out = append(out, uint8(litWidth)) 1006 1007 uncompressed := []byte(nil) 1008 for s != "" { 1009 x := uint32(0) 1010 x, s, ok = parseHex(s) 1011 if !ok { 1012 break outer 1013 } 1014 uncompressed = append(uncompressed, uint8(x)) 1015 } 1016 1017 buf := bytes.NewBuffer(nil) 1018 w := lzw.NewWriter(buf, lzw.LSB, int(litWidth)) 1019 if _, err := w.Write(uncompressed); err != nil { 1020 return nil, err 1021 } 1022 if err := w.Close(); err != nil { 1023 return nil, err 1024 } 1025 compressed := buf.Bytes() 1026 1027 for len(compressed) > 0 { 1028 if len(compressed) <= 0xFF { 1029 out = append(out, uint8(len(compressed))) 1030 out = append(out, compressed...) 1031 compressed = nil 1032 } else { 1033 out = append(out, 0xFF) 1034 out = append(out, compressed[:0xFF]...) 1035 compressed = compressed[0xFF:] 1036 } 1037 } 1038 out = append(out, 0x00) 1039 return stateGif, nil 1040 1041 case strings.HasPrefix(line, cmdLC): 1042 s := line[len(cmdLC):] 1043 loopCount, _, ok := parseNum(s) 1044 if !ok || 0xFFFF < loopCount { 1045 break 1046 } 1047 out = append(out, 1048 0x21, // Extension Introducer. 1049 0xFF, // Application Extension Label. 1050 0x0B, // Block Size. 1051 ) 1052 out = append(out, "NETSCAPE2.0"...) 1053 out = append(out, 1054 0x03, // Block Size. 1055 0x01, // Magic Number. 1056 byte(loopCount), 1057 byte(loopCount>>8), 1058 0x00, // Block Terminator. 1059 ) 1060 return stateGif, nil 1061 } 1062 1063 return nil, fmt.Errorf("bad stateGif command: %q", line) 1064} 1065 1066func stateGifImage(line string) (stateFunc, error) { 1067 g := &gifGlobals 1068 if line == "}" { 1069 out = appendU16LE(out, uint16(g.imageWidth)) 1070 out = appendU16LE(out, uint16(g.imageHeight)) 1071 if g.globalPalette == nil { 1072 out = append(out, 0x00) 1073 } else if n := log2(uint32(len(g.globalPalette))); n < 2 || 8 < n { 1074 return nil, fmt.Errorf("bad len(g.globalPalette): %d", len(g.globalPalette)) 1075 } else { 1076 out = append(out, 0x80|uint8(n-1)) 1077 } 1078 out = append(out, uint8(g.imageBackgroundColorIndex)) 1079 out = append(out, 0x00) 1080 for _, x := range g.globalPalette { 1081 out = append(out, x[0], x[1], x[2]) 1082 } 1083 return stateGif, nil 1084 } 1085 1086 const ( 1087 cmdBCI = "backgroundColorIndex " 1088 cmdIWH = "imageWidthHeight " 1089 cmdP = "palette {" 1090 ) 1091 switch { 1092 case strings.HasPrefix(line, cmdBCI): 1093 s := line[len(cmdBCI):] 1094 if i, _, ok := parseNum(s); ok { 1095 g.imageBackgroundColorIndex = i 1096 } 1097 return stateGifImage, nil 1098 1099 case strings.HasPrefix(line, cmdIWH): 1100 s := line[len(cmdIWH):] 1101 if w, s, ok := parseNum(s); ok { 1102 if h, _, ok := parseNum(s); ok { 1103 g.imageWidth = w 1104 g.imageHeight = h 1105 return stateGifImage, nil 1106 } 1107 } 1108 1109 case strings.HasPrefix(line, cmdP): 1110 return stateGifImagePalette, nil 1111 } 1112 1113 return nil, fmt.Errorf("bad stateGifImage command: %q", line) 1114} 1115 1116func stateGifFrame(line string) (stateFunc, error) { 1117 g := &gifGlobals 1118 if line == "}" { 1119 out = appendU16LE(out, uint16(g.frameLeft)) 1120 out = appendU16LE(out, uint16(g.frameTop)) 1121 out = appendU16LE(out, uint16(g.frameWidth)) 1122 out = appendU16LE(out, uint16(g.frameHeight)) 1123 flags := byte(0x00) 1124 if g.frameInterlaced { 1125 flags |= 0x40 1126 } 1127 if g.localPalette == nil { 1128 out = append(out, flags) 1129 } else if n := log2(uint32(len(g.localPalette))); n < 2 || 8 < n { 1130 return nil, fmt.Errorf("bad len(g.localPalette): %d", len(g.localPalette)) 1131 } else { 1132 out = append(out, flags|0x80|uint8(n-1)) 1133 } 1134 for _, x := range g.localPalette { 1135 out = append(out, x[0], x[1], x[2]) 1136 } 1137 return stateGif, nil 1138 } 1139 1140 const ( 1141 cmdFLTWH = "frameLeftTopWidthHeight " 1142 cmdP = "palette {" 1143 ) 1144 switch { 1145 case line == "interlaced": 1146 g.frameInterlaced = true 1147 return stateGifFrame, nil 1148 1149 case strings.HasPrefix(line, cmdFLTWH): 1150 s := line[len(cmdFLTWH):] 1151 if l, s, ok := parseNum(s); ok { 1152 if t, s, ok := parseNum(s); ok { 1153 if w, s, ok := parseNum(s); ok { 1154 if h, _, ok := parseNum(s); ok { 1155 g.frameLeft = l 1156 g.frameTop = t 1157 g.frameWidth = w 1158 g.frameHeight = h 1159 return stateGifFrame, nil 1160 } 1161 } 1162 } 1163 } 1164 1165 case strings.HasPrefix(line, cmdP): 1166 return stateGifFramePalette, nil 1167 } 1168 1169 return nil, fmt.Errorf("bad stateGifFrame command: %q", line) 1170} 1171 1172func stateGifImagePalette(line string) (stateFunc, error) { 1173 g := &gifGlobals 1174 if line == "}" { 1175 return stateGifImage, nil 1176 } 1177 1178 s := line 1179 if rgb0, s, ok := parseHex(s); ok { 1180 if rgb1, s, ok := parseHex(s); ok { 1181 if rgb2, _, ok := parseHex(s); ok { 1182 g.globalPalette = append(g.globalPalette, 1183 [4]uint8{uint8(rgb0), uint8(rgb1), uint8(rgb2), 0xFF}) 1184 return stateGifImagePalette, nil 1185 } 1186 } 1187 } 1188 1189 return nil, fmt.Errorf("bad stateGifImagePalette command: %q", line) 1190} 1191 1192func stateGifFramePalette(line string) (stateFunc, error) { 1193 g := &gifGlobals 1194 if line == "}" { 1195 return stateGifFrame, nil 1196 } 1197 1198 s := line 1199 if rgb0, s, ok := parseHex(s); ok { 1200 if rgb1, s, ok := parseHex(s); ok { 1201 if rgb2, _, ok := parseHex(s); ok { 1202 g.localPalette = append(g.localPalette, 1203 [4]uint8{uint8(rgb0), uint8(rgb1), uint8(rgb2), 0xFF}) 1204 return stateGifFramePalette, nil 1205 } 1206 } 1207 } 1208 1209 return nil, fmt.Errorf("bad stateGifFramePalette command: %q", line) 1210} 1211