1 module pxtone.descriptor; 2 // '11/08/12 pxFile.h 3 // '16/01/22 pxFile.h 4 // '16/04/27 pxtnFile. (int) 5 // '16/09/09 pxtnDescriptor. 6 7 import pxtone.error; 8 import pxtone.pxtn; 9 10 import std.exception; 11 import std.stdio; 12 import std.traits; 13 14 enum pxSCE = false; 15 16 enum pxtnSEEK { 17 set = 0, 18 cur, 19 end, 20 num 21 } 22 23 struct pxtnDescriptor { 24 private: 25 ubyte[] _p_desc; 26 File file; 27 bool _b_file; 28 bool _b_read; 29 int _size; 30 int _cur; 31 32 bool isOpen() nothrow @safe { 33 return (_p_desc != null) || file.isOpen; 34 } 35 public: 36 37 void set_file_r(ref File fd) @safe { 38 enforce(fd.isOpen, new PxtoneException("File must be opened for reading")); 39 40 fd.seek(0, SEEK_END); 41 ulong sz = fd.tell; 42 fd.seek(0, SEEK_SET); 43 file = fd; 44 45 _size = cast(int) sz; 46 47 _b_file = true; 48 _b_read = true; 49 _cur = 0; 50 } 51 52 void set_file_w(ref File fd) @safe { 53 file = fd; 54 _size = 0; 55 _b_file = true; 56 _b_read = false; 57 _cur = 0; 58 } 59 60 void set_memory_r(ubyte[] buf) @safe { 61 enforce(buf.length >= 1, new PxtoneException("No data to read in buffer")); 62 _p_desc = buf; 63 _b_file = false; 64 _b_read = true; 65 _cur = 0; 66 } 67 68 void seek(pxtnSEEK mode, int val) @safe { 69 if (_b_file) { 70 int[pxtnSEEK.num] seek_tbl = [SEEK_SET, SEEK_CUR, SEEK_END]; 71 file.seek(val, seek_tbl[mode]); 72 } else { 73 switch (mode) { 74 case pxtnSEEK.set: 75 enforce(val < _p_desc.length, "Unexpected end of data"); 76 enforce(val >= 0, "Cannot seek to negative position"); 77 _cur = val; 78 break; 79 case pxtnSEEK.cur: 80 enforce(_cur + val < _p_desc.length, "Unexpected end of data"); 81 enforce(_cur + val >= 0, "Cannot seek to negative position"); 82 _cur += val; 83 break; 84 case pxtnSEEK.end: 85 enforce(_p_desc.length + val < _p_desc.length, "Unexpected end of data"); 86 enforce(_p_desc.length + val >= 0, "Cannot seek to negative position"); 87 _cur = cast(int)_p_desc.length + val; 88 break; 89 default: 90 break; 91 } 92 } 93 } 94 95 void w_asfile(T)(const T p) @safe if (!is(T : U[], U)) { 96 union RawAccess { 97 T t; 98 ubyte[T.sizeof] bytes; 99 } 100 w_asfile(RawAccess(p).bytes); 101 } 102 void w_asfile(T)(scope const(T)[] p) @safe { 103 enforce(isOpen && _b_file && !_b_read, new PxtoneException("File must be opened for writing")); 104 105 file.trustedWrite(p); 106 _size += p.length * T.sizeof; 107 } 108 109 void r(T)(T[] p) @safe { 110 enforce(isOpen, new PxtoneException("File must be opened for reading")); 111 enforce(_b_read, new PxtoneException("File must be opened for reading")); 112 113 if (_b_file) { 114 file.trustedRead(p); 115 } else { 116 for (int i = 0; i < p.length; i++) { 117 enforce(_cur + T.sizeof < _p_desc.length, new PxtoneException("Unexpected end of buffer")); 118 p[i] = (cast(T[])_p_desc[_cur .. _cur + T.sizeof])[0]; 119 _cur += T.sizeof; 120 } 121 } 122 } 123 void r(T)(ref T p) @safe if (!is(T : U[], U)) { 124 enforce(isOpen, new PxtoneException("File must be opened for reading")); 125 enforce(_b_read, new PxtoneException("File must be opened for reading")); 126 127 if (_b_file) { 128 p = file.trustedRead!T(); 129 } else { 130 enforce(_cur + T.sizeof < _p_desc.length, new PxtoneException("Unexpected end of buffer")); 131 p = (cast(T[])_p_desc[_cur .. _cur + T.sizeof])[0]; 132 _cur += T.sizeof; 133 } 134 } 135 136 // ..uint 137 void v_w_asfile(int val) @safe { 138 int dummy; 139 v_w_asfile(val, dummy); 140 } 141 void v_w_asfile(int val, ref int p_add) @safe { 142 enforce(isOpen && _b_file && !_b_read, new PxtoneException("File must be opened for writing")); 143 144 ubyte[5] a = 0; 145 ubyte[5] b = 0; 146 uint us = cast(uint) val; 147 int bytes = 0; 148 149 (cast(uint[])(a[0 .. uint.sizeof]))[0] = us; 150 a[4] = 0; 151 152 // 1byte(7bit) 153 if (us < 0x00000080) { 154 bytes = 1; 155 b[0] = a[0]; 156 } // 2byte(14bit) 157 else if (us < 0x00004000) { 158 bytes = 2; 159 b[0] = ((a[0] << 0) & 0x7F) | 0x80; 160 b[1] = (a[0] >> 7) | ((a[1] << 1) & 0x7F); 161 } // 3byte(21bit) 162 else if (us < 0x00200000) { 163 bytes = 3; 164 b[0] = ((a[0] << 0) & 0x7F) | 0x80; 165 b[1] = (a[0] >> 7) | ((a[1] << 1) & 0x7F) | 0x80; 166 b[2] = (a[1] >> 6) | ((a[2] << 2) & 0x7F); 167 } // 4byte(28bit) 168 else if (us < 0x10000000) { 169 bytes = 4; 170 b[0] = ((a[0] << 0) & 0x7F) | 0x80; 171 b[1] = (a[0] >> 7) | ((a[1] << 1) & 0x7F) | 0x80; 172 b[2] = (a[1] >> 6) | ((a[2] << 2) & 0x7F) | 0x80; 173 b[3] = (a[2] >> 5) | ((a[3] << 3) & 0x7F); 174 } // 5byte(32bit) 175 else { 176 bytes = 5; 177 b[0] = ((a[0] << 0) & 0x7F) | 0x80; 178 b[1] = (a[0] >> 7) | ((a[1] << 1) & 0x7F) | 0x80; 179 b[2] = (a[1] >> 6) | ((a[2] << 2) & 0x7F) | 0x80; 180 b[3] = (a[2] >> 5) | ((a[3] << 3) & 0x7F) | 0x80; 181 b[4] = (a[3] >> 4) | ((a[4] << 4) & 0x7F); 182 } 183 file.trustedWrite(b[0 .. bytes]); 184 p_add += bytes; 185 _size += bytes; 186 } 187 // 可変長読み込み(int までを保証) 188 void v_r(ref int p) @safe { 189 enforce(isOpen && _b_read, new PxtoneException("File must be opened for reading")); 190 191 int i; 192 ubyte[5] a = 0; 193 ubyte[5] b = 0; 194 195 for (i = 0; i < 5; i++) { 196 r(a[i]); 197 if (!(a[i] & 0x80)) { 198 break; 199 } 200 } 201 switch (i) { 202 case 0: 203 b[0] = (a[0] & 0x7F) >> 0; 204 break; 205 case 1: 206 b[0] = cast(ubyte)(((a[0] & 0x7F) >> 0) | (a[1] << 7)); 207 b[1] = (a[1] & 0x7F) >> 1; 208 break; 209 case 2: 210 b[0] = cast(ubyte)(((a[0] & 0x7F) >> 0) | (a[1] << 7)); 211 b[1] = cast(ubyte)(((a[1] & 0x7F) >> 1) | (a[2] << 6)); 212 b[2] = (a[2] & 0x7F) >> 2; 213 break; 214 case 3: 215 b[0] = cast(ubyte)(((a[0] & 0x7F) >> 0) | (a[1] << 7)); 216 b[1] = cast(ubyte)(((a[1] & 0x7F) >> 1) | (a[2] << 6)); 217 b[2] = cast(ubyte)(((a[2] & 0x7F) >> 2) | (a[3] << 5)); 218 b[3] = (a[3] & 0x7F) >> 3; 219 break; 220 case 4: 221 b[0] = cast(ubyte)(((a[0] & 0x7F) >> 0) | (a[1] << 7)); 222 b[1] = cast(ubyte)(((a[1] & 0x7F) >> 1) | (a[2] << 6)); 223 b[2] = cast(ubyte)(((a[2] & 0x7F) >> 2) | (a[3] << 5)); 224 b[3] = cast(ubyte)(((a[3] & 0x7F) >> 3) | (a[4] << 4)); 225 b[4] = (a[4] & 0x7F) >> 4; 226 break; 227 case 5: 228 throw new PxtoneException("Integer too large"); 229 default: 230 break; 231 } 232 233 p = (cast(int[]) b[0 .. 4])[0]; 234 } 235 236 int get_size_bytes() const nothrow @safe { 237 return _b_file ? _size : cast(int)_p_desc.length; 238 } 239 } 240 241 int pxtnDescriptor_v_chk(int val) nothrow @safe { 242 uint us; 243 244 us = cast(uint) val; 245 if (us < 0x80) { 246 return 1; // 1byte( 7bit) 247 } 248 if (us < 0x4000) { 249 return 2; // 2byte(14bit) 250 } 251 if (us < 0x200000) { 252 return 3; // 3byte(21bit) 253 } 254 if (us < 0x10000000) { 255 return 4; // 4byte(28bit) 256 } 257 // if( value < 0x800000000 ) return 5; // 5byte(35bit) 258 if (us <= 0xffffffff) { 259 return 5; 260 } 261 262 return 6; 263 } 264 265 T trustedRead(T)(File file) @safe if (!hasIndirections!T) { 266 T[1] p; 267 file.trustedRead(p); 268 return p[0]; 269 } 270 271 void trustedRead(T)(File file, T[] arr) @trusted if (!hasIndirections!T) { 272 file.rawRead(arr); 273 } 274 275 void trustedWrite(T)(File file, T val) @safe if (!hasIndirections!T) { 276 T[1] p = [val]; 277 file.trustedWrite(p); 278 } 279 280 void trustedWrite(T)(File file, T[] arr) @trusted if (!hasIndirections!T) { 281 file.rawWrite(arr); 282 }