ranger-compiler 3.4.0 → 3.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,675 @@
1
+ ; SPDX-License-Identifier: MIT
2
+
3
+ ; Inflate.rgr - DEFLATE decompression (RFC 1951)
4
+ ; Used to decompress ZIP files with compression method 8
5
+
6
+ Import "ZipBuffer.rgr"
7
+
8
+ class InflateHuffmanTable {
9
+ def counts:[int] ; Count of codes at each bit length (index 0-15)
10
+ def symbols:[int] ; Symbol for each code
11
+ def maxBits:int 0
12
+
13
+ Constructor () {
14
+ ; Initialize counts array (16 entries for bit lengths 0-15)
15
+ def i 0
16
+ while (i < 16) {
17
+ push counts 0
18
+ i = i + 1
19
+ }
20
+ }
21
+
22
+ fn build:void (lengths:[int] numSymbols:int) {
23
+ ; Build Huffman table from code lengths
24
+ ; lengths[i] = bit length for symbol i
25
+
26
+ ; Count codes of each length
27
+ def i 0
28
+ while (i < 16) {
29
+ set counts i 0
30
+ i = i + 1
31
+ }
32
+
33
+ i = 0
34
+ while (i < numSymbols) {
35
+ def len:int (itemAt lengths i)
36
+ if (len > 0) {
37
+ def cnt:int (itemAt counts len)
38
+ set counts len (cnt + 1)
39
+ if (len > maxBits) {
40
+ maxBits = len
41
+ }
42
+ }
43
+ i = i + 1
44
+ }
45
+
46
+ ; Generate offsets for sorting symbols by code length
47
+ def offsets:[int]
48
+ def offset:int 0
49
+ i = 0
50
+ while (i < 16) {
51
+ push offsets offset
52
+ def cnt:int (itemAt counts i)
53
+ offset = offset + cnt
54
+ i = i + 1
55
+ }
56
+
57
+ ; Sort symbols by code length, preserving order within same length
58
+ ; Allocate symbols array
59
+ i = 0
60
+ while (i < numSymbols) {
61
+ push symbols 0
62
+ i = i + 1
63
+ }
64
+
65
+ i = 0
66
+ while (i < numSymbols) {
67
+ def len:int (itemAt lengths i)
68
+ if (len > 0) {
69
+ def off:int (itemAt offsets len)
70
+ set symbols off i
71
+ set offsets len (off + 1)
72
+ }
73
+ i = i + 1
74
+ }
75
+ }
76
+
77
+ fn decode:int (reader:InflateBitReader) {
78
+ ; Decode next symbol using this Huffman table
79
+ def code:int 0
80
+ def first:int 0
81
+ def index:int 0
82
+
83
+ def len:int 1
84
+ while (len <= maxBits) {
85
+ def bit:int (reader.readBit())
86
+ code = (code * 2) + bit
87
+ def count:int (itemAt counts len)
88
+ if ((code - first) < count) {
89
+ return (itemAt symbols (index + code - first))
90
+ }
91
+ index = index + count
92
+ first = (first + count) * 2
93
+ len = len + 1
94
+ }
95
+
96
+ ; Invalid code
97
+ return -1
98
+ }
99
+ }
100
+
101
+ class InflateBitReader {
102
+ def data:buffer (buffer_alloc 0)
103
+ def bytePos:int 0
104
+ def bitPos:int 0 ; Bits remaining in current byte (0 = need new byte)
105
+ def currentByte:int 0
106
+ def dataLength:int 0
107
+
108
+ Constructor () {
109
+ }
110
+
111
+ fn init:void (buf:buffer offset:int length:int) {
112
+ data = buf
113
+ bytePos = offset
114
+ dataLength = offset + length
115
+ bitPos = 0
116
+ currentByte = 0
117
+ }
118
+
119
+ fn readBit:int () {
120
+ ; DEFLATE reads bits LSB first (unlike JPEG which is MSB first)
121
+ if (bitPos == 0) {
122
+ if (bytePos >= dataLength) {
123
+ return 0
124
+ }
125
+ currentByte = (buffer_get data bytePos)
126
+ bytePos = bytePos + 1
127
+ bitPos = 8
128
+ }
129
+
130
+ def bit:int (bit_and currentByte 1)
131
+ currentByte = (bit_shr currentByte 1)
132
+ bitPos = bitPos - 1
133
+ return bit
134
+ }
135
+
136
+ fn readBits:int (count:int) {
137
+ ; Read multiple bits, LSB first
138
+ def result:int 0
139
+ def multiplier:int 1
140
+ def i 0
141
+ while (i < count) {
142
+ def bit:int (this.readBit())
143
+ result = result + (bit * multiplier)
144
+ multiplier = multiplier * 2
145
+ i = i + 1
146
+ }
147
+ return result
148
+ }
149
+
150
+ fn alignToByte:void () {
151
+ ; Skip remaining bits in current byte
152
+ bitPos = 0
153
+ }
154
+
155
+ fn readByte:int () {
156
+ this.alignToByte()
157
+ if (bytePos >= dataLength) {
158
+ return 0
159
+ }
160
+ def b:int (buffer_get data bytePos)
161
+ bytePos = bytePos + 1
162
+ return b
163
+ }
164
+
165
+ fn readUint16LE:int () {
166
+ def b0:int (this.readByte())
167
+ def b1:int (this.readByte())
168
+ return (b0 + (b1 * 256))
169
+ }
170
+
171
+ fn getBytePosition:int () {
172
+ return bytePos
173
+ }
174
+
175
+ fn isEOF:boolean () {
176
+ return ((bytePos >= dataLength) && (bitPos == 0))
177
+ }
178
+ }
179
+
180
+ class Inflate {
181
+ def input:buffer (buffer_alloc 0)
182
+ def reader:InflateBitReader (new InflateBitReader())
183
+
184
+ ; Flat random-access output buffer (doubles on growth). LZ77 back-references
185
+ ; read directly from already-decoded bytes — no per-byte reconstruction.
186
+ def outBuf:buffer (buffer_alloc 0)
187
+ def outLen:int 0
188
+ def outCap:int 0
189
+
190
+ ; Fixed Huffman tables (built once)
191
+ def fixedLitLen:InflateHuffmanTable (new InflateHuffmanTable())
192
+ def fixedDist:InflateHuffmanTable (new InflateHuffmanTable())
193
+ def fixedTablesBuilt:boolean false
194
+
195
+ ; Length and distance extra bits tables
196
+ def lengthBase:[int]
197
+ def lengthExtra:[int]
198
+ def distBase:[int]
199
+ def distExtra:[int]
200
+
201
+ Constructor () {
202
+ this.buildLengthDistTables()
203
+ }
204
+
205
+ fn resetOutput:void (hint:int) {
206
+ def cap:int hint
207
+ if (cap < 4096) {
208
+ cap = 4096
209
+ }
210
+ outBuf = (buffer_alloc cap)
211
+ outCap = cap
212
+ outLen = 0
213
+ }
214
+
215
+ fn ensureCapacity:void (extra:int) {
216
+ def need:int (outLen + extra)
217
+ if (need <= outCap) {
218
+ return
219
+ }
220
+ def newCap:int (outCap * 2)
221
+ if (newCap < need) {
222
+ newCap = need
223
+ }
224
+ def grown:buffer (buffer_alloc newCap)
225
+ buffer_copy grown 0 outBuf 0 outLen
226
+ outBuf = grown
227
+ outCap = newCap
228
+ }
229
+
230
+ fn pushByte:void (b:int) {
231
+ this.ensureCapacity(1)
232
+ buffer_set outBuf outLen b
233
+ outLen = (outLen + 1)
234
+ }
235
+
236
+ fn finalOutput:buffer () {
237
+ def size:int outLen
238
+ def result:buffer (buffer_alloc size)
239
+ buffer_copy result 0 outBuf 0 size
240
+ return result
241
+ }
242
+
243
+ fn buildLengthDistTables:void () {
244
+ ; Length codes 257-285 -> lengths 3-258
245
+ ; Base lengths for codes 257-285
246
+ def bases:[int]
247
+ push bases 3 ; 257
248
+ push bases 4 ; 258
249
+ push bases 5 ; 259
250
+ push bases 6 ; 260
251
+ push bases 7 ; 261
252
+ push bases 8 ; 262
253
+ push bases 9 ; 263
254
+ push bases 10 ; 264
255
+ push bases 11 ; 265
256
+ push bases 13 ; 266
257
+ push bases 15 ; 267
258
+ push bases 17 ; 268
259
+ push bases 19 ; 269
260
+ push bases 23 ; 270
261
+ push bases 27 ; 271
262
+ push bases 31 ; 272
263
+ push bases 35 ; 273
264
+ push bases 43 ; 274
265
+ push bases 51 ; 275
266
+ push bases 59 ; 276
267
+ push bases 67 ; 277
268
+ push bases 83 ; 278
269
+ push bases 99 ; 279
270
+ push bases 115 ; 280
271
+ push bases 131 ; 281
272
+ push bases 163 ; 282
273
+ push bases 195 ; 283
274
+ push bases 227 ; 284
275
+ push bases 258 ; 285
276
+ lengthBase = bases
277
+
278
+ ; Extra bits for length codes 257-285
279
+ def extras:[int]
280
+ push extras 0 ; 257
281
+ push extras 0 ; 258
282
+ push extras 0 ; 259
283
+ push extras 0 ; 260
284
+ push extras 0 ; 261
285
+ push extras 0 ; 262
286
+ push extras 0 ; 263
287
+ push extras 0 ; 264
288
+ push extras 1 ; 265
289
+ push extras 1 ; 266
290
+ push extras 1 ; 267
291
+ push extras 1 ; 268
292
+ push extras 2 ; 269
293
+ push extras 2 ; 270
294
+ push extras 2 ; 271
295
+ push extras 2 ; 272
296
+ push extras 3 ; 273
297
+ push extras 3 ; 274
298
+ push extras 3 ; 275
299
+ push extras 3 ; 276
300
+ push extras 4 ; 277
301
+ push extras 4 ; 278
302
+ push extras 4 ; 279
303
+ push extras 4 ; 280
304
+ push extras 5 ; 281
305
+ push extras 5 ; 282
306
+ push extras 5 ; 283
307
+ push extras 5 ; 284
308
+ push extras 0 ; 285
309
+ lengthExtra = extras
310
+
311
+ ; Distance codes 0-29 -> distances 1-32768
312
+ def dBases:[int]
313
+ push dBases 1
314
+ push dBases 2
315
+ push dBases 3
316
+ push dBases 4
317
+ push dBases 5
318
+ push dBases 7
319
+ push dBases 9
320
+ push dBases 13
321
+ push dBases 17
322
+ push dBases 25
323
+ push dBases 33
324
+ push dBases 49
325
+ push dBases 65
326
+ push dBases 97
327
+ push dBases 129
328
+ push dBases 193
329
+ push dBases 257
330
+ push dBases 385
331
+ push dBases 513
332
+ push dBases 769
333
+ push dBases 1025
334
+ push dBases 1537
335
+ push dBases 2049
336
+ push dBases 3073
337
+ push dBases 4097
338
+ push dBases 6145
339
+ push dBases 8193
340
+ push dBases 12289
341
+ push dBases 16385
342
+ push dBases 24577
343
+ distBase = dBases
344
+
345
+ def dExtras:[int]
346
+ push dExtras 0
347
+ push dExtras 0
348
+ push dExtras 0
349
+ push dExtras 0
350
+ push dExtras 1
351
+ push dExtras 1
352
+ push dExtras 2
353
+ push dExtras 2
354
+ push dExtras 3
355
+ push dExtras 3
356
+ push dExtras 4
357
+ push dExtras 4
358
+ push dExtras 5
359
+ push dExtras 5
360
+ push dExtras 6
361
+ push dExtras 6
362
+ push dExtras 7
363
+ push dExtras 7
364
+ push dExtras 8
365
+ push dExtras 8
366
+ push dExtras 9
367
+ push dExtras 9
368
+ push dExtras 10
369
+ push dExtras 10
370
+ push dExtras 11
371
+ push dExtras 11
372
+ push dExtras 12
373
+ push dExtras 12
374
+ push dExtras 13
375
+ push dExtras 13
376
+ distExtra = dExtras
377
+ }
378
+
379
+ fn buildFixedTables:void () {
380
+ if fixedTablesBuilt {
381
+ return
382
+ }
383
+
384
+ ; Build fixed literal/length Huffman table
385
+ ; Literals 0-143: 8-bit codes
386
+ ; Literals 144-255: 9-bit codes
387
+ ; End-of-block 256: 7-bit code
388
+ ; Lengths 257-279: 7-bit codes
389
+ ; Lengths 280-287: 8-bit codes
390
+ def lengths:[int]
391
+ def i 0
392
+ while (i < 144) {
393
+ push lengths 8
394
+ i = i + 1
395
+ }
396
+ while (i < 256) {
397
+ push lengths 9
398
+ i = i + 1
399
+ }
400
+ while (i < 280) {
401
+ push lengths 7
402
+ i = i + 1
403
+ }
404
+ while (i < 288) {
405
+ push lengths 8
406
+ i = i + 1
407
+ }
408
+ fixedLitLen.build(lengths 288)
409
+
410
+ ; Build fixed distance Huffman table (all 5-bit codes)
411
+ def distLengths:[int]
412
+ i = 0
413
+ while (i < 32) {
414
+ push distLengths 5
415
+ i = i + 1
416
+ }
417
+ fixedDist.build(distLengths 32)
418
+
419
+ fixedTablesBuilt = true
420
+ }
421
+
422
+ fn decompress:buffer (data:buffer) {
423
+ return this.decompressFrom(data 0)
424
+ }
425
+
426
+ ; Inflate a DEFLATE stream that begins at `offset` inside `data` and
427
+ ; runs until BFINAL. Used by ZIP (offset 0, known length) and by Git
428
+ ; zlib wrappers (offset after the 2-byte CMF/FLG, unknown length —
429
+ ; the next object in a pack starts at inputPos after this returns).
430
+ fn decompressFrom:buffer (data:buffer offset:int) {
431
+ input = data
432
+ def dataLen:int (buffer_length data)
433
+ def from:int offset
434
+ if (from < 0) {
435
+ from = 0
436
+ }
437
+ if (from > dataLen) {
438
+ from = dataLen
439
+ }
440
+ def rest:int (dataLen - from)
441
+ ; Deflate typically expands 2-4x; start generous to avoid re-growth.
442
+ this.resetOutput(rest * 4)
443
+ reader.init(data from rest)
444
+
445
+ this.buildFixedTables()
446
+
447
+ def finalBlock:boolean false
448
+ while ((false == finalBlock)) {
449
+ ; Read block header
450
+ def bfinal:int (reader.readBit())
451
+ def btype:int (reader.readBits(2))
452
+
453
+ finalBlock = (bfinal == 1)
454
+
455
+ if (btype == 0) {
456
+ ; Stored block (no compression)
457
+ this.decompressStored()
458
+ }
459
+ if (btype == 1) {
460
+ ; Fixed Huffman codes
461
+ this.decompressHuffman(fixedLitLen fixedDist)
462
+ }
463
+ if (btype == 2) {
464
+ ; Dynamic Huffman codes
465
+ this.decompressDynamic()
466
+ }
467
+ ; btype == 3 is reserved/error
468
+ }
469
+
470
+ return (this.finalOutput())
471
+ }
472
+
473
+ ; Absolute byte index in the input after the last DEFLATE bit.
474
+ ; Unused bits in that last byte have already been skipped: the next
475
+ ; zlib Adler-32 (or the next Git pack object) starts here.
476
+ fn inputPos:int () {
477
+ return reader.getBytePosition()
478
+ }
479
+
480
+ fn decompressStored:void () {
481
+ ; Stored block: skip to byte boundary, read length, copy literal bytes
482
+ reader.alignToByte()
483
+ def len:int (reader.readUint16LE())
484
+ def nlen:int (reader.readUint16LE())
485
+ if ((len + nlen) != 65535) {
486
+ ; NLEN read advances the bitstream even when LEN/NLEN do not match.
487
+ }
488
+
489
+ this.ensureCapacity(len)
490
+ def i 0
491
+ while (i < len) {
492
+ def b:int (reader.readByte())
493
+ this.pushByte(b)
494
+ i = i + 1
495
+ }
496
+ }
497
+
498
+ fn decompressHuffman:void (litLenTable:InflateHuffmanTable distTable:InflateHuffmanTable) {
499
+ ; Decode Huffman-compressed data
500
+ def done:boolean false
501
+ while ((false == done)) {
502
+ def sym:int (litLenTable.decode(reader))
503
+
504
+ if (sym < 256) {
505
+ ; Literal byte
506
+ this.pushByte(sym)
507
+ }
508
+ if (sym == 256) {
509
+ ; End of block
510
+ done = true
511
+ }
512
+ if (sym > 256) {
513
+ ; Length/distance pair
514
+ def lengthCode:int (sym - 257)
515
+ def length:int (itemAt lengthBase lengthCode)
516
+ def extraBits:int (itemAt lengthExtra lengthCode)
517
+ if (extraBits > 0) {
518
+ length = length + (reader.readBits(extraBits))
519
+ }
520
+
521
+ def distCode:int (distTable.decode(reader))
522
+ def dist:int (itemAt distBase distCode)
523
+ def distExtraBits:int (itemAt distExtra distCode)
524
+ if (distExtraBits > 0) {
525
+ dist = dist + (reader.readBits(distExtraBits))
526
+ }
527
+
528
+ ; Copy from output buffer (LZ77)
529
+ this.copyFromOutput(dist length)
530
+ }
531
+ }
532
+ }
533
+
534
+ fn decompressDynamic:void () {
535
+ ; Read dynamic Huffman table definitions
536
+ def hlit:int ((reader.readBits(5)) + 257) ; # of literal/length codes
537
+ def hdist:int ((reader.readBits(5)) + 1) ; # of distance codes
538
+ def hclen:int ((reader.readBits(4)) + 4) ; # of code length codes
539
+
540
+ ; Code length code order
541
+ def clOrder:[int]
542
+ push clOrder 16
543
+ push clOrder 17
544
+ push clOrder 18
545
+ push clOrder 0
546
+ push clOrder 8
547
+ push clOrder 7
548
+ push clOrder 9
549
+ push clOrder 6
550
+ push clOrder 10
551
+ push clOrder 5
552
+ push clOrder 11
553
+ push clOrder 4
554
+ push clOrder 12
555
+ push clOrder 3
556
+ push clOrder 13
557
+ push clOrder 2
558
+ push clOrder 14
559
+ push clOrder 1
560
+ push clOrder 15
561
+
562
+ ; Read code length code lengths
563
+ def clLengths:[int]
564
+ def i 0
565
+ while (i < 19) {
566
+ push clLengths 0
567
+ i = i + 1
568
+ }
569
+
570
+ i = 0
571
+ while (i < hclen) {
572
+ def idx:int (itemAt clOrder i)
573
+ def len:int (reader.readBits(3))
574
+ set clLengths idx len
575
+ i = i + 1
576
+ }
577
+
578
+ ; Build code length Huffman table
579
+ def clTable (new InflateHuffmanTable())
580
+ clTable.build(clLengths 19)
581
+
582
+ ; Decode literal/length and distance code lengths
583
+ def allLengths:[int]
584
+ def totalCodes:int (hlit + hdist)
585
+ i = 0
586
+ while (i < totalCodes) {
587
+ def sym:int (clTable.decode(reader))
588
+
589
+ if (sym < 16) {
590
+ ; Literal code length
591
+ push allLengths sym
592
+ i = i + 1
593
+ }
594
+ if (sym == 16) {
595
+ ; Repeat previous length 3-6 times
596
+ def repeat:int ((reader.readBits(2)) + 3)
597
+ def prevLen:int 0
598
+ def arrLen:int (array_length allLengths)
599
+ if (arrLen > 0) {
600
+ prevLen = (itemAt allLengths (arrLen - 1))
601
+ }
602
+ def j 0
603
+ while (j < repeat) {
604
+ push allLengths prevLen
605
+ j = j + 1
606
+ }
607
+ i = i + repeat
608
+ }
609
+ if (sym == 17) {
610
+ ; Repeat zero 3-10 times
611
+ def repeat:int ((reader.readBits(3)) + 3)
612
+ def j 0
613
+ while (j < repeat) {
614
+ push allLengths 0
615
+ j = j + 1
616
+ }
617
+ i = i + repeat
618
+ }
619
+ if (sym == 18) {
620
+ ; Repeat zero 11-138 times
621
+ def repeat:int ((reader.readBits(7)) + 11)
622
+ def j 0
623
+ while (j < repeat) {
624
+ push allLengths 0
625
+ j = j + 1
626
+ }
627
+ i = i + repeat
628
+ }
629
+ }
630
+
631
+ ; Split into literal/length and distance lengths
632
+ def litLenLengths:[int]
633
+ def distLengths:[int]
634
+ i = 0
635
+ while (i < hlit) {
636
+ push litLenLengths (itemAt allLengths i)
637
+ i = i + 1
638
+ }
639
+ while (i < totalCodes) {
640
+ push distLengths (itemAt allLengths i)
641
+ i = i + 1
642
+ }
643
+
644
+ ; Build dynamic Huffman tables
645
+ def dynLitLen (new InflateHuffmanTable())
646
+ dynLitLen.build(litLenLengths hlit)
647
+
648
+ def dynDist (new InflateHuffmanTable())
649
+ dynDist.build(distLengths hdist)
650
+
651
+ ; Decode data using dynamic tables
652
+ this.decompressHuffman(dynLitLen dynDist)
653
+ }
654
+
655
+ fn copyFromOutput:void (distance:int length:int) {
656
+ ; Copy 'length' bytes from 'distance' bytes back in output.
657
+ ; Byte-by-byte read-then-write handles overlapping copies (distance < length)
658
+ ; correctly, since each read position trails the write head.
659
+ def srcPos:int (outLen - distance)
660
+ this.ensureCapacity(length)
661
+ def i 0
662
+ while (i < length) {
663
+ def b:int 0
664
+ def readPos:int (srcPos + i)
665
+ if (readPos >= 0) {
666
+ if (readPos < outLen) {
667
+ b = (buffer_get outBuf readPos)
668
+ }
669
+ }
670
+ buffer_set outBuf outLen b
671
+ outLen = (outLen + 1)
672
+ i = i + 1
673
+ }
674
+ }
675
+ }