1 /++ 2 +/ 3 // TODO: tape building for Annotations 4 module mir.ion.tape; 5 6 import core.stdc.string: memmove, memcpy; 7 import mir.bignum.low_level_view; 8 import mir.bitop; 9 import mir.date; 10 import mir.lob; 11 import mir.timestamp: Timestamp; 12 import mir.ion.type_code; 13 import mir.utility: _expect; 14 import std.traits; 15 16 version(LDC) import ldc.attributes: optStrategy; 17 else private struct optStrategy { string opt; } 18 19 /++ 20 +/ 21 size_t ionPutVarUInt(T)(scope ubyte* ptr, const T num) 22 if (isUnsigned!T) 23 { 24 T value = num; 25 enum s = T.sizeof * 8 / 7 + 1; 26 uint len; 27 do ptr[s - 1 - len++] = value & 0x7F; 28 while (value >>>= 7); 29 ptr[s - 1] |= 0x80; 30 if (!__ctfe) 31 { 32 auto arr = *cast(ubyte[s-1]*)(ptr + s - len); 33 *cast(ubyte[s-1]*)ptr = arr; 34 } 35 else 36 { 37 foreach(i; 0 .. len) 38 ptr[i] = ptr[i + s - len]; 39 } 40 return len; 41 } 42 43 /// 44 @system pure nothrow @nogc 45 version(mir_ion_test) unittest 46 { 47 ubyte[19] data = void; 48 49 alias AliasSeq(T...) = T; 50 51 foreach(T; AliasSeq!(ubyte, ushort, uint, ulong)) 52 { 53 data[] = 0; 54 assert(ionPutVarUInt!T(data.ptr, 0) == 1); 55 assert(data[0] == 0x80); 56 57 data[] = 0; 58 assert(ionPutVarUInt!T(data.ptr, 1) == 1); 59 assert(data[0] == 0x81); 60 61 data[] = 0; 62 assert(ionPutVarUInt!T(data.ptr, 0x7F) == 1); 63 assert(data[0] == 0xFF); 64 65 data[] = 0; 66 assert(ionPutVarUInt!T(data.ptr, 0xFF) == 2); 67 assert(data[0] == 0x01); 68 assert(data[1] == 0xFF); 69 } 70 71 foreach(T; AliasSeq!(ushort, uint, ulong)) 72 { 73 74 data[] = 0; 75 assert(ionPutVarUInt!T(data.ptr, 0x3FFF) == 2); 76 assert(data[0] == 0x7F); 77 assert(data[1] == 0xFF); 78 79 data[] = 0; 80 assert(ionPutVarUInt!T(data.ptr, 0x7FFF) == 3); 81 assert(data[0] == 0x01); 82 assert(data[1] == 0x7F); 83 assert(data[2] == 0xFF); 84 85 data[] = 0; 86 assert(ionPutVarUInt!T(data.ptr, 0xFFEE) == 3); 87 assert(data[0] == 0x03); 88 assert(data[1] == 0x7F); 89 assert(data[2] == 0xEE); 90 } 91 92 data[] = 0; 93 assert(ionPutVarUInt(data.ptr, uint.max) == 5); 94 assert(data[0] == 0x0F); 95 assert(data[1] == 0x7F); 96 assert(data[2] == 0x7F); 97 assert(data[3] == 0x7F); 98 assert(data[4] == 0xFF); 99 100 data[] = 0; 101 assert(ionPutVarUInt!ulong(data.ptr, ulong.max >> 1) == 9); 102 assert(data[0] == 0x7F); 103 assert(data[1] == 0x7F); 104 assert(data[2] == 0x7F); 105 assert(data[3] == 0x7F); 106 assert(data[4] == 0x7F); 107 assert(data[5] == 0x7F); 108 assert(data[6] == 0x7F); 109 assert(data[7] == 0x7F); 110 assert(data[8] == 0xFF); 111 112 data[] = 0; 113 assert(ionPutVarUInt(data.ptr, ulong.max) == 10); 114 assert(data[0] == 0x01); 115 assert(data[1] == 0x7F); 116 assert(data[2] == 0x7F); 117 assert(data[3] == 0x7F); 118 assert(data[4] == 0x7F); 119 assert(data[5] == 0x7F); 120 assert(data[6] == 0x7F); 121 assert(data[7] == 0x7F); 122 assert(data[8] == 0x7F); 123 assert(data[9] == 0xFF); 124 } 125 126 /++ 127 +/ 128 size_t ionPutVarInt(T)(scope ubyte* ptr, const T num) 129 if (isSigned!T) 130 { 131 return .ionPutVarInt!(Unsigned!T)(ptr, num < 0 ? cast(Unsigned!T)(0-num) : num, num < 0); 132 } 133 134 /++ 135 +/ 136 size_t ionPutVarInt(T)(scope ubyte* ptr, const T num, bool sign) 137 if (isUnsigned!T) 138 { 139 T value = num; 140 if (_expect(value < 64, true)) 141 { 142 *ptr = cast(ubyte)(value | 0x80 | (sign << 6)); 143 return 1; 144 } 145 enum s = T.sizeof * 8 / 7 + 1; 146 size_t len; 147 do ptr[s - 1 - len++] = value & 0x7F; 148 while (value >>>= 7); 149 auto sb = ptr[s - len] >>> 6; 150 auto r = ptr[s - len] & ~(~sb + 1); 151 len += sb; 152 ptr[s - len] = cast(ubyte)r | (cast(ubyte)sign << 6); 153 ptr[s - 1] |= 0x80; 154 auto arr = *cast(ubyte[s-1]*)(ptr + s - len); 155 *cast(ubyte[s-1]*)ptr = arr; 156 return len; 157 } 158 159 /// 160 @system pure nothrow @nogc 161 version(mir_ion_test) unittest 162 { 163 ubyte[19] data = void; 164 165 alias AliasSeq(T...) = T; 166 167 foreach(T; AliasSeq!(ubyte, ushort, uint, ulong)) 168 { 169 data[] = 0; 170 assert(ionPutVarInt!T(data.ptr, 0, false) == 1); 171 assert(data[0] == 0x80); 172 173 data[] = 0; 174 assert(ionPutVarInt!T(data.ptr, 1, false) == 1); 175 assert(data[0] == 0x81); 176 177 data[] = 0; 178 assert(ionPutVarInt!T(data.ptr, 1, true) == 1); 179 assert(data[0] == 0xC1); 180 181 data[] = 0; 182 assert(ionPutVarInt!T(data.ptr, 0x3F, false) == 1); 183 assert(data[0] == 0xBF); 184 185 data[] = 0; 186 assert(ionPutVarInt!T(data.ptr, 0x3F, true) == 1); 187 assert(data[0] == 0xFF); 188 189 data[] = 0; 190 assert(ionPutVarInt!T(data.ptr, 0x7F, false) == 2); 191 assert(data[0] == 0x00); 192 assert(data[1] == 0xFF); 193 194 data[] = 0; 195 assert(ionPutVarInt!T(data.ptr, 128, true) == 2); 196 assert(data[0] == 0x41); 197 assert(data[1] == 0x80); 198 199 data[] = 0; 200 assert(ionPutVarInt!T(data.ptr, 127, true) == 2); 201 assert(data[0] == 0x40); 202 assert(data[1] == 0xFF); 203 204 205 data[] = 0; 206 assert(ionPutVarInt!T(data.ptr, 3, true) == 1); 207 assert(data[0] == 0xC3); 208 209 data[] = 0; 210 assert(ionPutVarInt!T(data.ptr, 127, true) == 2); 211 assert(data[0] == 0x40); 212 assert(data[1] == 0xFF); 213 214 data[] = 0; 215 assert(ionPutVarInt!T(data.ptr, 63, true) == 1); 216 assert(data[0] == 0xFF); 217 } 218 219 data[] = 0; 220 assert(ionPutVarInt!uint(data.ptr, int.max, false) == 5); 221 assert(data[0] == 0x07); 222 assert(data[1] == 0x7F); 223 assert(data[2] == 0x7F); 224 assert(data[3] == 0x7F); 225 assert(data[4] == 0xFF); 226 227 data[] = 0; 228 assert(ionPutVarInt!uint(data.ptr, int.max, true) == 5); 229 assert(data[0] == 0x47); 230 assert(data[1] == 0x7F); 231 assert(data[2] == 0x7F); 232 assert(data[3] == 0x7F); 233 assert(data[4] == 0xFF); 234 235 data[] = 0; 236 assert(ionPutVarInt!uint(data.ptr, int.max + 1, true) == 5); 237 assert(data[0] == 0x48); 238 assert(data[1] == 0x00); 239 assert(data[2] == 0x00); 240 assert(data[3] == 0x00); 241 assert(data[4] == 0x80); 242 243 data[] = 0; 244 assert(ionPutVarInt!ulong(data.ptr, long.max >> 1, false) == 9); 245 assert(data[0] == 0x3F); 246 assert(data[1] == 0x7F); 247 assert(data[2] == 0x7F); 248 assert(data[3] == 0x7F); 249 assert(data[4] == 0x7F); 250 assert(data[5] == 0x7F); 251 assert(data[6] == 0x7F); 252 assert(data[7] == 0x7F); 253 assert(data[8] == 0xFF); 254 255 data[] = 0; 256 assert(ionPutVarInt!ulong(data.ptr, long.max, false) == 10); 257 assert(data[0] == 0x00); 258 assert(data[1] == 0x7F); 259 assert(data[2] == 0x7F); 260 assert(data[3] == 0x7F); 261 assert(data[4] == 0x7F); 262 assert(data[5] == 0x7F); 263 assert(data[6] == 0x7F); 264 assert(data[7] == 0x7F); 265 assert(data[8] == 0x7F); 266 assert(data[9] == 0xFF); 267 268 data[] = 0; 269 assert(ionPutVarInt!ulong(data.ptr, long.max, true) == 10); 270 assert(data[0] == 0x40); 271 assert(data[1] == 0x7F); 272 assert(data[2] == 0x7F); 273 assert(data[3] == 0x7F); 274 assert(data[4] == 0x7F); 275 assert(data[5] == 0x7F); 276 assert(data[6] == 0x7F); 277 assert(data[7] == 0x7F); 278 assert(data[8] == 0x7F); 279 assert(data[9] == 0xFF); 280 281 data[] = 0; 282 assert(ionPutVarInt!ulong(data.ptr, -long.min, true) == 10); 283 assert(data[0] == 0x41); 284 assert(data[1] == 0x00); 285 assert(data[2] == 0x00); 286 assert(data[3] == 0x00); 287 assert(data[4] == 0x00); 288 assert(data[5] == 0x00); 289 assert(data[6] == 0x00); 290 assert(data[7] == 0x00); 291 assert(data[8] == 0x00); 292 assert(data[9] == 0x80); 293 294 data[] = 0; 295 assert(ionPutVarInt(data.ptr, ulong.max, true) == 10); 296 assert(data[0] == 0x41); 297 assert(data[1] == 0x7F); 298 assert(data[2] == 0x7F); 299 assert(data[3] == 0x7F); 300 assert(data[4] == 0x7F); 301 assert(data[5] == 0x7F); 302 assert(data[6] == 0x7F); 303 assert(data[7] == 0x7F); 304 assert(data[8] == 0x7F); 305 assert(data[9] == 0xFF); 306 307 data[] = 0; 308 assert(ionPutVarInt(data.ptr, ulong.max, false) == 10); 309 assert(data[0] == 0x01); 310 assert(data[1] == 0x7F); 311 assert(data[2] == 0x7F); 312 assert(data[3] == 0x7F); 313 assert(data[4] == 0x7F); 314 assert(data[5] == 0x7F); 315 assert(data[6] == 0x7F); 316 assert(data[7] == 0x7F); 317 assert(data[8] == 0x7F); 318 assert(data[9] == 0xFF); 319 } 320 321 /++ 322 +/ 323 size_t ionPutVarIntR(T)(scope ubyte* ptr, const T num) 324 if (isSigned!T) 325 { 326 return .ionPutVarIntR!(Unsigned!T)(ptr, num < 0 ? cast(Unsigned!T)(0-num) : num, num < 0); 327 } 328 329 /++ 330 +/ 331 size_t ionPutVarIntR(T)(scope ubyte* ptr, const T num, bool sign) 332 if (isUnsigned!T) 333 { 334 T value = num; 335 if (_expect(value < 64, true)) 336 { 337 *(ptr - 1) = cast(ubyte)(value | 0x80 | (sign << 6)); 338 return 1; 339 } 340 enum s = T.sizeof * 8 / 7 + 1; 341 size_t len; 342 do *(ptr - ++len) = value & 0x7F; 343 while (value >>>= 7); 344 auto sb = *(ptr - len) >>> 6; 345 auto r = *(ptr - len) & ~(~sb + 1); 346 len += sb; 347 *(ptr - len) = cast(ubyte)r | (cast(ubyte)sign << 6); 348 *(ptr - 1) |= 0x80; 349 return len; 350 } 351 352 /// 353 @system pure nothrow @nogc 354 version(mir_ion_test) unittest 355 { 356 ubyte[10] data = void; 357 358 alias AliasSeq(T...) = T; 359 360 361 foreach(T; AliasSeq!(ubyte, ushort, uint, ulong)) 362 { 363 data[] = 0; 364 assert(ionPutVarIntR!T(data.ptr + 10, 0, false) == 1); 365 assert(data[$ - 1] == 0x80); 366 367 data[] = 0; 368 assert(ionPutVarIntR!T(data.ptr + 10, 1, false) == 1); 369 assert(data[$ - 1] == 0x81); 370 371 data[] = 0; 372 assert(ionPutVarIntR!T(data.ptr + 10, 1, true) == 1); 373 assert(data[$ - 1] == 0xC1); 374 375 data[] = 0; 376 assert(ionPutVarIntR!T(data.ptr + 10, 0x3F, false) == 1); 377 assert(data[$ - 1] == 0xBF); 378 379 data[] = 0; 380 assert(ionPutVarIntR!T(data.ptr + 10, 0x3F, true) == 1); 381 assert(data[$ - 1] == 0xFF); 382 383 data[] = 0; 384 assert(ionPutVarIntR!T(data.ptr + 10, 0x7F, false) == 2); 385 assert(data[$ - 2] == 0x00); 386 assert(data[$ - 1] == 0xFF); 387 388 data[] = 0; 389 assert(ionPutVarIntR!T(data.ptr + 10, 128, true) == 2); 390 assert(data[$ - 2] == 0x41); 391 assert(data[$ - 1] == 0x80); 392 393 data[] = 0; 394 assert(ionPutVarIntR!T(data.ptr + 10, 127, true) == 2); 395 assert(data[$ - 2] == 0x40); 396 assert(data[$ - 1] == 0xFF); 397 398 399 data[] = 0; 400 assert(ionPutVarIntR!T(data.ptr + 10, 3, true) == 1); 401 assert(data[$ - 1] == 0xC3); 402 403 data[] = 0; 404 assert(ionPutVarIntR!T(data.ptr + 10, 127, true) == 2); 405 assert(data[$ - 2] == 0x40); 406 assert(data[$ - 1] == 0xFF); 407 408 data[] = 0; 409 assert(ionPutVarIntR!T(data.ptr + 10, 63, true) == 1); 410 assert(data[$ - 1] == 0xFF); 411 } 412 413 data[] = 0; 414 assert(ionPutVarIntR!uint(data.ptr + 10, int.max, false) == 5); 415 assert(data[5 + 0] == 0x07); 416 assert(data[5 + 1] == 0x7F); 417 assert(data[5 + 2] == 0x7F); 418 assert(data[5 + 3] == 0x7F); 419 assert(data[5 + 4] == 0xFF); 420 421 data[] = 0; 422 assert(ionPutVarIntR!uint(data.ptr + 10, int.max, true) == 5); 423 assert(data[5 + 0] == 0x47); 424 assert(data[5 + 1] == 0x7F); 425 assert(data[5 + 2] == 0x7F); 426 assert(data[5 + 3] == 0x7F); 427 assert(data[5 + 4] == 0xFF); 428 429 data[] = 0; 430 assert(ionPutVarIntR!uint(data.ptr + 10, int.max + 1, true) == 5); 431 assert(data[5 + 0] == 0x48); 432 assert(data[5 + 1] == 0x00); 433 assert(data[5 + 2] == 0x00); 434 assert(data[5 + 3] == 0x00); 435 assert(data[5 + 4] == 0x80); 436 437 data[] = 0; 438 assert(ionPutVarIntR!ulong(data.ptr + 10, long.max >> 1, false) == 9); 439 assert(data[1 + 0] == 0x3F); 440 assert(data[1 + 1] == 0x7F); 441 assert(data[1 + 2] == 0x7F); 442 assert(data[1 + 3] == 0x7F); 443 assert(data[1 + 4] == 0x7F); 444 assert(data[1 + 5] == 0x7F); 445 assert(data[1 + 6] == 0x7F); 446 assert(data[1 + 7] == 0x7F); 447 assert(data[1 + 8] == 0xFF); 448 449 data[] = 0; 450 assert(ionPutVarIntR!ulong(data.ptr + 10, long.max, false) == 10); 451 assert(data[0] == 0x00); 452 assert(data[1] == 0x7F); 453 assert(data[2] == 0x7F); 454 assert(data[3] == 0x7F); 455 assert(data[4] == 0x7F); 456 assert(data[5] == 0x7F); 457 assert(data[6] == 0x7F); 458 assert(data[7] == 0x7F); 459 assert(data[8] == 0x7F); 460 assert(data[9] == 0xFF); 461 462 data[] = 0; 463 assert(ionPutVarIntR!ulong(data.ptr + 10, long.max, true) == 10); 464 assert(data[0] == 0x40); 465 assert(data[1] == 0x7F); 466 assert(data[2] == 0x7F); 467 assert(data[3] == 0x7F); 468 assert(data[4] == 0x7F); 469 assert(data[5] == 0x7F); 470 assert(data[6] == 0x7F); 471 assert(data[7] == 0x7F); 472 assert(data[8] == 0x7F); 473 assert(data[9] == 0xFF); 474 475 data[] = 0; 476 assert(ionPutVarIntR!ulong(data.ptr + 10, -long.min, true) == 10); 477 assert(data[0] == 0x41); 478 assert(data[1] == 0x00); 479 assert(data[2] == 0x00); 480 assert(data[3] == 0x00); 481 assert(data[4] == 0x00); 482 assert(data[5] == 0x00); 483 assert(data[6] == 0x00); 484 assert(data[7] == 0x00); 485 assert(data[8] == 0x00); 486 assert(data[9] == 0x80); 487 488 data[] = 0; 489 assert(ionPutVarIntR(data.ptr + 10, ulong.max, true) == 10); 490 assert(data[0] == 0x41); 491 assert(data[1] == 0x7F); 492 assert(data[2] == 0x7F); 493 assert(data[3] == 0x7F); 494 assert(data[4] == 0x7F); 495 assert(data[5] == 0x7F); 496 assert(data[6] == 0x7F); 497 assert(data[7] == 0x7F); 498 assert(data[8] == 0x7F); 499 assert(data[9] == 0xFF); 500 501 data[] = 0; 502 assert(ionPutVarIntR(data.ptr + 10, ulong.max, false) == 10); 503 assert(data[0] == 0x01); 504 assert(data[1] == 0x7F); 505 assert(data[2] == 0x7F); 506 assert(data[3] == 0x7F); 507 assert(data[4] == 0x7F); 508 assert(data[5] == 0x7F); 509 assert(data[6] == 0x7F); 510 assert(data[7] == 0x7F); 511 assert(data[8] == 0x7F); 512 assert(data[9] == 0xFF); 513 } 514 515 /++ 516 +/ 517 @optStrategy("optsize") 518 size_t ionPutUIntField()( 519 scope ubyte* ptr, 520 BigUIntView!(const size_t) value, 521 ) 522 { 523 auto data = value.coefficients; 524 size_t ret; 525 static if (size_t.sizeof > 1) 526 { 527 if (data.length) 528 { 529 ret = .ionPutUIntField(ptr, data[$ - 1]); 530 data = data[0 .. $ - 1]; 531 } 532 } 533 foreach_reverse (d; data) 534 { 535 *cast(ubyte[size_t.sizeof]*)(ptr + ret) = byteData(d); 536 ret += size_t.sizeof; 537 } 538 return ret; 539 } 540 541 /++ 542 +/ 543 size_t ionPutUIntField(T)(scope ubyte* ptr, const T num) 544 if (isUnsigned!T && T.sizeof >= 4) 545 { 546 T value = num; 547 auto c = cast(size_t)ctlzp(value); 548 enum ubyte cm = 0xF8 & (value.sizeof * 8 - 1); 549 value <<= c & cm; 550 c >>>= 3; 551 *cast(ubyte[T.sizeof]*)ptr = byteData(value); 552 return T.sizeof - c; 553 } 554 555 /++ 556 +/ 557 size_t ionPutUIntField(T)(scope ubyte* ptr, const T num) 558 if (is(T == ubyte)) 559 { 560 *ptr = num; 561 return num != 0; 562 } 563 564 /++ 565 +/ 566 size_t ionPutUIntField(T)(scope ubyte* ptr, const T num) 567 if (is(T == ushort)) 568 { 569 return ionPutUIntField!uint(ptr, num); 570 } 571 572 /// 573 @system pure nothrow @nogc 574 version(mir_ion_test) unittest 575 { 576 ubyte[8] data; 577 578 alias AliasSeq(T...) = T; 579 580 foreach(T; AliasSeq!(ubyte, ushort, uint, ulong)) 581 { 582 data[] = 0; 583 assert(ionPutUIntField!T(data.ptr, 0) == 0); 584 585 data[] = 0; 586 assert(ionPutUIntField!T(data.ptr, 1) == 1); 587 assert(data[0] == 0x01); 588 589 data[] = 0; 590 assert(ionPutUIntField!T(data.ptr, 0x3F) == 1); 591 assert(data[0] == 0x3F); 592 593 data[] = 0; 594 assert(ionPutUIntField!T(data.ptr, 0xFF) == 1); 595 assert(data[0] == 0xFF); 596 597 data[] = 0; 598 assert(ionPutUIntField!T(data.ptr, 0x80) == 1); 599 assert(data[0] == 0x80); 600 } 601 602 data[] = 0; 603 assert(ionPutUIntField!uint(data.ptr, int.max) == 4); 604 assert(data[0] == 0x7F); 605 assert(data[1] == 0xFF); 606 assert(data[2] == 0xFF); 607 assert(data[3] == 0xFF); 608 609 data[] = 0; 610 assert(ionPutUIntField!uint(data.ptr, int.max + 1) == 4); 611 assert(data[0] == 0x80); 612 assert(data[1] == 0x00); 613 assert(data[2] == 0x00); 614 assert(data[3] == 0x00); 615 616 data[] = 0; 617 assert(ionPutUIntField!ulong(data.ptr, long.max >> 1) == 8); 618 assert(data[0] == 0x3F); 619 assert(data[1] == 0xFF); 620 assert(data[2] == 0xFF); 621 assert(data[3] == 0xFF); 622 assert(data[4] == 0xFF); 623 assert(data[5] == 0xFF); 624 assert(data[6] == 0xFF); 625 assert(data[7] == 0xFF); 626 627 data[] = 0; 628 assert(ionPutUIntField!ulong(data.ptr, long.max) == 8); 629 assert(data[0] == 0x7F); 630 assert(data[1] == 0xFF); 631 assert(data[2] == 0xFF); 632 assert(data[3] == 0xFF); 633 assert(data[4] == 0xFF); 634 assert(data[5] == 0xFF); 635 assert(data[6] == 0xFF); 636 assert(data[7] == 0xFF); 637 638 data[] = 0; 639 assert(ionPutUIntField!ulong(data.ptr, long.max + 1) == 8); 640 assert(data[0] == 0x80); 641 assert(data[1] == 0x00); 642 assert(data[2] == 0x00); 643 assert(data[3] == 0x00); 644 assert(data[4] == 0x00); 645 assert(data[5] == 0x00); 646 assert(data[6] == 0x00); 647 assert(data[7] == 0x00); 648 649 data[] = 0; 650 assert(ionPutUIntField(data.ptr, ulong.max) == 8); 651 assert(data[0] == 0xFF); 652 assert(data[1] == 0xFF); 653 assert(data[2] == 0xFF); 654 assert(data[3] == 0xFF); 655 assert(data[4] == 0xFF); 656 assert(data[5] == 0xFF); 657 assert(data[6] == 0xFF); 658 assert(data[7] == 0xFF); 659 } 660 661 662 /++ 663 +/ 664 size_t ionPutUIntFieldR(T)(scope ubyte* ptr, const T num) 665 if (isUnsigned!T && T.sizeof >= 4) 666 { 667 T value = num; 668 auto c = cast(size_t)ctlzp(value); 669 enum ubyte cm = 0xF8 & (value.sizeof * 8 - 1); 670 c >>>= 3; 671 *cast(ubyte[T.sizeof]*)(ptr - T.sizeof) = byteData(value); 672 return T.sizeof - c; 673 } 674 675 /++ 676 +/ 677 size_t ionPutUIntFieldR(T)(scope ubyte* ptr, const T num) 678 if (is(T == ubyte)) 679 { 680 *(ptr - 1) = num; 681 return num != 0; 682 } 683 684 /++ 685 +/ 686 size_t ionPutUIntFieldR(T)(scope ubyte* ptr, const T num) 687 if (is(T == ushort)) 688 { 689 return ionPutUIntFieldR!uint(ptr, num); 690 } 691 692 693 /// 694 @system pure nothrow @nogc 695 version(mir_ion_test) unittest 696 { 697 ubyte[8] data; 698 699 alias AliasSeq(T...) = T; 700 701 foreach(T; AliasSeq!(ubyte, ushort, uint, ulong)) 702 { 703 data[] = 0; 704 assert(ionPutUIntFieldR!T(data.ptr + data.length, 0) == 0); 705 706 data[] = 0; 707 assert(ionPutUIntFieldR!T(data.ptr + data.length, 1) == 1); 708 assert(data[$ - 1] == 0x01); 709 710 data[] = 0; 711 assert(ionPutUIntFieldR!T(data.ptr + data.length, 0x3F) == 1); 712 assert(data[$ - 1] == 0x3F); 713 714 data[] = 0; 715 assert(ionPutUIntFieldR!T(data.ptr + data.length, 0xFF) == 1); 716 assert(data[$ - 1] == 0xFF); 717 718 data[] = 0; 719 assert(ionPutUIntFieldR!T(data.ptr + data.length, 0x80) == 1); 720 assert(data[$ - 1] == 0x80); 721 } 722 723 data[] = 0; 724 assert(ionPutUIntFieldR!uint(data.ptr + data.length, int.max) == 4); 725 assert(data[4 + 0] == 0x7F); 726 assert(data[4 + 1] == 0xFF); 727 assert(data[4 + 2] == 0xFF); 728 assert(data[4 + 3] == 0xFF); 729 730 data[] = 0; 731 assert(ionPutUIntFieldR!uint(data.ptr + data.length, int.max + 1) == 4); 732 assert(data[4 + 0] == 0x80); 733 assert(data[4 + 1] == 0x00); 734 assert(data[4 + 2] == 0x00); 735 assert(data[4 + 3] == 0x00); 736 737 data[] = 0; 738 assert(ionPutUIntFieldR!ulong(data.ptr + data.length, long.max >> 1) == 8); 739 assert(data[0] == 0x3F); 740 assert(data[1] == 0xFF); 741 assert(data[2] == 0xFF); 742 assert(data[3] == 0xFF); 743 assert(data[4] == 0xFF); 744 assert(data[5] == 0xFF); 745 assert(data[6] == 0xFF); 746 assert(data[7] == 0xFF); 747 748 data[] = 0; 749 assert(ionPutUIntFieldR!ulong(data.ptr + data.length, long.max) == 8); 750 assert(data[0] == 0x7F); 751 assert(data[1] == 0xFF); 752 assert(data[2] == 0xFF); 753 assert(data[3] == 0xFF); 754 assert(data[4] == 0xFF); 755 assert(data[5] == 0xFF); 756 assert(data[6] == 0xFF); 757 assert(data[7] == 0xFF); 758 759 data[] = 0; 760 assert(ionPutUIntFieldR!ulong(data.ptr + data.length, long.max + 1) == 8); 761 assert(data[0] == 0x80); 762 assert(data[1] == 0x00); 763 assert(data[2] == 0x00); 764 assert(data[3] == 0x00); 765 assert(data[4] == 0x00); 766 assert(data[5] == 0x00); 767 assert(data[6] == 0x00); 768 assert(data[7] == 0x00); 769 770 data[] = 0; 771 assert(ionPutUIntFieldR(data.ptr + data.length, ulong.max) == 8); 772 assert(data[0] == 0xFF); 773 assert(data[1] == 0xFF); 774 assert(data[2] == 0xFF); 775 assert(data[3] == 0xFF); 776 assert(data[4] == 0xFF); 777 assert(data[5] == 0xFF); 778 assert(data[6] == 0xFF); 779 assert(data[7] == 0xFF); 780 } 781 782 /++ 783 +/ 784 @optStrategy("optsize") 785 size_t ionPutIntField()( 786 scope ubyte* ptr, 787 BigIntView!(const size_t) value, 788 ) 789 { 790 auto data = value.unsigned.coefficients; 791 if (data.length == 0) 792 { 793 *ptr = value.sign << 7; 794 return value.sign; 795 } 796 size_t ret = .ionPutIntField(ptr, data[$ - 1], value.sign); 797 data = data[0 .. $ - 1]; 798 foreach_reverse (d; data) 799 { 800 *cast(ubyte[size_t.sizeof]*)(ptr + ret) = byteData(d); 801 ret += size_t.sizeof; 802 } 803 return ret; 804 } 805 806 /++ 807 +/ 808 size_t ionPutIntField(T)(scope ubyte* ptr, const T num) 809 if (isSigned!T && isIntegral!T) 810 { 811 T value = num; 812 bool sign = value < 0; 813 if (sign) 814 value = cast(T)(0-value); 815 return ionPutIntField!(Unsigned!T)(ptr, value, sign); 816 } 817 818 /++ 819 +/ 820 size_t ionPutIntField(T)(scope ubyte* ptr, const T num, bool sign) 821 if (isUnsigned!T) 822 { 823 T value = num; 824 static if (T.sizeof >= 4) 825 { 826 auto c = cast(uint)ctlzp(value); 827 bool s = (c & 0x7) == 0; 828 *ptr = sign << 7; 829 ptr += s; 830 enum ubyte cm = 0xF8 & (value.sizeof * 8 - 1); 831 value <<= c & cm; 832 c >>>= 3; 833 value |= T(sign) << (T.sizeof * 8 - 1); 834 c = uint(T.sizeof) - c + s - (value == 0); 835 *cast(ubyte[T.sizeof]*)ptr = byteData(value); 836 return c; 837 } 838 else 839 { 840 return ionPutIntField!uint(ptr, value, sign); 841 } 842 } 843 844 /// 845 @system pure nothrow @nogc 846 version(mir_ion_test) unittest 847 { 848 ubyte[9] data; 849 850 alias AliasSeq(T...) = T; 851 852 foreach(T; AliasSeq!(ubyte, ushort, uint, ulong)) 853 { 854 data[] = 0; 855 assert(ionPutIntField!T(data.ptr, 0, false) == 0, T.stringof); 856 857 data[] = 0; 858 assert(ionPutIntField!T(data.ptr, 0, true) == 1); 859 assert(data[0] == 0x80); 860 861 data[] = 0; 862 assert(ionPutIntField!T(data.ptr, 1, false) == 1); 863 assert(data[0] == 0x01); 864 865 data[] = 0; 866 assert(ionPutIntField!T(data.ptr, 1, true) == 1); 867 assert(data[0] == 0x81); 868 869 data[] = 0; 870 assert(ionPutIntField!T(data.ptr, 0x3F, true) == 1); 871 assert(data[0] == 0xBF); 872 873 data[] = 0; 874 assert(ionPutIntField!T(data.ptr, 0xFF, false) == 2); 875 assert(data[0] == 0x00); 876 assert(data[1] == 0xFF); 877 878 data[] = 0; 879 assert(ionPutIntField!T(data.ptr, 0xFF, true) == 2); 880 assert(data[0] == 0x80); 881 assert(data[1] == 0xFF); 882 883 data[] = 0; 884 assert(ionPutIntField!T(data.ptr, 0x80, true) == 2); 885 assert(data[0] == 0x80); 886 assert(data[1] == 0x80); 887 } 888 889 data[] = 0; 890 assert(ionPutIntField(data.ptr, int.max) == 4); 891 assert(data[0] == 0x7F); 892 assert(data[1] == 0xFF); 893 assert(data[2] == 0xFF); 894 assert(data[3] == 0xFF); 895 896 data[] = 0; 897 assert(ionPutIntField(data.ptr, int.min) == 5); 898 assert(data[0] == 0x80); 899 assert(data[1] == 0x80); 900 assert(data[2] == 0x00); 901 assert(data[3] == 0x00); 902 assert(data[4] == 0x00); 903 904 data[] = 0; 905 assert(ionPutIntField(data.ptr, long.max >> 1) == 8); 906 assert(data[0] == 0x3F); 907 assert(data[1] == 0xFF); 908 assert(data[2] == 0xFF); 909 assert(data[3] == 0xFF); 910 assert(data[4] == 0xFF); 911 assert(data[5] == 0xFF); 912 assert(data[6] == 0xFF); 913 assert(data[7] == 0xFF); 914 915 data[] = 0; 916 assert(ionPutIntField(data.ptr, ulong(long.max >> 1), true) == 8); 917 assert(data[0] == 0xBF); 918 assert(data[1] == 0xFF); 919 assert(data[2] == 0xFF); 920 assert(data[3] == 0xFF); 921 assert(data[4] == 0xFF); 922 assert(data[5] == 0xFF); 923 assert(data[6] == 0xFF); 924 assert(data[7] == 0xFF); 925 926 data[] = 0; 927 assert(ionPutIntField(data.ptr, long.max) == 8); 928 assert(data[0] == 0x7F); 929 assert(data[1] == 0xFF); 930 assert(data[2] == 0xFF); 931 assert(data[3] == 0xFF); 932 assert(data[4] == 0xFF); 933 assert(data[5] == 0xFF); 934 assert(data[6] == 0xFF); 935 assert(data[7] == 0xFF); 936 937 data[] = 0; 938 assert(ionPutIntField(data.ptr, ulong(long.max), true) == 8); 939 assert(data[0] == 0xFF); 940 assert(data[1] == 0xFF); 941 assert(data[2] == 0xFF); 942 assert(data[3] == 0xFF); 943 assert(data[4] == 0xFF); 944 assert(data[5] == 0xFF); 945 assert(data[6] == 0xFF); 946 assert(data[7] == 0xFF); 947 948 data[] = 0; 949 assert(ionPutIntField!ulong(data.ptr, long.max + 1, false) == 9); 950 assert(data[0] == 0x00); 951 assert(data[1] == 0x80); 952 assert(data[2] == 0x00); 953 assert(data[3] == 0x00); 954 assert(data[4] == 0x00); 955 assert(data[5] == 0x00); 956 assert(data[6] == 0x00); 957 assert(data[7] == 0x00); 958 assert(data[8] == 0x00); 959 960 data[] = 0; 961 assert(ionPutIntField(data.ptr, ulong.max, true) == 9); 962 assert(data[0] == 0x80); 963 assert(data[1] == 0xFF); 964 assert(data[2] == 0xFF); 965 assert(data[3] == 0xFF); 966 assert(data[4] == 0xFF); 967 assert(data[5] == 0xFF); 968 assert(data[6] == 0xFF); 969 assert(data[7] == 0xFF); 970 assert(data[8] == 0xFF); 971 } 972 973 /++ 974 +/ 975 size_t ionPutIntFieldR(T)(scope ubyte* ptr, const T num) 976 if (isSigned!T && isIntegral!T) 977 { 978 T value = num; 979 bool sign = value < 0; 980 if (sign) 981 value = cast(T)(0-value); 982 return ionPutIntFieldR!(Unsigned!T)(ptr, value, sign); 983 } 984 985 /++ 986 +/ 987 size_t ionPutIntFieldR(T)(scope ubyte* ptr, const T num, bool sign) 988 if (isUnsigned!T) 989 { 990 T value = num; 991 static if (T.sizeof >= 4) 992 { 993 auto c = cast(uint)ctlzp(value); 994 bool s = (c & 0x7) == 0; 995 enum ubyte cm = 0xF8 & (value.sizeof * 8 - 1); 996 c >>>= 3; 997 c = uint(T.sizeof) - c + s - ((value | sign) == 0); 998 value |= T(sign) << ((c - (c > T.sizeof)) * 8 - 1); 999 *cast(ubyte[T.sizeof]*)(ptr - T.sizeof) = byteData(value); 1000 *(ptr - T.sizeof - 1) = sign << 7; 1001 return c; 1002 } 1003 else 1004 { 1005 return ionPutIntFieldR!uint(ptr, value, sign); 1006 } 1007 } 1008 1009 /// 1010 @system pure nothrow @nogc 1011 version(mir_ion_test) unittest 1012 { 1013 ubyte[9] data; 1014 1015 alias AliasSeq(T...) = T; 1016 1017 foreach(T; AliasSeq!(ubyte, ushort, uint, ulong)) 1018 { 1019 data[] = 0; 1020 assert(ionPutIntFieldR!T(data.ptr + 9, 0, false) == 0, T.stringof); 1021 1022 data[] = 0; 1023 assert(ionPutIntFieldR!T(data.ptr + 9, 0, true) == 1); 1024 assert(data[$ - 1] == 0x80); 1025 1026 data[] = 0; 1027 assert(ionPutIntFieldR!T(data.ptr + 9, 1, false) == 1); 1028 assert(data[$ - 1] == 0x01); 1029 1030 data[] = 0; 1031 assert(ionPutIntFieldR!T(data.ptr + 9, 1, true) == 1); 1032 assert(data[$ - 1] == 0x81); 1033 1034 data[] = 0; 1035 assert(ionPutIntFieldR!T(data.ptr + 9, 0x3F, true) == 1); 1036 assert(data[$ - 1] == 0xBF); 1037 1038 data[] = 0; 1039 assert(ionPutIntFieldR!T(data.ptr + 9, 0xFF, false) == 2); 1040 assert(data[$ - 2] == 0x00); 1041 assert(data[$ - 1] == 0xFF); 1042 1043 data[] = 0; 1044 assert(ionPutIntFieldR!T(data.ptr + 9, 0xFF, true) == 2); 1045 assert(data[$ - 2] == 0x80); 1046 assert(data[$ - 1] == 0xFF); 1047 1048 data[] = 0; 1049 assert(ionPutIntFieldR!T(data.ptr + 9, 0x80, true) == 2); 1050 assert(data[$ - 2] == 0x80); 1051 assert(data[$ - 1] == 0x80); 1052 } 1053 1054 data[] = 0; 1055 assert(ionPutIntFieldR(data.ptr + 9, int.max) == 4); 1056 assert(data[5 + 0] == 0x7F); 1057 assert(data[5 + 1] == 0xFF); 1058 assert(data[5 + 2] == 0xFF); 1059 assert(data[5 + 3] == 0xFF); 1060 1061 data[] = 0; 1062 assert(ionPutIntFieldR(data.ptr + 9, int.min) == 5); 1063 assert(data[4 + 0] == 0x80); 1064 assert(data[4 + 1] == 0x80); 1065 assert(data[4 + 2] == 0x00); 1066 assert(data[4 + 3] == 0x00); 1067 assert(data[4 + 4] == 0x00); 1068 1069 data[] = 0; 1070 assert(ionPutIntFieldR(data.ptr + 9, long.max >> 1) == 8); 1071 assert(data[1 + 0] == 0x3F); 1072 assert(data[1 + 1] == 0xFF); 1073 assert(data[1 + 2] == 0xFF); 1074 assert(data[1 + 3] == 0xFF); 1075 assert(data[1 + 4] == 0xFF); 1076 assert(data[1 + 5] == 0xFF); 1077 assert(data[1 + 6] == 0xFF); 1078 assert(data[1 + 7] == 0xFF); 1079 1080 data[] = 0; 1081 assert(ionPutIntFieldR(data.ptr + 9, long.max) == 8); 1082 assert(data[1 + 0] == 0x7F); 1083 assert(data[1 + 1] == 0xFF); 1084 assert(data[1 + 2] == 0xFF); 1085 assert(data[1 + 3] == 0xFF); 1086 assert(data[1 + 4] == 0xFF); 1087 assert(data[1 + 5] == 0xFF); 1088 assert(data[1 + 6] == 0xFF); 1089 assert(data[1 + 7] == 0xFF); 1090 1091 data[] = 0xFF; 1092 assert(ionPutIntFieldR!ulong(data.ptr + 9, long.max + 1, false) == 9); 1093 assert(data[0] == 0x00); 1094 assert(data[1] == 0x80); 1095 assert(data[2] == 0x00); 1096 assert(data[3] == 0x00); 1097 assert(data[4] == 0x00); 1098 assert(data[5] == 0x00); 1099 assert(data[6] == 0x00); 1100 assert(data[7] == 0x00); 1101 assert(data[8] == 0x00); 1102 1103 data[] = 0; 1104 assert(ionPutIntFieldR(data.ptr + 9, ulong.max, true) == 9); 1105 assert(data[0] == 0x80); 1106 assert(data[1] == 0xFF); 1107 assert(data[2] == 0xFF); 1108 assert(data[3] == 0xFF); 1109 assert(data[4] == 0xFF); 1110 assert(data[5] == 0xFF); 1111 assert(data[6] == 0xFF); 1112 assert(data[7] == 0xFF); 1113 assert(data[8] == 0xFF); 1114 } 1115 1116 /++ 1117 +/ 1118 size_t ionPut(scope ubyte* ptr, typeof(null), IonTypeCode typeCode = IonTypeCode.null_) pure nothrow @nogc 1119 { 1120 *ptr++ = cast(ubyte) (0x0F | (typeCode << 4)); 1121 return 1; 1122 } 1123 1124 /// 1125 // @system pure nothrow @nogc 1126 version(mir_ion_test) unittest 1127 { 1128 ubyte[1] data; 1129 assert(ionPut(data.ptr, null) == 1); 1130 import mir.conv; 1131 assert(data[0] == 0x0F, data[0].to!string); 1132 } 1133 1134 /++ 1135 +/ 1136 size_t ionPut(T : bool)(scope ubyte* ptr, const T value) 1137 { 1138 *ptr++ = 0x10 | value; 1139 return 1; 1140 } 1141 1142 /// 1143 @system pure nothrow @nogc 1144 version(mir_ion_test) unittest 1145 { 1146 ubyte[1] data; 1147 assert(ionPut(data.ptr, true) == 1); 1148 assert(data[0] == 0x11); 1149 assert(ionPut(data.ptr, false) == 1); 1150 assert(data[0] == 0x10); 1151 } 1152 1153 /++ 1154 +/ 1155 size_t ionPut(T)(scope ubyte* ptr, const T value, bool sign = false) 1156 if (isUnsigned!T) 1157 { 1158 auto L = ionPutUIntField!T(ptr + 1, value); 1159 static if (T.sizeof <= 8) 1160 { 1161 *ptr = cast(ubyte) (0x20 | (sign << 4) | L); 1162 return L + 1; 1163 } 1164 else 1165 { 1166 static assert(0, "cent and ucent types not supported by mir.ion for now"); 1167 } 1168 } 1169 1170 /// 1171 @system pure nothrow @nogc 1172 version(mir_ion_test) unittest 1173 { 1174 ubyte[19] data = void; 1175 assert(ionPut(data.ptr, 0u) == 1); 1176 assert(data[0] == 0x20); 1177 assert(ionPut(data.ptr, 0u, true) == 1); 1178 assert(data[0] == 0x30); 1179 assert(ionPut(data.ptr, 0xFFu) == 2); 1180 assert(data[0] == 0x21); 1181 assert(data[1] == 0xFF); 1182 assert(ionPut(data.ptr, 0xFFu, true) == 2); 1183 assert(data[0] == 0x31); 1184 assert(data[1] == 0xFF); 1185 1186 assert(ionPut(data.ptr, ulong.max, true) == 9); 1187 assert(data[0] == 0x38); 1188 assert(data[1] == 0xFF); 1189 assert(data[2] == 0xFF); 1190 assert(data[3] == 0xFF); 1191 assert(data[4] == 0xFF); 1192 assert(data[5] == 0xFF); 1193 assert(data[6] == 0xFF); 1194 assert(data[7] == 0xFF); 1195 assert(data[8] == 0xFF); 1196 } 1197 1198 /++ 1199 +/ 1200 size_t ionPutR(T)(scope ubyte* ptr, const T value, bool sign = false) 1201 if (isUnsigned!T) 1202 { 1203 auto L = ionPutUIntFieldR!T(ptr, value); 1204 static if (T.sizeof <= 8) 1205 { 1206 *(ptr - (L + 1)) = cast(ubyte) (0x20 | (sign << 4) | L); 1207 return L + 1; 1208 } 1209 else 1210 { 1211 static assert(0, "cent and ucent types not supported by mir.ion for now"); 1212 } 1213 } 1214 1215 /// 1216 @system pure nothrow @nogc 1217 version(mir_ion_test) unittest 1218 { 1219 ubyte[19] data = void; 1220 assert(ionPutR(data.ptr + 1, 0u) == 1); 1221 assert(data[0] == 0x20); 1222 assert(ionPutR(data.ptr + 1, 0u, true) == 1); 1223 assert(data[0] == 0x30); 1224 assert(ionPutR(data.ptr + 2, 0xFFu) == 2); 1225 assert(data[0] == 0x21); 1226 assert(data[1] == 0xFF); 1227 assert(ionPutR(data.ptr + 2, 0xFFu, true) == 2); 1228 assert(data[0] == 0x31); 1229 assert(data[1] == 0xFF); 1230 1231 assert(ionPutR(data.ptr + 9, ulong.max, true) == 9); 1232 assert(data[0] == 0x38); 1233 assert(data[1] == 0xFF); 1234 assert(data[2] == 0xFF); 1235 assert(data[3] == 0xFF); 1236 assert(data[4] == 0xFF); 1237 assert(data[5] == 0xFF); 1238 assert(data[6] == 0xFF); 1239 assert(data[7] == 0xFF); 1240 assert(data[8] == 0xFF); 1241 } 1242 1243 /++ 1244 +/ 1245 size_t ionPut(T)(scope ubyte* ptr, const T value) 1246 if (isSigned!T && isIntegral!T) 1247 { 1248 bool sign = value < 0; 1249 T num = value; 1250 if (sign) 1251 num = cast(T)(0-num); 1252 return ionPut!(Unsigned!T)(ptr, num, sign); 1253 } 1254 1255 /// 1256 @("ionPutInteger") 1257 @system pure nothrow @nogc 1258 version(mir_ion_test) unittest 1259 { 1260 ubyte[19] data = void; 1261 assert(ionPut(data.ptr, -16) == 2); 1262 assert(data[0] == 0x31); 1263 assert(data[1] == 0x10); 1264 1265 assert(ionPut(data.ptr, 258) == 3); 1266 assert(data[0] == 0x22); 1267 assert(data[1] == 0x01); 1268 assert(data[2] == 0x02); 1269 } 1270 1271 private auto byteData(T)(const T value) 1272 if (__traits(isUnsigned, T)) 1273 { 1274 static if (T.sizeof == 1) 1275 { 1276 T num = value; 1277 } 1278 else 1279 version (LittleEndian) 1280 { 1281 import core.bitop: bswap; 1282 T num = bswap(value); 1283 } 1284 else 1285 { 1286 T num = value; 1287 } 1288 1289 ubyte[T.sizeof] data; 1290 1291 if (__ctfe) 1292 { 1293 foreach (ref d; data) 1294 { 1295 d = num & 0xFF; 1296 num >>= 8; 1297 } 1298 } 1299 else 1300 { 1301 data = cast(ubyte[T.sizeof])cast(T[1])[num]; 1302 } 1303 1304 return data; 1305 } 1306 1307 /++ 1308 +/ 1309 size_t ionPut(T)(scope ubyte* ptr, const T value) 1310 if (is(T == float)) 1311 { 1312 auto num = *cast(uint*)&value; 1313 auto s = (num != 0) << 2; 1314 *ptr = cast(ubyte)(0x40 + s); 1315 *cast(ubyte[4]*)(ptr + 1) = byteData(num); 1316 return 1 + s; 1317 } 1318 1319 /// 1320 @system pure nothrow @nogc 1321 version(mir_ion_test) unittest 1322 { 1323 ubyte[5] data; 1324 assert(ionPut(data.ptr, -16f) == 5); 1325 assert(data[0] == 0x44); 1326 assert(data[1] == 0xC1); 1327 assert(data[2] == 0x80); 1328 assert(data[3] == 0x00); 1329 assert(data[4] == 0x00); 1330 1331 assert(ionPut(data.ptr, 0f) == 1); 1332 assert(data[0] == 0x40); 1333 1334 assert(ionPut(data.ptr, -0f) == 5); 1335 assert(data[0] == 0x44); 1336 assert(data[1] == 0x80); 1337 assert(data[2] == 0x00); 1338 assert(data[3] == 0x00); 1339 assert(data[4] == 0x00); 1340 } 1341 1342 /++ 1343 +/ 1344 size_t ionPut(T)(scope ubyte* ptr, const T value) 1345 if (is(T == double)) 1346 { 1347 auto num = *cast(ulong*)&value; 1348 auto s = (num != 0) << 3; 1349 *ptr = cast(ubyte)(0x40 + s); 1350 *cast(ubyte[8]*)(ptr + 1) = byteData(num); 1351 return 1 + s; 1352 } 1353 1354 /// 1355 @system pure nothrow @nogc 1356 version(mir_ion_test) unittest 1357 { 1358 ubyte[9] data; 1359 assert(ionPut(data.ptr, -16.0) == 9); 1360 assert(data[0] == 0x48); 1361 assert(data[1] == 0xC0); 1362 assert(data[2] == 0x30); 1363 assert(data[3] == 0x00); 1364 assert(data[4] == 0x00); 1365 assert(data[5] == 0x00); 1366 assert(data[6] == 0x00); 1367 assert(data[7] == 0x00); 1368 assert(data[8] == 0x00); 1369 1370 assert(ionPut(data.ptr, 0.0) == 1); 1371 assert(data[0] == 0x40); 1372 1373 assert(ionPut(data.ptr, -0.0) == 9); 1374 assert(data[0] == 0x48); 1375 assert(data[1] == 0x80); 1376 assert(data[2] == 0x00); 1377 assert(data[3] == 0x00); 1378 assert(data[4] == 0x00); 1379 assert(data[5] == 0x00); 1380 assert(data[6] == 0x00); 1381 assert(data[7] == 0x00); 1382 assert(data[8] == 0x00); 1383 } 1384 1385 /++ 1386 +/ 1387 size_t ionPutR(T)(scope ubyte* ptr, const T value) 1388 if (is(T == double)) 1389 { 1390 auto num = *cast(ulong*)&value; 1391 auto s = (num != 0) << 3; 1392 *cast(ubyte[8]*)(ptr - double.sizeof) = byteData(num); 1393 *(ptr - (s + 1)) = cast(ubyte)(0x40 + s); 1394 return s + 1; 1395 } 1396 1397 /// 1398 @system pure nothrow @nogc 1399 version(mir_ion_test) unittest 1400 { 1401 ubyte[9] data; 1402 assert(ionPutR(data.ptr + data.length, -16.0) == 9); 1403 assert(data[0] == 0x48); 1404 assert(data[1] == 0xC0); 1405 assert(data[2] == 0x30); 1406 assert(data[3] == 0x00); 1407 assert(data[4] == 0x00); 1408 assert(data[5] == 0x00); 1409 assert(data[6] == 0x00); 1410 assert(data[7] == 0x00); 1411 assert(data[8] == 0x00); 1412 1413 assert(ionPutR(data.ptr + data.length, 0.0) == 1); 1414 assert(data[$ - 1] == 0x40); 1415 1416 assert(ionPutR(data.ptr + data.length, -0.0) == 9); 1417 assert(data[0] == 0x48); 1418 assert(data[1] == 0x80); 1419 assert(data[2] == 0x00); 1420 assert(data[3] == 0x00); 1421 assert(data[4] == 0x00); 1422 assert(data[5] == 0x00); 1423 assert(data[6] == 0x00); 1424 assert(data[7] == 0x00); 1425 assert(data[8] == 0x00); 1426 } 1427 1428 /++ 1429 +/ 1430 size_t ionPut(T)(scope ubyte* ptr, const T value) 1431 if (is(T == real)) 1432 { 1433 return ionPut!double(ptr, value); 1434 } 1435 1436 /// 1437 @system pure nothrow @nogc 1438 version(mir_ion_test) unittest 1439 { 1440 ubyte[9] data; 1441 assert(ionPut(data.ptr, -16.0L) == 9); 1442 assert(data[0] == 0x48); 1443 assert(data[1] == 0xC0); 1444 assert(data[2] == 0x30); 1445 assert(data[3] == 0x00); 1446 assert(data[4] == 0x00); 1447 assert(data[5] == 0x00); 1448 assert(data[6] == 0x00); 1449 assert(data[7] == 0x00); 1450 assert(data[8] == 0x00); 1451 1452 assert(ionPut(data.ptr, 0.0L) == 1); 1453 assert(data[0] == 0x40); 1454 1455 assert(ionPut(data.ptr, -0.0L) == 9); 1456 assert(data[0] == 0x48); 1457 assert(data[1] == 0x80); 1458 assert(data[2] == 0x00); 1459 assert(data[3] == 0x00); 1460 assert(data[4] == 0x00); 1461 assert(data[5] == 0x00); 1462 assert(data[6] == 0x00); 1463 assert(data[7] == 0x00); 1464 assert(data[8] == 0x00); 1465 } 1466 1467 /++ 1468 +/ 1469 size_t ionPut()( 1470 scope ubyte* ptr, 1471 BigUIntView!(const size_t) value, 1472 ) 1473 { 1474 return ionPut(ptr, value.signed); 1475 } 1476 1477 pure 1478 version(mir_ion_test) unittest 1479 { 1480 ubyte[32] data; 1481 // big unsigned integer 1482 assert(ionPut(data.ptr, BigUIntView!size_t.fromHexString("88BF4748507FB9900ADB624CCFF8D78897DC900FB0460327D4D86D327219").lightConst) == 32); 1483 assert(data[0] == 0x2E); 1484 assert(data[1] == 0x9E); 1485 // assert(data[2 .. 32] == BigUIntView!(ubyte, WordEndian.big).fromHexString("88BF4748507FB9900ADB624CCFF8D78897DC900FB0460327D4D86D327219").coefficients); 1486 } 1487 1488 /++ 1489 +/ 1490 size_t ionPut()( 1491 scope ubyte* ptr, 1492 BigIntView!(const size_t) value, 1493 ) 1494 { 1495 auto length = ionPutUIntField(ptr + 1, value.unsigned); 1496 auto q = 0x20 | (value.sign << 4); 1497 if (_expect(length < 0xE, true)) 1498 { 1499 *ptr = cast(ubyte)(q | length); 1500 return length + 1; 1501 } 1502 else 1503 { 1504 *ptr = cast(ubyte)(q | 0xE); 1505 ubyte[19] lengthPayload = void; 1506 auto lengthLength = ionPutVarUInt(lengthPayload.ptr, length); 1507 1508 if (__ctfe) 1509 { 1510 foreach_reverse (i; 0 .. length) 1511 ptr[i + 1 + lengthLength] = ptr[i + 1]; 1512 ptr[1 .. lengthLength + 1] = lengthPayload[0 .. lengthLength]; 1513 } 1514 else 1515 { 1516 memmove(ptr + 1 + lengthLength, ptr + 1, length); 1517 memcpy(ptr + 1, lengthPayload.ptr, lengthLength); 1518 } 1519 return length + 1 + lengthLength; 1520 } 1521 } 1522 1523 pure 1524 version(mir_ion_test) unittest 1525 { 1526 ubyte[9] data; 1527 // big unsigned integer 1528 assert(ionPut(data.ptr, -BigUIntView!size_t.fromHexString("45be").lightConst) == 3); 1529 assert(data[0] == 0x32); 1530 assert(data[1] == 0x45); 1531 assert(data[2] == 0xbe); 1532 } 1533 1534 /++ 1535 +/ 1536 size_t ionPut()( 1537 scope ubyte* ptr, 1538 DecimalView!(const size_t) value, 1539 ) 1540 { 1541 size_t length; 1542 if (value.coefficient.coefficients.length == 0 && value.sign == false && value.exponent == 0) 1543 goto L; 1544 length = ionPutVarInt(ptr + 1, value.exponent); 1545 length += ionPutIntField(ptr + 1 + length, value.signedCoefficient); 1546 if (_expect(length < 0xE, true)) 1547 { 1548 L: 1549 *ptr = cast(ubyte)(0x50 | length); 1550 return length + 1; 1551 } 1552 else 1553 { 1554 *ptr = 0x5E; 1555 ubyte[19] lengthPayload = void; 1556 auto lengthLength = ionPutVarUInt(lengthPayload.ptr, length); 1557 if (__ctfe) 1558 { 1559 foreach_reverse (i; 0 .. length) 1560 ptr[i + 1 + lengthLength] = ptr[i + 1]; 1561 ptr[1 .. lengthLength + 1] = lengthPayload[0 .. lengthLength]; 1562 } 1563 else 1564 { 1565 memmove(ptr + 1 + lengthLength, ptr + 1, length); 1566 memcpy(ptr + 1, lengthPayload.ptr, lengthLength); 1567 } 1568 return length + 1 + lengthLength; 1569 } 1570 } 1571 1572 pure 1573 version(mir_ion_test) unittest 1574 { 1575 ubyte[34] data; 1576 // 0.6 1577 assert(ionPut(data.ptr, DecimalView!size_t(false, -1, BigUIntView!size_t.fromHexString("06")).lightConst) == 3); 1578 assert(data[0] == 0x52); 1579 assert(data[1] == 0xC1); 1580 assert(data[2] == 0x06); 1581 1582 // -0.6 1583 assert(ionPut(data.ptr, DecimalView!size_t(true, -1, BigUIntView!size_t.fromHexString("06")).lightConst) == 3); 1584 assert(data[0] == 0x52); 1585 assert(data[1] == 0xC1); 1586 assert(data[2] == 0x86); 1587 1588 1589 // 0e-3 1590 assert(ionPut(data.ptr, DecimalView!size_t(false, 3, BigUIntView!size_t([0])).lightConst) == 2); 1591 assert(data[0] == 0x51); 1592 assert(data[1] == 0x83); 1593 1594 // -0e+0 1595 assert(ionPut(data.ptr, DecimalView!size_t(true, 0, BigUIntView!size_t([0])).lightConst) == 3); 1596 assert(data[0] == 0x52); 1597 assert(data[1] == 0x80); 1598 assert(data[2] == 0x80); 1599 1600 // 0e+0 1601 assert(ionPut(data.ptr, DecimalView!size_t(false, 0, BigUIntView!size_t([0])).lightConst) == 2); 1602 assert(data[0] == 0x51); 1603 assert(data[1] == 0x80); 1604 1605 // 0e+0 (minimal) 1606 assert(ionPut(data.ptr, DecimalView!size_t(false, 0, BigUIntView!size_t.init).lightConst) == 1); 1607 assert(data[0] == 0x50); 1608 1609 // big decimal 1610 assert(ionPut(data.ptr, DecimalView!size_t(false, -9, BigUIntView!size_t.fromHexString("88BF4748507FB9900ADB624CCFF8D78897DC900FB0460327D4D86D327219")).lightConst) == 34); 1611 assert(data[0] == 0x5E); 1612 assert(data[1] == 0xA0); 1613 assert(data[2] == 0xC9); 1614 assert(data[3] == 0x00); 1615 // assert(data[4 .. 34] == BigUIntView!(ubyte, WordEndian.big).fromHexString("88BF4748507FB9900ADB624CCFF8D78897DC900FB0460327D4D86D327219").coefficients); 1616 1617 // -12.345 1618 // assert( >=0); 1619 assert(ionPut(data.ptr, DecimalView!size_t(true, -3, BigUIntView!size_t.fromHexString("3039")).lightConst) == 4); 1620 assert(data[0] == 0x53); 1621 assert(data[1] == 0xC3); 1622 assert(data[2] == 0xB0); 1623 assert(data[3] == 0x39); 1624 // assert(data[0] == 0x50); 1625 } 1626 1627 /// 1628 size_t ionPutDecimal()(scope ubyte* ptr, bool sign, ulong coefficient, long exponent) 1629 { 1630 version(LDC) 1631 pragma(inline, true); 1632 size_t length; 1633 // if (coefficient == 0) 1634 // goto L; 1635 length = ionPutVarInt(ptr + 1, exponent); 1636 length += ionPutIntField(ptr + 1 + length, coefficient, sign); 1637 if (_expect(length < 0xE, true)) 1638 { 1639 L: 1640 *ptr = cast(ubyte)(0x50 | length); 1641 return length + 1; 1642 } 1643 else 1644 { 1645 memmove(ptr + 2, ptr + 1, 16); 1646 *ptr = 0x5E; 1647 assert(length < 0x80); 1648 ptr[1] = cast(ubyte) (length ^ 0x80); 1649 return length + 2; 1650 } 1651 } 1652 1653 /// 1654 size_t ionPutDecimalR()(scope ubyte* ptr, bool sign, ulong coefficient, long exponent) 1655 { 1656 version(LDC) 1657 pragma(inline, true); 1658 size_t length; 1659 // if (coefficient == 0) 1660 // goto L; 1661 length = ionPutIntFieldR(ptr, coefficient, sign); 1662 length += ionPutVarIntR(ptr - length, exponent); 1663 ptr -= length; 1664 if (_expect(length < 0xE, true)) 1665 { 1666 L: 1667 *--ptr = cast(ubyte)(0x50 | length); 1668 return length + 1; 1669 } 1670 else 1671 { 1672 *--ptr = cast(ubyte)(0x80 | length); 1673 *--ptr = 0x5E; 1674 return length + 2; 1675 } 1676 } 1677 1678 /++ 1679 +/ 1680 size_t ionPut(T)(scope ubyte* ptr, const T value) 1681 if (is(T == Timestamp)) 1682 { 1683 size_t ret = 1; 1684 ret += value.isLocalTime ? 1685 ionPutVarInt(ptr + ret, ubyte.init, true): 1686 ionPutVarInt(ptr + ret, value.offset); 1687 ret += ionPutVarUInt(ptr + ret, cast(ushort)value.year); 1688 if (value.precision >= Timestamp.precision.month) 1689 { 1690 ptr[ret++] = cast(ubyte) (0x80 | value.month); 1691 if (value.precision >= Timestamp.precision.day) 1692 { 1693 ptr[ret++] = cast(ubyte) (0x80 | value.day); 1694 if (value.precision >= Timestamp.precision.minute) 1695 { 1696 ptr[ret++] = cast(ubyte) (0x80 | value.hour); 1697 ptr[ret++] = cast(ubyte) (0x80 | value.minute); 1698 if (value.precision >= Timestamp.precision.second) 1699 { 1700 ptr[ret++] = cast(ubyte) (0x80 | value.second); 1701 if (value.precision > Timestamp.precision.second) //fraction 1702 { 1703 ret += ionPutVarInt(ptr + ret, value.fractionExponent); 1704 ret += ionPutIntField(ptr + ret, long(value.fractionCoefficient)); 1705 } 1706 } 1707 } 1708 } 1709 } 1710 auto length = ret - 1; 1711 if (_expect(ret < 0xF, true)) 1712 { 1713 *ptr = cast(ubyte) (0x60 | length); 1714 return ret; 1715 } 1716 else 1717 { 1718 if (__ctfe) 1719 foreach_reverse (i; 0 .. length) 1720 ptr[i + 2] = ptr[i + 1]; 1721 else 1722 memmove(ptr + 2, ptr + 1, length); 1723 *ptr = 0x6E; 1724 ptr[1] = cast(ubyte) (0x80 | length); 1725 return ret + 1; 1726 } 1727 } 1728 1729 /// 1730 version(mir_ion_test) unittest 1731 { 1732 import mir.timestamp; 1733 1734 ubyte[20] data; 1735 1736 ubyte[] result = [0x68, 0x80, 0x0F, 0xD0, 0x87, 0x88, 0x82, 0x83, 0x84]; 1737 auto ts = Timestamp(2000, 7, 8, 2, 3, 4).withOffset(0); 1738 assert(data[0 .. ionPut(data.ptr, ts)] == result); 1739 1740 result = [0x69, 0x80, 0x0F, 0xD0, 0x87, 0x88, 0x82, 0x83, 0x84, 0xC2]; 1741 ts = Timestamp(2000, 7, 8, 2, 3, 4, -2, 0).withOffset(0); 1742 assert(data[0 .. ionPut(data.ptr, ts)] == result); 1743 1744 result = [0x6A, 0x80, 0x0F, 0xD0, 0x87, 0x88, 0x82, 0x83, 0x84, 0xC3, 0x10]; 1745 ts = Timestamp(2000, 7, 8, 2, 3, 4, -3, 16).withOffset(0); 1746 assert(data[0 .. ionPut(data.ptr, ts)] == result); 1747 } 1748 1749 /++ 1750 +/ 1751 size_t ionPut(T)(scope ubyte* ptr, const T value) 1752 if (is(T == Date)) 1753 { 1754 size_t ret = 1; 1755 auto ymd = value.yearMonthDay; 1756 ptr[ret++] = 0x80; 1757 ret += ionPutVarUInt(ptr + ret, cast(ushort)value.year); 1758 ptr[ret++] = cast(ubyte) (0x80 | value.month); 1759 ptr[ret++] = cast(ubyte) (0x80 | value.day); 1760 auto length = ret - 1; 1761 *ptr = cast(ubyte) (0x60 | length); 1762 return ret; 1763 } 1764 1765 /// 1766 version(mir_ion_test) unittest 1767 { 1768 import mir.date; 1769 1770 ubyte[13] data; 1771 1772 ubyte[] result = [0x65, 0x80, 0x0F, 0xD0, 0x87, 0x88]; 1773 auto ts = Date(2000, 7, 8); 1774 assert(data[0 .. ionPut(data.ptr, ts)] == result); 1775 } 1776 1777 /++ 1778 +/ 1779 size_t ionPutSymbolId(T)(scope ubyte* ptr, const T value) 1780 if (isUnsigned!T) 1781 { 1782 auto length = ionPutUIntField(ptr + 1, value); 1783 *ptr = cast(ubyte)(0x70 | length); 1784 return length + 1; 1785 } 1786 1787 /// 1788 version(mir_ion_test) unittest 1789 { 1790 ubyte[8] data; 1791 1792 ubyte[] result = [0x72, 0x01, 0xFF]; 1793 auto id = 0x1FFu; 1794 assert(data[0 .. ionPutSymbolId(data.ptr, id)] == result); 1795 } 1796 1797 /++ 1798 +/ 1799 size_t ionPutSymbolId(T)(scope ubyte* ptr, BigUIntView!T value) 1800 { 1801 auto length = ionPutUIntField(ptr + 1, value); 1802 assert(length < 10); 1803 *ptr = cast(ubyte)(0x70 | length); 1804 return length + 1; 1805 } 1806 1807 /// 1808 version(mir_ion_test) unittest 1809 { 1810 import mir.bignum.low_level_view: BigUIntView; 1811 1812 ubyte[8] data; 1813 1814 ubyte[] result = [0x72, 0x01, 0xFF]; 1815 // auto id = BigUIntView!(ubyte, WordEndian.big).fromHexString("1FF"); 1816 // assert(data[0 .. ionPutSymbolId(data.ptr, id)] == result); 1817 } 1818 1819 /++ 1820 +/ 1821 size_t ionPut()(scope ubyte* ptr, scope const(char)[] value) 1822 { 1823 size_t ret = 1; 1824 if (value.length < 0xE) 1825 { 1826 *ptr = cast(ubyte) (0x80 | value.length); 1827 } 1828 else 1829 { 1830 *ptr = 0x8E; 1831 ret += ionPutVarUInt(ptr + 1, value.length); 1832 } 1833 if (__ctfe) 1834 ptr[ret .. ret + value.length] = cast(const(ubyte)[])value; 1835 else 1836 memcpy(ptr + ret, value.ptr, value.length); 1837 return ret + value.length; 1838 } 1839 1840 /// 1841 version(mir_ion_test) unittest 1842 { 1843 ubyte[20] data; 1844 1845 ubyte[] result = [0x85, 'v', 'a', 'l', 'u', 'e']; 1846 auto str = "value"; 1847 assert(data[0 .. ionPut(data.ptr, str)] == result); 1848 1849 result = [ubyte(0x8E), ubyte(0x90)] ~ cast(ubyte[])"hexadecimal23456"; 1850 str = "hexadecimal23456"; 1851 assert(data[0 .. ionPut(data.ptr, str)] == result); 1852 } 1853 1854 /++ 1855 +/ 1856 size_t ionPut(T)(scope ubyte* ptr, const T value) 1857 if (is(T == Clob)) 1858 { 1859 size_t ret = 1; 1860 if (value.data.length < 0xE) 1861 { 1862 *ptr = cast(ubyte) (0x90 | value.data.length); 1863 } 1864 else 1865 { 1866 *ptr = 0x9E; 1867 ret += ionPutVarUInt(ptr + 1, value.data.length); 1868 } 1869 memcpy(ptr + ret, value.data.ptr, value.data.length); 1870 return ret + value.data.length; 1871 } 1872 1873 /// 1874 version(mir_ion_test) unittest 1875 { 1876 import mir.lob; 1877 1878 ubyte[20] data; 1879 1880 ubyte[] result = [0x95, 'v', 'a', 'l', 'u', 'e']; 1881 auto str = Clob("value"); 1882 assert(data[0 .. ionPut(data.ptr, str)] == result); 1883 1884 result = [ubyte(0x9E), ubyte(0x90)] ~ cast(ubyte[])"hexadecimal23456"; 1885 str = Clob("hexadecimal23456"); 1886 assert(data[0 .. ionPut(data.ptr, str)] == result); 1887 } 1888 1889 /++ 1890 +/ 1891 size_t ionPut(T)(scope ubyte* ptr, const T value) 1892 if (is(T == Blob)) 1893 { 1894 size_t ret = 1; 1895 if (value.data.length < 0xE) 1896 { 1897 *ptr = cast(ubyte) (0xA0 | value.data.length); 1898 } 1899 else 1900 { 1901 *ptr = 0xAE; 1902 ret += ionPutVarUInt(ptr + 1, value.data.length); 1903 } 1904 memcpy(ptr + ret, value.data.ptr, value.data.length); 1905 return ret + value.data.length; 1906 } 1907 1908 /// 1909 version(mir_ion_test) unittest 1910 { 1911 import mir.lob; 1912 1913 ubyte[20] data; 1914 1915 ubyte[] result = [0xA5, 'v', 'a', 'l', 'u', 'e']; 1916 auto payload = Blob(cast(ubyte[])"value"); 1917 assert(data[0 .. ionPut(data.ptr, payload)] == result); 1918 1919 result = [ubyte(0xAE), ubyte(0x90)] ~ cast(ubyte[])"hexadecimal23456"; 1920 payload = Blob(cast(ubyte[])"hexadecimal23456"); 1921 assert(data[0 .. ionPut(data.ptr, payload)] == result); 1922 } 1923 1924 /++ 1925 +/ 1926 size_t ionPutStartLength()() 1927 { 1928 return 3; 1929 } 1930 1931 /++ 1932 +/ 1933 size_t ionPutEmpty()(ubyte* startPtr, IonTypeCode tc) 1934 { 1935 version(LDC) pragma(inline, true); 1936 assert (tc == IonTypeCode..string || tc == IonTypeCode.list || tc == IonTypeCode.sexp || tc == IonTypeCode.struct_ || tc == IonTypeCode.annotations); 1937 auto tck = tc << 4; 1938 *startPtr = cast(ubyte) tck; 1939 return 1; 1940 } 1941 1942 /++ 1943 +/ 1944 size_t ionPutEnd()(ubyte* startPtr, IonTypeCode tc, size_t totalElementLength) 1945 { 1946 version(LDC) pragma(inline, true); 1947 assert (tc == IonTypeCode..string || tc == IonTypeCode.list || tc == IonTypeCode.sexp || tc == IonTypeCode.struct_ || tc == IonTypeCode.annotations); 1948 auto tck = tc << 4; 1949 if (totalElementLength < 0xE) 1950 { 1951 *startPtr = cast(ubyte) (tck | totalElementLength); 1952 if (__ctfe) 1953 foreach (i; 0 .. totalElementLength) 1954 startPtr[i + 1] = startPtr[i + 3]; 1955 else 1956 memmove(startPtr + 1, startPtr + 3, 16); 1957 debug { 1958 startPtr[totalElementLength + 1] = 0xFF; 1959 startPtr[totalElementLength + 2] = 0xFF; 1960 } 1961 return 1 + totalElementLength; 1962 } 1963 *startPtr = cast(ubyte)(tck | 0xE); 1964 if (totalElementLength < 0x80) 1965 { 1966 startPtr[1] = cast(ubyte) (0x80 | totalElementLength); 1967 if (__ctfe) 1968 foreach (i; 0 .. totalElementLength) 1969 startPtr[i + 2] = startPtr[i + 3]; 1970 else 1971 memmove(startPtr + 2, startPtr + 3, 128); 1972 debug { 1973 startPtr[totalElementLength + 2] = 0xFF; 1974 } 1975 return 2 + totalElementLength; 1976 } 1977 if (totalElementLength < 0x4000) 1978 { 1979 startPtr[1] = cast(ubyte) (totalElementLength >> 7); 1980 startPtr[2] = cast(ubyte) (totalElementLength | 0x80); 1981 return 3 + totalElementLength; 1982 } 1983 ubyte[19] lengthPayload = void; 1984 auto lengthLength = ionPutVarUInt(lengthPayload.ptr, totalElementLength); 1985 if (__ctfe) 1986 { 1987 foreach_reverse (i; 0 .. totalElementLength) 1988 startPtr[i + 1 + lengthLength] = startPtr[i + 3]; 1989 startPtr[1 .. lengthLength + 1] = lengthPayload[0 .. lengthLength]; 1990 } 1991 else 1992 { 1993 memmove(startPtr + 1 + lengthLength, startPtr + 3, totalElementLength); 1994 memcpy(startPtr + 1, lengthPayload.ptr, lengthLength); 1995 } 1996 return totalElementLength + 1 + lengthLength; 1997 } 1998 1999 /// 2000 version(mir_ion_test) unittest 2001 { 2002 import mir.ion.type_code; 2003 2004 ubyte[1024] data; 2005 auto pos = ionPutStartLength; 2006 2007 ubyte[] result = [0xB0]; 2008 assert(data[0 .. ionPutEnd(data.ptr, IonTypeCode.list, 0)] == result); 2009 2010 result = [ubyte(0xB6), ubyte(0x85)] ~ cast(ubyte[])"hello"; 2011 auto len = ionPut(data.ptr + pos, "hello"); 2012 assert(data[0 .. ionPutEnd(data.ptr, IonTypeCode.list, len)] == result); 2013 2014 result = [0xCE, 0x90, 0x8E, 0x8E]; 2015 result ~= cast(ubyte[])"hello world!!!"; 2016 len = ionPut(data.ptr + pos, "hello world!!!"); 2017 assert(data[0 .. ionPutEnd(data.ptr, IonTypeCode.sexp, len)] == result); 2018 2019 auto bm = ` 2020 Generating test runner configuration 'mir-ion-test-library' for 'library' (library). 2021 Performing "unittest" build using /Users/9il/dlang/ldc2/bin/ldc2 for x86_64. 2022 mir-core 1.1.7: target for configuration "library" is up to date. 2023 mir-algorithm 3.9.2: target for configuration "default" is up to date. 2024 mir-cpuid 1.2.6: target for configuration "library" is up to date. 2025 mir-ion 0.5.7+commit.70.g7dcac11: building configuration "mir-ion-test-library"... 2026 Linking... 2027 To force a rebuild of up-to-date targets, run again with --force. 2028 Running ./mir-ion-test-library`; 2029 2030 result = [0xBE, 0x04, 0xB0, 0x8E, 0x04, 0xAD]; 2031 result ~= cast(ubyte[])bm; 2032 len = ionPut(data.ptr + pos, bm); 2033 assert(data[0 .. ionPutEnd(data.ptr, IonTypeCode.list, len)] == result); 2034 } 2035 2036 /++ 2037 +/ 2038 size_t ionPutAnnotationsListStartLength()() 2039 { 2040 return 1; 2041 } 2042 2043 /++ 2044 +/ 2045 size_t ionPutAnnotationsListEnd()(ubyte* startPtr, size_t totalElementLength) 2046 { 2047 if (_expect(totalElementLength < 0x80, true)) 2048 { 2049 startPtr[0] = cast(ubyte) (0x80 | totalElementLength); 2050 return 1 + totalElementLength; 2051 } 2052 else 2053 { 2054 ubyte[19] lengthPayload = void; 2055 auto lengthLength = ionPutVarUInt(lengthPayload.ptr, totalElementLength); 2056 if (__ctfe) 2057 { 2058 foreach_reverse (i; 0 .. totalElementLength) 2059 startPtr[lengthLength] = startPtr[i + 1]; 2060 startPtr[0 .. lengthLength] = lengthPayload[0 .. lengthLength]; 2061 } 2062 else 2063 { 2064 memmove(startPtr + lengthLength, startPtr + 1, totalElementLength); 2065 memcpy(startPtr, lengthPayload.ptr, lengthLength); 2066 } 2067 return totalElementLength + lengthLength; 2068 } 2069 } 2070 2071 /// 2072 size_t ionPutEndR(ubyte* ptr, IonTypeCode type, size_t length) 2073 pure nothrow @nogc 2074 { 2075 if (length < 0xE) 2076 { 2077 *--ptr = cast(ubyte) ((type << 4) | length); 2078 return 1; 2079 } 2080 else 2081 { 2082 length = ionPutVarUIntR(ptr, length); 2083 *(ptr - (length + 1)) = cast(ubyte) ((type << 4) | 0xE); 2084 return length + 1; 2085 } 2086 } 2087 2088 /// 2089 size_t ionPutVarUIntR(ubyte* ptr, size_t length) 2090 pure nothrow @nogc 2091 { 2092 auto safe = ptr; 2093 do *--ptr = length & 0x7F; 2094 while (length >>>= 7); 2095 *(safe - 1) |= 0x80; 2096 return safe - ptr; 2097 }