1 module asdf.outputarray;
2 
3 import asdf.asdf;
4 
5 version(X86_64)
6     version = X86_Any;
7 else
8 version(X86)
9     version = X86_Any;
10 
11 package struct OutputArray
12 {
13     import core.memory;
14 
15     ubyte[] data;
16     size_t shift;
17 
18 pure:
19 
20     auto result()
21     {
22         return Asdf(data[0 .. shift]);
23     }
24 
25     this(size_t initialLength)
26     {
27         assert(initialLength >= 32);
28         const len = initialLength % 16 ? (initialLength + 16) / 16 * 16 : initialLength;
29         data = cast(ubyte[]) GC.malloc(len)[0 .. len];
30     }
31 
32     size_t skip(size_t len)
33     {
34         auto ret = shift;
35         shift += len;
36         if(shift > data.length)
37             extend;
38         return ret;
39     }
40 
41     void put(in char[] str)
42     {
43         size_t newShift = shift + str.length;
44         if(newShift > data.length)
45             extend(str.length);
46         data[shift .. newShift] = cast(ubyte[])str;
47         //assert(newShift > shift);
48         shift = newShift;
49     }
50 
51     void put1(ubyte b)
52     {
53         put1(b, shift);
54         shift += 1;
55     }
56 
57     void put(char b)
58     {
59         put1(cast(ubyte)b);
60     }
61 
62     void put4(uint b)
63     {
64         put4(b, shift);
65         shift += 4;
66     }
67 
68     void put1(ubyte b, size_t sh)
69     {
70         assert(sh <= data.length);
71         if(sh == data.length)
72             extend;
73         data[sh] = b;
74     }
75 
76     void put4(uint b, size_t sh)
77     {
78         immutable newShift = sh + 4;
79         if(newShift > data.length)
80             extend;
81         version (X86_Any)
82             *cast(uint*) (data.ptr + sh) = b;
83         else
84             *cast(ubyte[4]*) (data.ptr + sh) = cast(ubyte[4]) cast(uint[1]) [b];
85     }
86 
87     void extend(size_t len)
88     {
89         size_t length = (data.length) * 2 + len;
90         void[] t = data;
91         t = GC.realloc(t.ptr, length)[0 .. length];
92         data = cast(ubyte[])t;
93     }
94 
95     void extend()
96     {
97         size_t length = (data.length) * 2;
98         void[] t = data;
99         t = GC.realloc(t.ptr, length)[0 .. length];
100         data = cast(ubyte[])t;
101     }
102 }