1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.util.Serialize; 13 14 import std.traits; 15 import std.string; 16 import core.stdc.string; 17 import std.stdio; 18 import std.bitmanip; 19 import std.math; 20 public import std.json; 21 22 public: 23 enum IGNORE = 1024; 24 25 class UnIgnoreArray{ 26 27 void setUnIgnore(T)() 28 { 29 _unIgnore[T.stringof] = true; 30 } 31 32 bool ignore(T)() 33 { 34 return T.stringof !in _unIgnore; 35 } 36 37 private: 38 bool[string] _unIgnore; 39 } 40 41 42 private: 43 44 class RefClass 45 { 46 size_t[size_t] map; 47 void*[] arr; 48 uint level; 49 bool ignore; /// all class or struct ignore or not. 50 UnIgnoreArray unIgnore; /// part class unignore. 51 } 52 53 enum MAGIC_KEY = "o0o0o"; 54 55 enum bool isType(T1, T2) = is(T1 == T2) || is(T1 == ImmutableOf!T2) 56 || is(T1 == ConstOf!T2) || is(T1 == InoutOf!T2) 57 || is(T1 == SharedOf!T2) || is(T1 == SharedConstOf!T2) || is(T1 == SharedInoutOf!T2); 58 59 enum bool isSignedType(T) = isType!(T, byte) || isType!(T, short) || isType!(T, 60 int) || isType!(T, long); 61 enum bool isUnsignedType(T) = isType!(T, ubyte) || isType!(T, ushort) 62 || isType!(T, uint) || isType!(T, ulong); 63 enum bool isBigSignedType(T) = isType!(T, int) || isType!(T, long); 64 enum bool isBigUnsignedType(T) = isType!(T, uint) || isType!(T, ulong); 65 66 //unsigned 67 ulong[] byte_dots = [1 << 7, 1 << 14, 1 << 21, 1 << 28, cast(ulong) 1 << 35, 68 cast(ulong) 1 << 42, cast(ulong) 1 << 49, cast(ulong) 1 << 56, cast(ulong) 1 << 63,]; 69 70 //signed 71 ulong[] byte_dots_s = [1 << 6, 1 << 13, 1 << 20, 1 << 27, cast(ulong) 1 << 34, 72 cast(ulong) 1 << 41, cast(ulong) 1 << 48, cast(ulong) 1 << 55, cast(ulong) 1 << 62,]; 73 74 ubyte getbytenum(ulong v) 75 { 76 ubyte i = 0; 77 for (; i < byte_dots.length; i++) 78 { 79 if (v < byte_dots[i]) 80 { 81 break; 82 } 83 } 84 return cast(ubyte)(i + 1); 85 } 86 87 ubyte getbytenums(ulong v) 88 { 89 ubyte i = 0; 90 for (; i < byte_dots_s.length; i++) 91 { 92 if (v < byte_dots_s[i]) 93 { 94 break; 95 } 96 } 97 98 return cast(ubyte)(i + 1); 99 } 100 101 //signed 102 byte[] toVariant(T)(T t) if (isSignedType!T) 103 { 104 bool symbol = false; 105 if (t < 0) 106 symbol = true; 107 108 ulong val = cast(ulong) abs(t); 109 110 ubyte num = getbytenums(val); 111 112 ubyte[] var; 113 if(num == 1) 114 { 115 if (symbol) 116 val = val | 0x40; 117 } 118 else{ 119 for (size_t i = num; i > 1; i--) 120 { 121 auto n = val / (byte_dots_s[i - 2] * 2); 122 if (symbol && i == num) 123 n = n | 0x40; 124 var ~= cast(ubyte) n; 125 val = (val % (byte_dots_s[i - 2] * 2)); 126 } 127 } 128 129 var ~= cast(ubyte)(val | 0x80); 130 return cast(byte[]) var; 131 } 132 133 T toT(T)(const byte[] b, out long index) if (isSignedType!T) 134 { 135 T val = 0; 136 ubyte i = 0; 137 bool symbol = false; 138 139 if(b.length == 1) 140 { 141 val = (b[i] & 0x3F); 142 if (b[i] & 0x40) 143 symbol = true; 144 } 145 else 146 { 147 for (i = 0; i < b.length; i++) 148 { 149 if (i == 0) 150 { 151 val = (b[i] & 0x3F); 152 if (b[i] & 0x40) 153 symbol = true; 154 } 155 else 156 { 157 val = cast(T)((val << 7) + (b[i] & 0x7F)); 158 } 159 160 if (b[i] & 0x80) 161 break; 162 } 163 } 164 165 index = i + 1; 166 if (symbol) 167 return cast(T)(val * -1); 168 else 169 return val; 170 } 171 172 //unsigned 173 byte[] toVariant(T)(T t) if (isUnsignedType!T) 174 { 175 ubyte num = getbytenum(cast(ulong) t); 176 T val = t; 177 ubyte[] var; 178 for (size_t i = num; i > 1; i--) 179 { 180 auto n = val / (byte_dots[i - 2]); 181 var ~= cast(ubyte) n; 182 val = val % (byte_dots[i - 2]); 183 } 184 var ~= cast(ubyte)(val | 0x80); 185 return cast(byte[]) var; 186 } 187 188 //unsigned 189 T toT(T)(const byte[] b, out long index) if (isUnsignedType!T) 190 { 191 T val = 0; 192 ubyte i = 0; 193 for (i = 0; i < b.length; i++) 194 { 195 196 val = cast(T)((val << 7) + (b[i] & 0x7F)); 197 if (b[i] & 0x80) 198 break; 199 } 200 index = i + 1; 201 return val; 202 } 203 204 byte getbasictype(long size) 205 { 206 if (size == 1) 207 return 0; 208 else if (size == 2) 209 return 1; 210 else if (size == 4) 211 return 2; 212 else if (size == 8) 213 return 3; 214 else 215 assert(0); 216 } 217 218 byte getbasicsize(byte type) 219 { 220 if (type == 0) 221 return 1; 222 else if (type == 1) 223 return 2; 224 else if (type == 2) 225 return 4; 226 else if (type == 3) 227 return 8; 228 else 229 assert(0); 230 } 231 232 string serializeMembers(T)() 233 { 234 string str; 235 foreach (m; FieldNameTuple!T) 236 { 237 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 238 { 239 str ~= "data ~= serialize(t." ~ m ~ " , stack , level + 1);"; 240 } 241 } 242 return str; 243 } 244 245 string unserializeMembers(T)() 246 { 247 string str; 248 str ~= "long parse = 0; "; 249 foreach (m; FieldNameTuple!T) 250 { 251 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 252 { 253 str ~= " if ( index < parse_index)"; 254 str ~= "{"; 255 str ~= "t." ~ m ~ " = unserialize!(typeof(t." ~ m 256 ~ "))(data[cast(uint)index .. data.length] , parse , stack); "; 257 str ~= "index += parse; }"; 258 } 259 260 } 261 return str; 262 } 263 264 string getsizeMembers(T)() 265 { 266 string str; 267 foreach (m; FieldNameTuple!T) 268 { 269 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 270 { 271 str ~= "total += getsize(t." ~ m ~ " , stack , level + 1);"; 272 } 273 } 274 return str; 275 } 276 277 /////////////////////////////////////////////////////////// 278 // basic 279 // type size 280 // 0 - 1 281 // 1 - 2 282 // 2 - 4 283 // 3 - 8 284 // data 285 /////////////////////////////////////////////////////////// 286 /// 287 byte[] serialize(T)(T t, RefClass stack, uint level) 288 if (isScalarType!T && !isBigSignedType!T && !isBigUnsignedType!T && !is(T == enum)) 289 { 290 byte[] data; 291 data.length = T.sizeof + 1; 292 data[0] = getbasictype(T.sizeof); 293 memcpy(data.ptr + 1, &t, T.sizeof); 294 return data; 295 } 296 297 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 298 if (isScalarType!T && !isBigSignedType!T && !isBigUnsignedType!T && !is(T == enum)) 299 { 300 assert(cast(byte) T.sizeof == getbasicsize(data[0])); 301 302 T value; 303 memcpy(&value, data.ptr + 1, T.sizeof); 304 305 parse_index = T.sizeof + 1; 306 return value; 307 } 308 309 size_t getsize(T)(T t, RefClass stack, uint level) 310 if (isScalarType!T && !isBigSignedType!T && !isBigUnsignedType!T && !is(T == enum)) 311 { 312 return T.sizeof + 1; 313 } 314 315 /////////////////////////////////////////////////////////// 316 // variant 317 // type size 318 // 5 (4) - 319 // 6 (8) - 320 // data 321 /////////////////////////////////////////////////////////// 322 byte[] serialize(T)(T t, RefClass stack, uint level) 323 if (isBigSignedType!T || isBigUnsignedType!T) 324 { 325 byte[] data = toVariant!T(t); 326 long index; 327 byte[1] h; 328 h[0] = (T.sizeof == 4) ? 5 : 8; 329 return h ~ data; 330 } 331 332 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 333 if (isBigSignedType!T || isBigUnsignedType!T) 334 { 335 assert((T.sizeof == 4 ? 5 : 8) == data[0]); 336 long index; 337 T t = toT!T(data[1 .. $], index); 338 parse_index = index + 1; 339 return t; 340 } 341 342 size_t getsize(T)(T t, RefClass stack, uint level) if (isBigSignedType!T) 343 { 344 return getbytenums(abs(t)) + 1; 345 } 346 347 size_t getsize(T)(T t, RefClass stack, uint level) if (isBigUnsignedType!T) 348 { 349 return getbytenum(abs(t)) + 1; 350 } 351 352 // TString 353 // 1 type 7 354 // [uint] variant 355 // data 356 357 byte[] serialize(T)(T str, RefClass stack, uint level) if (is(T == string)) 358 { 359 byte[] data; 360 uint len = cast(uint) str.length; 361 byte[] dlen = toVariant(len); 362 data.length = 1 + dlen.length + len; 363 364 data[0] = 7; 365 memcpy(data.ptr + 1, dlen.ptr, dlen.length); 366 memcpy(data.ptr + 1 + dlen.length, str.ptr, len); 367 return data; 368 } 369 370 string unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 371 if (is(T == string)) 372 { 373 assert(data[0] == 7); 374 long index; 375 uint len = toT!uint(data[1 .. $], index); 376 parse_index += 1 + index + len; 377 return cast(T)(data[cast(size_t)(1 + index) .. cast(size_t) parse_index].dup); 378 } 379 380 size_t getsize(T)(T str, RefClass stack, uint level) if (is(T == string)) 381 { 382 uint len = cast(uint) str.length; 383 return cast(size_t)(1 + toVariant(len).length + str.length); 384 } 385 386 // TUnion don't support TUnion 387 // 1 type 6 388 // 1 len 389 // data 390 391 /* 392 byte[] serialize(T)(T t) if(is(T == union)) 393 { 394 byte[] data; 395 data.length = T.sizeof + 2; 396 data[0] = 5; 397 data[1] = T.sizeof; 398 memcpy(data.ptr + 2 , &t , T.sizeof); 399 return data; 400 } 401 T unserialize(T)(const byte[] data ) if(is(T == union)) 402 { 403 long parser_index; 404 return unserialize!T(data , parser_index); 405 } 406 T unserialize(T)(const byte[] data , out long parse_index) if(is(T == union)) 407 { 408 assert(data[0] == 5); 409 410 T value; 411 byte len; 412 memcpy(&len , data.ptr + 1 , 1); 413 parse_index = 2 + len; 414 memcpy(&value , data.ptr + 2 , len); 415 return value; 416 } 417 size_t getsize(T)(T t) if(is(T == union)) 418 { 419 return 2 + T.sizeof; 420 } 421 */ 422 423 // TSArray 424 // 1 type 8 425 // size[uint] variant 426 // len[uint] variant 427 // data 428 429 byte[] serialize(T)(T t, RefClass stack, uint level) if (isStaticArray!T) 430 { 431 byte[1] header; 432 header[0] = 8; 433 uint uSize = cast(uint) t.length; 434 byte[] dh = cast(byte[]) header; 435 dh ~= toVariant(uSize); 436 437 byte[] data; 438 for (size_t i = 0; i < uSize; i++) 439 { 440 data ~= serialize(t[i], stack, level + 1); 441 } 442 uint len = cast(uint) data.length; 443 dh ~= toVariant(len); 444 return dh ~ data; 445 } 446 447 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 448 if (isStaticArray!T) 449 { 450 assert(data[0] == 8); 451 T value; 452 uint uSize; 453 uint len; 454 long index1; 455 long index2; 456 uSize = toT!uint(data[1 .. $], index1); 457 458 len = toT!uint(data[cast(size_t)(index1 + 1) .. $], index2); 459 parse_index += 1 + index1 + index2; 460 461 long index = parse_index; 462 long parse = 0; 463 for (size_t i = 0; i < uSize; i++) 464 { 465 parse = 0; 466 value[i] = unserialize!(typeof(value[0]))(data[cast(size_t) index .. data.length], 467 parse, stack); 468 index += parse; 469 } 470 471 parse_index += len; 472 473 return value; 474 } 475 476 size_t getsize(T)(T t, RefClass stack, uint level) if (isStaticArray!T) 477 { 478 long total = 1; 479 total += getbytenum(t.length); 480 uint uSize = cast(uint) t.length; 481 for (size_t i = 0; i < uSize; i++) 482 { 483 total += getsize(t[i], stack, level + 1); 484 } 485 total += getbytenum(total); 486 return total; 487 } 488 489 // TDArray 490 // 1 type 9 491 // size[uint] variant 492 // length[uint] variant 493 // data 494 495 byte[] serialize(T)(T t, RefClass stack, uint level) 496 if (isDynamicArray!T && !is(T == string) && !is(T == enum)) 497 { 498 byte[1] header; 499 header[0] = 9; 500 501 uint uSize = cast(uint) t.length; 502 byte[] dh = cast(byte[]) header; 503 dh ~= toVariant(uSize); 504 505 byte[] data; 506 for (size_t i = 0; i < uSize; i++) 507 { 508 data ~= serialize(t[i], stack, level + 1); 509 } 510 uint len = cast(uint) data.length; 511 dh ~= toVariant(len); 512 513 return dh ~ data; 514 } 515 516 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 517 if (isDynamicArray!T && !is(T == string) && !is(T == enum)) 518 { 519 assert(data[0] == 9); 520 521 T value; 522 uint uSize; 523 uint len; 524 long index1; 525 long index2; 526 uSize = toT!uint(data[1 .. $], index1); 527 len = toT!uint(data[cast(size_t)(1 + index1) .. $], index2); 528 529 parse_index += 1 + index1 + index2; 530 value.length = uSize; 531 ulong index = parse_index; 532 long parse = 0; 533 for (size_t i = 0; i < uSize; i++) 534 { 535 value[i] = unserialize!(typeof(value[0]))(data[cast(size_t) index .. data.length], 536 parse, stack); 537 index += parse; 538 } 539 parse_index += len; 540 541 return value; 542 } 543 544 size_t getsize(T)(T t, RefClass stack, uint level) 545 if (isDynamicArray!T && !is(T == string) && !is(T == enum) ) 546 { 547 long total = 1; 548 total += getbytenum(t.length); 549 uint uSize = cast(uint) t.length; 550 for (size_t i = 0; i < uSize; i++) 551 { 552 total += getsize(t[i], stack, level + 1); 553 } 554 total += getbytenum(total); 555 return total; 556 } 557 558 // TStruct 559 // 1 type 10 560 // [uint] variant 561 // data 562 563 byte[] serialize(T)(T t, RefClass stack, uint level) if (is(T == struct)) 564 { 565 byte[1] header; 566 header[0] = 10; 567 byte[] data; 568 569 mixin(serializeMembers!T()); 570 byte[] dh = cast(byte[]) header; 571 uint len = cast(uint) data.length; 572 dh ~= toVariant(len); 573 return dh ~ data; 574 } 575 576 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 577 if (is(T == struct)) 578 { 579 assert(data[0] == 10); 580 581 T t; 582 long index1; 583 uint len = toT!uint(data[1 .. $], index1); 584 585 parse_index = 1 + index1 + len; 586 long index = 1 + index1; 587 mixin(unserializeMembers!T()); 588 589 return t; 590 } 591 592 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == struct)) 593 { 594 long total = 1; 595 596 mixin(getsizeMembers!T()); 597 598 total += getbytenum(total); 599 return cast(uint) total; 600 } 601 602 // TClass 603 // 1 type 11 604 // [uint] len variant 605 // data 606 607 // TClass ref 608 // 1 type 12 609 // id variant 610 611 byte[] serialize(T)(T t, RefClass stack, uint level) if (is(T == class)) 612 { 613 byte[1] header; 614 size_t* id = null; 615 616 if (t !is null) 617 { 618 id = t.toHash() in stack.map; 619 } 620 621 if (id == null) 622 { 623 header[0] = 11; 624 byte[] data; 625 byte[] dh = cast(byte[]) header; 626 if (t !is null) 627 { 628 stack.map[t.toHash()] = stack.map.length; 629 mixin(serializeMembers!T()); 630 } 631 uint len = cast(uint) data.length; 632 dh ~= toVariant(len); 633 634 return dh ~ data; 635 } 636 else 637 { 638 header[0] = 12; 639 byte[] dh = cast(byte[]) header; 640 dh ~= toVariant(*id); 641 return dh; 642 } 643 644 } 645 646 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 647 if (is(T == class)) 648 { 649 assert(data[0] == 11 || data[0] == 12); 650 651 if (data[0] == 11) 652 { 653 long index1; 654 uint len = toT!uint(data[1 .. $], index1); 655 if (len == 0) 656 return null; 657 T t = new T; 658 parse_index = index1 + 1 + len; 659 long index = index1 + 1; 660 stack.arr ~= cast(void*) t; 661 mixin(unserializeMembers!T()); 662 return t; 663 } 664 else 665 { 666 long index1; 667 size_t id = toT!size_t(data[1 .. $], index1); 668 parse_index += index1 + 1; 669 return cast(T) stack.arr[id]; 670 } 671 672 } 673 674 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == class)) 675 { 676 long total = 1; 677 678 size_t* id = null; 679 680 if (t !is null) 681 { 682 id = t.toHash() in stack.map; 683 } 684 685 if (id == null) 686 { 687 if (t !is null) 688 { 689 stack.map[t.toHash()] = stack.map.length; 690 mixin(getsizeMembers!T()); 691 } 692 693 total += getbytenum(total - 1); 694 return total; 695 } 696 else 697 { 698 return getbytenum(*id) + 1; 699 } 700 701 } 702 703 // AssociativeArray 704 // 1 type 13 705 // [uint] len variant 706 // (k,v) 707 708 byte[] serialize(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T) 709 { 710 byte[1] header; 711 header[0] = 13; 712 byte[] dh; 713 dh ~= cast(byte[]) header; 714 byte[] data; 715 foreach (k, v; t) 716 { 717 data ~= serialize(k, stack, level + 1); 718 data ~= serialize(v, stack, level + 1); 719 } 720 uint len = cast(uint) data.length; 721 dh ~= toVariant(len); 722 return dh ~ data; 723 } 724 725 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 726 if (isAssociativeArray!T) 727 { 728 assert(data[0] == 13); 729 730 T t; 731 long index1; 732 uint len = toT!uint(data[1 .. $], index1); 733 734 parse_index = index1 + 1 + len; 735 long index = index1 + 1; 736 while (index < parse_index) 737 { 738 long out_len; 739 auto k = unserialize!(KeyType!T)(data[index .. $], out_len, stack); 740 index += out_len; 741 out_len = 0; 742 auto v = unserialize!(ValueType!T)(data[index .. $], out_len, stack); 743 index += out_len; 744 t[k] = v; 745 } 746 return t; 747 } 748 749 size_t getsize(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T) 750 { 751 long total = 1; 752 foreach (k, v; t) 753 { 754 total += serialize(k).length; 755 total += serialize(v).length; 756 } 757 total += getbytenum(total - 1); 758 return total; 759 } 760 761 // named enum 762 // 1 type 14 763 // 2 [uint] len 764 // 3 other 765 byte[] serialize(T)(T t, RefClass stack, uint level) if (is(T == enum)) 766 { 767 byte[1] header; 768 header[0] = 14; 769 byte[] dh; 770 dh ~= cast(byte[]) header; 771 OriginalType!T v = cast(OriginalType!T)t; 772 byte[] data = serialize(v); 773 uint len = cast(uint)data.length; 774 dh ~= toVariant(len); 775 return dh ~ data; 776 } 777 778 T unserialize(T)(const byte[] data, out long parse_index, RefClass stack) 779 if (is(T == enum)) 780 { 781 assert(data[0] == 14); 782 783 T t; 784 long index1; 785 uint len = toT!uint(data[1 .. $], index1); 786 787 parse_index = index1 + 1 + len; 788 long index = index1 + 1; 789 while (index < parse_index) 790 { 791 long out_len = 0; 792 t = cast(T)unserialize!(OriginalType!T)(data[index .. $], out_len, stack); 793 index += out_len; 794 } 795 return t; 796 } 797 798 size_t getsize(T)(T t, RefClass stack, uint level) if (is(T == enum)) 799 { 800 long total = 1; 801 802 total += serialize(cast(OriginalType!T)t).length; 803 804 total += getbytenum(total - 1); 805 return total; 806 } 807 808 809 810 public: 811 812 T unserialize(T)(const byte[] data ) 813 { 814 long parse_index; 815 return unserialize!T(data, parse_index); 816 } 817 818 T unserialize(T)(const byte[] data, out long parse_index ) 819 { 820 RefClass stack = new RefClass(); 821 return unserialize!T(data, parse_index, stack); 822 } 823 824 byte[] serialize(T)(T t ) 825 { 826 RefClass stack = new RefClass(); 827 return serialize!T(t, stack, 0); 828 } 829 830 size_t getsize(T)(T t ) 831 { 832 RefClass stack = new RefClass(); 833 return getsize!T(t, stack, 0); 834 } 835 836 //////////////////////////////////////////////////////////////////json/////////////////////////// 837 private: 838 enum bool isFloatType(T) = isType!(T, float) || isType!(T, double); 839 840 JSONValue toJson(T)(T t, RefClass stack, uint level) 841 if (isSignedType!T || isUnsignedType!T || is(T == string) || is(T == bool) || isFloatType!T) 842 { 843 return JSONValue(t); 844 } 845 846 // uinteger 847 T toObject(T)(JSONValue v, RefClass stack) if (isUnsignedType!T) 848 { 849 if(v.type() == JSON_TYPE.UINTEGER) 850 return cast(T) v.uinteger; 851 else 852 return T.init; 853 } 854 855 // integer 856 T toObject(T)(JSONValue v, RefClass stack) if (isSignedType!T) 857 { 858 if(v.type() == JSON_TYPE.INTEGER) 859 return cast(T) v.integer; 860 else 861 return T.init; 862 } 863 864 // string 865 T toObject(T)(JSONValue v, RefClass stack) if (is(T == string)) 866 { 867 if(v.type() == JSON_TYPE.STRING) 868 return v.str; 869 else 870 return T.init; 871 } 872 873 // bool 874 T toObject(T)(JSONValue v, RefClass stack) if (is(T == bool)) 875 { 876 if(v.type() == JSON_TYPE.TRUE || v.type() == JSON_TYPE.FALSE) 877 return v.type() == JSON_TYPE.TRUE; 878 else 879 return T.init; 880 } 881 882 // floating 883 T toObject(T)(JSONValue v, RefClass stack) if (isFloatType!T) 884 { 885 if(v.type() == JSON_TYPE.FLOAT) 886 return cast(T) v.floating; 887 else 888 return T.init; 889 } 890 891 892 // array 893 JSONValue toJson(T)(T t, RefClass stack, uint level) 894 if (isStaticArray!T || (isDynamicArray!T && !is(T == string) && !is(T == enum))) 895 { 896 JSONValue[] j; 897 foreach (e; t) 898 { 899 j ~= toJson(e, stack, level); 900 } 901 902 return JSONValue(j); 903 } 904 905 T toObject(T)(JSONValue v, RefClass stack) if (isStaticArray!T) 906 { 907 T t; 908 if(v.type() == JSON_TYPE.ARRAY) 909 { 910 for (size_t i = 0; i < t.length; i++) 911 { 912 t[i] = toObject!(typeof(t[i]))(v.array[i], stack); 913 } 914 } 915 return t; 916 917 } 918 919 T toObject(T)(JSONValue v, RefClass stack) if (isDynamicArray!T && !is(T == string)&& !is(T == enum)) 920 { 921 T t; 922 if(v.type() == JSON_TYPE.ARRAY) 923 { 924 t.length = v.array.length; 925 for (size_t i = 0; i < t.length; i++) 926 { 927 t[i] = toObject!(typeof(t[i]))(v.array[i], stack); 928 } 929 } 930 return t; 931 } 932 933 // struct & class 934 935 string toJsonMembers(T , bool ignore)() 936 { 937 string str; 938 foreach (m; FieldNameTuple!T) 939 { 940 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 941 { 942 if(!ignore || !hasUDA!(__traits(getMember , T , m) ,IGNORE )) 943 { 944 str ~= "j[\"" ~ m ~ "\"] = toJson(t." ~ m ~ " , stack , level + 1);"; 945 } 946 } 947 } 948 return str; 949 } 950 951 string toJsonMembersAll(T)() 952 { 953 string str; 954 foreach (m; FieldNameTuple!T) 955 { 956 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 957 { 958 str ~= "j[\"" ~ m ~ "\"] = toJson(t." ~ m ~ " , stack , level + 1);"; 959 } 960 } 961 return str; 962 } 963 964 965 966 string toObjectMembers(T)() 967 { 968 string str; 969 foreach (m; FieldNameTuple!T) 970 { 971 static if (__traits(getProtection, __traits(getMember, T, m)) == "public") 972 { 973 str ~= " if ( \"" ~ m ~ "\" in j )"; 974 str ~= "t." ~ m ~ " = toObject!(typeof(t." ~ m ~ "))(j[\"" ~ m ~ "\"] , stack);"; 975 } 976 977 } 978 return str; 979 } 980 981 JSONValue toJson(T)(T t, RefClass stack, uint level) if (is(T == struct)) 982 { 983 JSONValue j; 984 985 static if (is(T == JSONValue)) 986 { 987 return t; 988 } 989 else{ 990 bool ignore = (stack.unIgnore is null)? stack.ignore :(stack.unIgnore.ignore!T); 991 992 if(ignore) 993 mixin(toJsonMembers!(T,true)); 994 else 995 mixin(toJsonMembers!(T,false)); 996 997 998 999 1000 1001 return j; 1002 } 1003 } 1004 1005 T toObject(T)(JSONValue j, RefClass stack) if (is(T == struct)) 1006 { 1007 static if (is(T == JSONValue)) 1008 { 1009 return j; 1010 } 1011 else 1012 { 1013 T t; 1014 if(j.type() == JSON_TYPE.OBJECT) 1015 { 1016 mixin(toObjectMembers!T); 1017 } 1018 return t; 1019 } 1020 } 1021 1022 JSONValue toJson(T)(T t, RefClass stack, uint level) if (is(T == class)) 1023 { 1024 if (t is null || level >= stack.level) 1025 { 1026 return JSONValue(null); 1027 } 1028 1029 auto id = t.toHash() in stack.map; 1030 if (id == null) 1031 { 1032 stack.map[t.toHash()] = stack.map.length; 1033 JSONValue j; 1034 bool ignore = (stack.unIgnore is null)? stack.ignore :(stack.unIgnore.ignore!T); 1035 1036 if(ignore) 1037 mixin(toJsonMembers!(T,true)); 1038 else 1039 mixin(toJsonMembers!(T,false)); 1040 return j; 1041 } 1042 else 1043 { 1044 JSONValue j; 1045 j[MAGIC_KEY] = *id; 1046 return j; 1047 } 1048 } 1049 1050 T toObject(T)(JSONValue j, RefClass stack) if (is(T == class)) 1051 { 1052 if ( j.type() != JSON_TYPE.OBJECT) 1053 return T.init; 1054 assert(j.type() == JSON_TYPE.OBJECT); 1055 1056 if (MAGIC_KEY in j) 1057 { 1058 return cast(T) stack.arr[j[MAGIC_KEY].uinteger]; 1059 } 1060 else 1061 { 1062 T t = new T; 1063 stack.arr ~= cast(void*) t; 1064 mixin(toObjectMembers!T); 1065 return t; 1066 } 1067 } 1068 1069 //AssociativeArray 1070 JSONValue toJson(T)(T t, RefClass stack, uint level) if (isAssociativeArray!T) 1071 { 1072 JSONValue j; 1073 import std.conv; 1074 1075 foreach (k, v; t) 1076 j[to!string(k)] = toJson(v, stack, level); 1077 return j; 1078 } 1079 1080 T toObject(T)(JSONValue j, RefClass stack) if (isAssociativeArray!T) 1081 { 1082 import std.conv; 1083 if ( j.type() != JSON_TYPE.OBJECT) 1084 return T.init; 1085 T t; 1086 foreach (k, v; j.object) 1087 { 1088 t[to!(KeyType!T)(k)] = toObject!(ValueType!T)(v, stack); 1089 } 1090 return t; 1091 } 1092 1093 //enum 1094 JSONValue toJson(T)(T t, RefClass stack, uint level) if (is(T == enum)) 1095 { 1096 1097 auto j = JSONValue(cast(OriginalType!T)t); 1098 writeln(j.type()); 1099 return j; 1100 } 1101 1102 T toObject(T)(JSONValue j, RefClass stack) if (is(T == enum)) 1103 { 1104 import std.conv; 1105 writeln(j , " " , j.type() , typeid(T)); 1106 OriginalType!T val; 1107 static if (is(OriginalType!T == string )) 1108 { 1109 if(j.type() == JSON_TYPE.STRING) 1110 val = cast(OriginalType!T)j.str; 1111 else 1112 return T.init; 1113 } 1114 else static if (is(OriginalType!T == int)) 1115 { 1116 if(j.type() == JSON_TYPE.integer) 1117 val = cast(OriginalType!T)j.integer; 1118 else if(j.type() == JSON_TYPE.uinteger) 1119 val = cast(OriginalType!T)j.uinteger; 1120 else 1121 return T.init; 1122 } 1123 1124 return cast(T)val; 1125 } 1126 1127 public: 1128 1129 JSONValue toJson(T)(T t , uint level = uint.max , bool ignore = true) 1130 { 1131 RefClass stack = new RefClass(); 1132 stack.level = level; 1133 stack.ignore = ignore; 1134 return toJson!T(t, stack, 0); 1135 } 1136 1137 JSONValue toJson(T)(T t , UnIgnoreArray array , uint level = uint.max) 1138 { 1139 RefClass stack = new RefClass(); 1140 stack.level = level; 1141 stack.unIgnore = array; 1142 return toJson!T(t, stack, 0); 1143 } 1144 1145 T toObject(T)(JSONValue j) 1146 { 1147 RefClass stack = new RefClass(); 1148 return toObject!T(j, stack); 1149 } 1150 1151 deprecated("Using toJson instead.") 1152 alias toJSON = toJson; 1153 1154 deprecated("Using toObject instead.") 1155 alias toOBJ = toObject; 1156 1157 ////------------------------- toTextString ------ 1158 /** 1159 Takes a tree of JSON values and returns the serialized string. 1160 1161 Any Object types will be serialized in a key-sorted order. 1162 1163 If `pretty` is false no whitespaces are generated. 1164 If `pretty` is true serialized string is formatted to be human-readable. 1165 Set the $(LREF JSONOptions.specialFloatLiterals) flag is set in `options` to encode NaN/Infinity as strings. 1166 */ 1167 string toTextString(const ref JSONValue root, in bool pretty = false, in JSONOptions options = JSONOptions.none) @safe 1168 { 1169 import std.array; 1170 import std.conv; 1171 import std.string; 1172 1173 auto json = appender!string(); 1174 1175 void toStringImpl(Char)(string str) @safe 1176 { 1177 json.put('"'); 1178 1179 foreach (Char c; str) 1180 { 1181 switch (c) 1182 { 1183 case '"': json.put("\\\""); break; 1184 case '\\': json.put("\\\\"); break; 1185 1186 case '/': 1187 if (!(options & JSONOptions.doNotEscapeSlashes)) 1188 json.put('\\'); 1189 json.put('/'); 1190 break; 1191 1192 case '\b': json.put("\\b"); break; 1193 case '\f': json.put("\\f"); break; 1194 case '\n': json.put("\\n"); break; 1195 case '\r': json.put("\\r"); break; 1196 case '\t': json.put("\\t"); break; 1197 default: 1198 { 1199 import std.ascii : isControl; 1200 import std.utf : encode; 1201 1202 // Make sure we do UTF decoding iff we want to 1203 // escape Unicode characters. 1204 assert(((options & JSONOptions.escapeNonAsciiChars) != 0) 1205 == is(Char == dchar), "JSONOptions.escapeNonAsciiChars needs dchar strings"); 1206 1207 with (JSONOptions) if (isControl(c) || 1208 ((options & escapeNonAsciiChars) >= escapeNonAsciiChars && c >= 0x80)) 1209 { 1210 // Ensure non-BMP characters are encoded as a pair 1211 // of UTF-16 surrogate characters, as per RFC 4627. 1212 wchar[2] wchars; // 1 or 2 UTF-16 code units 1213 size_t wNum = encode(wchars, c); // number of UTF-16 code units 1214 foreach (wc; wchars[0 .. wNum]) 1215 { 1216 json.put("\\u"); 1217 foreach_reverse (i; 0 .. 4) 1218 { 1219 char ch = (wc >>> (4 * i)) & 0x0f; 1220 ch += ch < 10 ? '0' : 'A' - 10; 1221 json.put(ch); 1222 } 1223 } 1224 } 1225 else 1226 { 1227 json.put(c); 1228 } 1229 } 1230 } 1231 } 1232 1233 json.put('"'); 1234 } 1235 1236 void toString(string str) @safe 1237 { 1238 // Avoid UTF decoding when possible, as it is unnecessary when 1239 // processing JSON. 1240 if (options & JSONOptions.escapeNonAsciiChars) 1241 toStringImpl!dchar(str); 1242 else 1243 toStringImpl!char(str); 1244 } 1245 1246 void toValue(ref in JSONValue value, ulong indentLevel) @safe 1247 { 1248 void putTabs(ulong additionalIndent = 0) 1249 { 1250 if (pretty) 1251 foreach (i; 0 .. indentLevel + additionalIndent) 1252 json.put(" "); 1253 } 1254 void putEOL() 1255 { 1256 if (pretty) 1257 json.put('\n'); 1258 } 1259 void putCharAndEOL(char ch) 1260 { 1261 json.put(ch); 1262 putEOL(); 1263 } 1264 1265 final switch (value.type) 1266 { 1267 case JSON_TYPE.OBJECT: 1268 auto obj = value.objectNoRef; 1269 if (!obj.length) 1270 { 1271 json.put("{}"); 1272 } 1273 else 1274 { 1275 putCharAndEOL('{'); 1276 bool first = true; 1277 1278 void emit(R)(R names) 1279 { 1280 foreach (name; names) 1281 { 1282 auto member = obj[name]; 1283 if (!first) 1284 putCharAndEOL(','); 1285 first = false; 1286 putTabs(1); 1287 toString(name); 1288 json.put(':'); 1289 if (pretty) 1290 json.put(' '); 1291 toValue(member, indentLevel + 1); 1292 } 1293 } 1294 1295 import std.algorithm.sorting : sort; 1296 // @@@BUG@@@ 14439 1297 // auto names = obj.keys; // aa.keys can't be called in @safe code 1298 auto names = new string[obj.length]; 1299 size_t i = 0; 1300 foreach (k, v; obj) 1301 { 1302 names[i] = k; 1303 i++; 1304 } 1305 sort(names); 1306 emit(names); 1307 1308 putEOL(); 1309 putTabs(); 1310 json.put('}'); 1311 } 1312 break; 1313 1314 case JSON_TYPE.ARRAY: 1315 auto arr = value.arrayNoRef; 1316 if (arr.empty) 1317 { 1318 json.put("[]"); 1319 } 1320 else 1321 { 1322 putCharAndEOL('['); 1323 foreach (i, el; arr) 1324 { 1325 if (i) 1326 putCharAndEOL(','); 1327 putTabs(1); 1328 toValue(el, indentLevel + 1); 1329 } 1330 putEOL(); 1331 putTabs(); 1332 json.put(']'); 1333 } 1334 break; 1335 1336 case JSON_TYPE.STRING: 1337 toString(value.str); 1338 break; 1339 1340 case JSON_TYPE.INTEGER: 1341 json.put(to!string(value.integer)); 1342 break; 1343 1344 case JSON_TYPE.UINTEGER: 1345 json.put(to!string(value.uinteger)); 1346 break; 1347 1348 case JSON_TYPE.FLOAT: 1349 import std.math : isNaN, isInfinity; 1350 1351 auto val = value.floating; 1352 1353 if (val.isNaN) 1354 { 1355 if (options & JSONOptions.specialFloatLiterals) 1356 { 1357 toString(JSONFloatLiteral.nan); 1358 } 1359 else 1360 { 1361 throw new JSONException( 1362 "Cannot encode NaN. Consider passing the specialFloatLiterals flag."); 1363 } 1364 } 1365 else if (val.isInfinity) 1366 { 1367 if (options & JSONOptions.specialFloatLiterals) 1368 { 1369 toString((val > 0) ? JSONFloatLiteral.inf : JSONFloatLiteral.negativeInf); 1370 } 1371 else 1372 { 1373 throw new JSONException( 1374 "Cannot encode Infinity. Consider passing the specialFloatLiterals flag."); 1375 } 1376 } 1377 else 1378 { 1379 import std.format : format; 1380 // The correct formula for the number of decimal digits needed for lossless round 1381 // trips is actually: 1382 // ceil(log(pow(2.0, double.mant_dig - 1)) / log(10.0) + 1) == (double.dig + 2) 1383 // Anything less will round off (1 + double.epsilon) 1384 json.put("%s".format(val)); 1385 } 1386 break; 1387 1388 case JSON_TYPE.TRUE: 1389 json.put("true"); 1390 break; 1391 1392 case JSON_TYPE.FALSE: 1393 json.put("false"); 1394 break; 1395 1396 case JSON_TYPE.NULL: 1397 json.put("null"); 1398 break; 1399 } 1400 } 1401 1402 toValue(root, 0); 1403 return json.data; 1404 } 1405 1406 1407 1408 // only for , nested , new T 1409 /* 1410 version (unittest) 1411 { 1412 //test struct 1413 void test1(T)(T t) 1414 { 1415 assert(unserialize!T(serialize(t)) == t); 1416 assert(serialize(t).length == getsize(t)); 1417 assert(toObject!T(toJson(t)) == t); 1418 } 1419 struct T1 1420 { 1421 bool b; 1422 byte ib; 1423 ubyte ub; 1424 short ish; 1425 ushort ush; 1426 int ii; 1427 uint ui; 1428 long il; 1429 ulong ul; 1430 string s; 1431 uint[10] sa; 1432 long[] sb; 1433 } 1434 struct T2 1435 { 1436 string n; 1437 T1[] t; 1438 } 1439 struct T3 1440 { 1441 T1 t1; 1442 T2 t2; 1443 string[] name; 1444 } 1445 //test class 1446 class C 1447 { 1448 int age; 1449 string name; 1450 T3 t3; 1451 override bool opEquals(Object c) 1452 { 1453 auto c1 = cast(C) c; 1454 return age == c1.age && name == c1.name && t3 == c1.t3; 1455 } 1456 C clone() 1457 { 1458 auto c = new C(); 1459 c.age = age; 1460 c.name = name; 1461 c.t3 = t3; 1462 return c; 1463 } 1464 } 1465 class C2 1466 { 1467 C[] c; 1468 C c1; 1469 T1 t1; 1470 override bool opEquals(Object c) 1471 { 1472 auto c2 = cast(C2) c; 1473 return this.c == c2.c && c1 == c2.c1 && t1 == c2.t1; 1474 } 1475 } 1476 //ref test 1477 class School 1478 { 1479 string name; 1480 User[] users; 1481 override bool opEquals(Object c) 1482 { 1483 auto school = cast(School) c; 1484 return school.name == this.name; 1485 } 1486 } 1487 class User 1488 { 1489 int age; 1490 string name; 1491 School school; 1492 override bool opEquals(Object c) 1493 { 1494 auto user = cast(User) c; 1495 return user.age == this.age && user.name == this.name && user.school == this.school; 1496 } 1497 } 1498 struct J{ 1499 string data; 1500 JSONValue val; 1501 1502 } 1503 1504 enum MONTH 1505 { 1506 M1, 1507 M2 1508 } 1509 1510 enum WEEK : int 1511 { 1512 K1 = 1, 1513 K2 = 2 1514 } 1515 1516 enum DAY : string 1517 { 1518 D1 = "one", 1519 D2 = "two" 1520 } 1521 1522 class Date1 1523 { 1524 MONTH month; 1525 WEEK week; 1526 DAY day; 1527 override bool opEquals(Object c) 1528 { 1529 auto date = cast(Date1) c; 1530 return date.month == this.month && date.week == this.week && date.day == this.day; 1531 } 1532 1533 } 1534 1535 void test_enum_ser() 1536 { 1537 Date1 date = new Date1(); 1538 date.month = MONTH.M2; 1539 date.week = WEEK.K2; 1540 date.day = DAY.D2; 1541 test1(date); 1542 1543 } 1544 1545 void test_json_ser() 1546 { 1547 J j; 1548 j.data = "test"; 1549 j.val = "FUC"; 1550 toObject!J(toJson(j)); 1551 } 1552 void test_ref_class() 1553 { 1554 School school = new School(); 1555 User user1 = new User(); 1556 user1.age = 30; 1557 user1.name = "zhangyuchun"; 1558 user1.school = school; 1559 User user2 = new User(); 1560 user2.age = 31; 1561 user2.name = "wulishan"; 1562 user2.school = school; 1563 school.name = "putao"; 1564 school.users ~= user1; 1565 school.users ~= user2; 1566 test1(user1); 1567 test1(user2); 1568 } 1569 void test_struct_class_array() 1570 { 1571 T1 t; 1572 t.b = true; 1573 t.ib = -11; 1574 t.ub = 128 + 50; 1575 t.ish = -50; 1576 t.ush = (1 << 15) + 50; 1577 t.ii = -50; 1578 t.ui = (1 << 31) + 50; 1579 t.il = (cast(long) 1 << 63) - 50; 1580 t.ul = (cast(long) 1 << 63) + 50; 1581 t.s = "test"; 1582 t.sa[0] = 10; 1583 t.sa[1] = 100; 1584 t.sb ~= 10; 1585 t.sb ~= 100; 1586 test1(t); 1587 T2 t2; 1588 t2.t ~= t; 1589 t2.t ~= t; 1590 t2.n = "testt2"; 1591 test1(t2); 1592 T3 t3; 1593 t3.t1 = t; 1594 t3.t2 = t2; 1595 t3.name ~= "123"; 1596 t3.name ~= "456"; 1597 test1(t3); 1598 C c1 = new C(); 1599 c1.age = 100; 1600 c1.name = "test"; 1601 c1.t3 = t3; 1602 test1(c1); 1603 C2 c2 = new C2(); 1604 c2.c ~= c1; 1605 c2.c ~= c1.clone(); 1606 c2.c1 = c1.clone(); 1607 c2.t1 = t; 1608 test1(c2); 1609 C2 c3 = null; 1610 test1(c3); 1611 string[string] map1 = ["1" : "1", "2" : "2"]; 1612 string[int] map2 = [1 : "1", 2 : "2"]; 1613 T1[string] map3; 1614 T1 a1; 1615 a1.ib = 1; 1616 T1 a2; 1617 a2.ib = 2; 1618 map3["1"] = a1; 1619 map3["2"] = a2; 1620 test1(map1); 1621 test1(map2); 1622 test1(map3); 1623 } 1624 1625 } 1626 unittest 1627 { 1628 import std.stdio; 1629 long index; 1630 void test(T)(T v) 1631 { 1632 long index; 1633 byte[] bs = toVariant(v); 1634 long length = bs.length; 1635 bs ~= ['x', 'y']; 1636 assert(toT!T(bs, index) == v && index == length); 1637 assert(toObject!T(toJson(v)) == v); 1638 } 1639 //test variant 1640 //unsigned 1641 { 1642 ubyte j0 = 0; 1643 ubyte j1 = 50; 1644 ubyte j2 = (1 << 7) + 50; 1645 ubyte j3 = 0xFF; 1646 ushort j4 = (1 << 14) + 50; 1647 ushort j5 = 0xFFFF; 1648 uint j6 = (1 << 21) + 50; 1649 uint j7 = (1 << 28) + 50; 1650 uint j8 = 128; 1651 uint j9 = 0xFFFFFFFF; 1652 { 1653 } 1654 ulong j10 = (cast(ulong) 1 << 35) + 50; 1655 ulong j11 = (cast(ulong) 1 << 42) + 50; 1656 ulong j12 = (cast(ulong) 1 << 49) + 50; 1657 ulong j13 = (cast(ulong) 1 << 56) + 50; 1658 ulong j14 = j9 + j10 + j11 + j12; 1659 ulong j15 = 0xFFFFFFFFFFFFFFFF; 1660 test(j0); 1661 test(j1); 1662 test(j2); 1663 test(j3); 1664 test(j4); 1665 test(j5); 1666 test(j6); 1667 test(j7); 1668 test(j8); 1669 test(j9); 1670 test(j10); 1671 test(j11); 1672 test(j12); 1673 test(j13); 1674 test(j14); 1675 test(j15); 1676 } 1677 //signed 1678 { 1679 byte i0 = 0; 1680 byte i1 = (1 << 6) + 50; 1681 byte i2 = (1 << 7) - 1; 1682 byte i3 = -i2; 1683 byte i4 = -i1; 1684 test(i0); 1685 test(i1); 1686 test(i2); 1687 test(i3); 1688 test(i4); 1689 short i5 = (1 << 7) + 50; 1690 short i6 = (1 << 14) + 50; 1691 short i7 = -i5; 1692 short i8 = -i6; 1693 test(i5); 1694 test(i6); 1695 test(i7); 1696 test(i8); 1697 int i9 = (1 << 16) + 50; 1698 int i10 = (1 << 25) + 50; 1699 int i11 = (1 << 30) + 50; 1700 int i12 = 64; 1701 int i13 = -i10; 1702 int i14 = -i11; 1703 int i15 = i9 + i10 + i11; 1704 int i16 = -i15; 1705 test(i9); 1706 test(i10); 1707 test(i11); 1708 test(i12); 1709 test(i13); 1710 test(i14); 1711 test(i15); 1712 test(i16); 1713 long i17 = (cast(long) 1 << 32) + 50; 1714 long i18 = (cast(long) 1 << 48) + 50; 1715 long i19 = (cast(long) 1 << 63) + 50; 1716 long i20 = i17 + i18 + i19; 1717 long i21 = -i17; 1718 long i22 = -i20; 1719 test(i17); 1720 test(i18); 1721 test(i19); 1722 test(i20); 1723 test(i21); 1724 test(i22); 1725 int i23 = -11; 1726 test(i23); 1727 } 1728 //test serialize 1729 //basic: byte ubyte short ushort int uint long ulong 1730 { 1731 byte b1 = 123; 1732 byte b2 = -11; 1733 ubyte b3 = 233; 1734 short s1 = -11; 1735 short s2 = (1 << 8) + 50; 1736 short s3 = (1 << 15) - 50; 1737 ushort s4 = (1 << 16) - 50; 1738 int i1 = -11; 1739 int i2 = (1 << 16) + 50; 1740 int i3 = (1 << 31) - 50; 1741 uint i4 = (1 << 31) + 50; 1742 long l1 = -11; 1743 long l2 = (cast(long) 1 << 32) + 50; 1744 long l3 = (cast(long) 1 << 63) - 50; 1745 ulong l4 = (cast(long) 1 << 63) + 50; 1746 test1(b1); 1747 test1(b2); 1748 test1(b3); 1749 test1(s1); 1750 test1(s2); 1751 test1(s3); 1752 test1(s4); 1753 test1(i1); 1754 test1(i2); 1755 test1(i3); 1756 test1(i4); 1757 test1(l1); 1758 test1(l2); 1759 test1(l3); 1760 test1(l4); 1761 } 1762 //test string 1763 { 1764 string s1 = ""; 1765 string s2 = "1"; 1766 string s3 = "123"; 1767 test1(s1); 1768 test1(s2); 1769 test1(s3); 1770 } 1771 //test static arrary 1772 { 1773 string[5] sa; 1774 sa[0] = "test0"; 1775 sa[1] = "test1"; 1776 sa[2] = "test2"; 1777 sa[3] = "test3"; 1778 sa[4] = "test4"; 1779 test1(sa); 1780 } 1781 //test dynamic arrary 1782 { 1783 string[] sa; 1784 sa ~= "test1"; 1785 sa ~= "test2"; 1786 sa ~= "test3"; 1787 sa ~= "test4"; 1788 test1(sa); 1789 string[] sa2; 1790 test1(sa2); 1791 } 1792 //test enum \ struct \ class \ associative array 1793 test_enum_ser(); 1794 test_struct_class_array(); 1795 test_ref_class(); 1796 test_json_ser(); 1797 ////unsigned 1798 uint ut1 = 1 << 7; 1799 uint ut2 = 1 << 14; 1800 uint ut3 = 1 << 21; 1801 uint ut4 = 1 << 28; 1802 //signed 1803 int it1 = 1 << 6; 1804 int it2 = 1 << 13; 1805 int it3 = 1 << 20; 1806 int it4 = 1 << 27; 1807 test1(ut1); 1808 test1(ut2); 1809 test1(ut3); 1810 test1(ut4); 1811 test1(it1); 1812 test1(it2); 1813 test1(it3); 1814 test1(it4); 1815 } 1816 */