yum-mirror/slang
Making it easier to work with shaders
git clone https://git.yummers.dev/yum-mirror/slang
eb7f3357a
master
1// slang-json-value.cpp 2#include "slang-json-value.h" 3 4#include "../core/slang-string-escape-util.h" 5#include "../core/slang-string-util.h" 6 7namespace Slang 8{ 9 10/* static */ const JSONValue ::Kind JSONValue ::g_typeToKind []= { 11JSONValue ::Kind ::Invalid ,// Invalid 12 13JSONValue ::Kind ::Bool ,// True, 14JSONValue ::Kind ::Bool ,// False 15JSONValue ::Kind ::Null ,// Null, 16 17JSONValue ::Kind ::String ,// StringLexeme, 18JSONValue ::Kind ::Integer ,// IntegerLexeme, 19JSONValue ::Kind ::Float ,// FloatLexeme, 20 21JSONValue ::Kind ::Integer ,// IntegerValue, 22JSONValue ::Kind ::Float ,// FloatValue, 23JSONValue ::Kind ::String ,// StringValue, 24 25JSONValue ::Kind ::String ,// StringRepresentation 26 27JSONValue ::Kind ::Array ,// Array, 28JSONValue ::Kind ::Object ,// Object, 29}; 30 31static bool _isDefault (const RttiInfo * type ,const void * in ) 32{ 33SLANG_UNUSED (type ) 34const JSONValue & value = * (const JSONValue * )in ; 35return value .getKind ()== JSONValue ::Kind ::Invalid ; 36} 37 38static OtherRttiInfo _getJSONValueRttiInfo () 39{ 40OtherRttiInfo info ; 41info .init < JSONValue > (RttiInfo ::Kind ::Other ); 42info .m_name = "JSONValue" ; 43info .m_isDefaultFunc = _isDefault ; 44info .m_typeFuncs = GetRttiTypeFuncs < JSONValue > ::getFuncs (); 45return info ; 46} 47/* static */ const OtherRttiInfo JSONValue ::g_rttiInfo = _getJSONValueRttiInfo (); 48 49static JSONKeyValue _makeInvalidKeyValue () 50{ 51JSONKeyValue keyValue ; 52keyValue .key = JSONKey (0 ); 53keyValue .value .type = JSONValue ::Type ::Invalid ; 54return keyValue ; 55} 56 57/* static */ JSONKeyValue g_invalid = _makeInvalidKeyValue (); 58 59/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 60 61JSONValue 62 63!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 64 65bool JSONValue ::asBool ()const 66{ 67switch (type ) 68 { 69case JSONValue ::Type ::True : 70return true; 71case JSONValue ::Type ::False : 72case JSONValue ::Type ::Null : 73 { 74return false; 75 } 76case JSONValue ::Type ::IntegerValue : 77return intValue != 0 ; 78case JSONValue ::Type ::FloatValue : 79return floatValue != 0 ; 80default : 81break ; 82 } 83 84if (isLexeme (type )) 85 { 86SLANG_ASSERT (!"Lexeme values can only be accessed through container" ); 87 } 88else 89 { 90SLANG_ASSERT (!"Not bool convertable" ); 91 } 92 93return false; 94} 95 96int64_t JSONValue ::asInteger ()const 97{ 98switch (type ) 99 { 100case JSONValue ::Type ::True : 101return 1 ; 102case JSONValue ::Type ::False : 103case JSONValue ::Type ::Null : 104 { 105return 0 ; 106 } 107case JSONValue ::Type ::IntegerValue : 108return intValue ; 109case JSONValue ::Type ::FloatValue : 110return int64_t (floatValue ); 111break ; 112 } 113 114if (isLexeme (type )) 115 { 116SLANG_ASSERT (!"Lexeme values can only be accessed through container" ); 117 } 118else 119 { 120SLANG_ASSERT (!"Not int convertable" ); 121 } 122 123return 0 ; 124} 125 126double JSONValue ::asFloat ()const 127{ 128switch (type ) 129 { 130case JSONValue ::Type ::True : 131return 1.0 ; 132case JSONValue ::Type ::False : 133case JSONValue ::Type ::Null : 134 { 135return 0.0 ; 136 } 137case JSONValue ::Type ::IntegerValue : 138return double (intValue ); 139case JSONValue ::Type ::FloatValue : 140return floatValue ; 141default : 142break ; 143 } 144 145if (isLexeme (type )) 146 { 147SLANG_ASSERT (!"Lexeme values can only be accessed through container" ); 148 } 149else 150 { 151SLANG_ASSERT (!"Not float convertable" ); 152 } 153 154return 0 ; 155} 156 157/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 158 159PersistentJSONValue 160 161!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 162 163PersistentJSONValue ::PersistentJSONValue (const ThisType & rhs ) 164{ 165* (JSONValue * )this = rhs ; 166 167if (type == Type ::StringRepresentation && stringRep ) 168 { 169stringRep -> addReference (); 170 } 171} 172 173void PersistentJSONValue ::operator= (const ThisType & rhs ) 174{ 175if (this != & rhs ) 176 { 177if (rhs .type == Type ::StringRepresentation && rhs .stringRep ) 178 { 179rhs .stringRep -> addReference (); 180 } 181if (type == Type ::StringRepresentation && stringRep ) 182 { 183stringRep -> releaseReference (); 184 } 185* (JSONValue * )this = rhs ; 186 } 187} 188 189String PersistentJSONValue ::getString ()const 190{ 191if (type == Type ::StringRepresentation ) 192 { 193return String (stringRep ); 194 } 195SLANG_ASSERT (!"Not a string type" ); 196return String (); 197} 198 199UnownedStringSlice PersistentJSONValue ::getSlice ()const 200{ 201if (type == Type ::StringRepresentation ) 202 { 203return StringRepresentation ::asSlice (stringRep ); 204 } 205SLANG_ASSERT (!"Not a string type" ); 206return UnownedStringSlice (); 207} 208 209void PersistentJSONValue ::set (const UnownedStringSlice & slice ,SourceLoc inLoc ) 210{ 211StringRepresentation * oldRep = 212 (type == JSONValue ::Type ::StringRepresentation ) ?stringRep :nullptr ; 213 214type = Type ::StringRepresentation ; 215loc = inLoc ; 216 217StringRepresentation * newRep = nullptr ; 218 219const auto sliceLength = slice .getLength (); 220 221// If we have an oldRep that is unique and large enough reuse it 222if (sliceLength ) 223 { 224if (oldRep && oldRep -> isUniquelyReferenced ()&& sliceLength <=oldRep -> capacity ) 225 { 226oldRep -> setContents (slice ); 227newRep = oldRep ; 228// We are reusing so make null so not freed 229oldRep = nullptr ; 230 } 231else 232 { 233newRep = StringRepresentation ::createWithReference (slice ); 234 } 235 236SLANG_ASSERT (newRep -> debugGetReferenceCount () >=1 ); 237 } 238 239stringRep = newRep ; 240 241if (oldRep ) 242 { 243oldRep -> releaseReference (); 244 } 245} 246 247void PersistentJSONValue ::_init (const UnownedStringSlice & slice ,SourceLoc inLoc ) 248{ 249loc = inLoc ; 250type = Type ::StringRepresentation ; 251stringRep = StringRepresentation ::createWithReference (slice ); 252} 253 254bool PersistentJSONValue ::operator== (const ThisType & rhs )const 255{ 256if (this == & rhs ) 257 { 258return true; 259 } 260 261if (type != rhs .type || loc != rhs .loc ) 262 { 263return false; 264 } 265 266switch (type ) 267 { 268case Type ::Invalid : 269case Type ::True : 270case Type ::False : 271case Type ::Null : 272 { 273// The type is all that needs to be checked 274return true; 275 } 276case Type ::IntegerValue : 277return intValue == rhs .intValue ; 278case Type ::FloatValue : 279return floatValue == rhs .floatValue ; 280case Type ::StringRepresentation : 281 { 282if (stringRep == rhs .stringRep ) 283 { 284return true; 285 } 286auto thisSlice = StringRepresentation ::asSlice (stringRep ); 287auto rhsSlice = StringRepresentation ::asSlice (rhs .stringRep ); 288return thisSlice == rhsSlice ; 289 } 290default : 291break ; 292 } 293 294SLANG_ASSERT (!"Not valid Persistent type" ); 295return false; 296} 297 298void PersistentJSONValue ::_init (const JSONValue & in ,JSONContainer * container ) 299{ 300// We are assuming this is invalid, so it can't be the same as in 301SLANG_ASSERT (& in != this ); 302 303switch (in .type ) 304 { 305case Type ::StringValue : 306case Type ::StringLexeme : 307 { 308if (!container ) 309 { 310SLANG_ASSERT (!"Requires container" ); 311return ; 312 } 313_init (container -> getTransientString (in ),in .loc ); 314break ; 315 } 316case Type ::StringRepresentation : 317 { 318* (JSONValue * )this = in ; 319if (stringRep ) 320 { 321stringRep -> addReference (); 322 } 323break ; 324 } 325case Type ::IntegerLexeme : 326 { 327type = JSONValue ::Type ::IntegerValue ; 328intValue = container -> asInteger (in ); 329loc = in .loc ; 330break ; 331 } 332case Type ::FloatLexeme : 333 { 334type = JSONValue ::Type ::FloatValue ; 335floatValue = container -> asFloat (in ); 336loc = in .loc ; 337break ; 338 } 339case Type ::Array : 340case Type ::Object : 341 { 342SLANG_ASSERT (!"Not a simple JSON type" ); 343break ; 344 } 345default : 346 { 347* (JSONValue * )this = in ; 348break ; 349 } 350 } 351} 352 353void PersistentJSONValue ::set (const JSONValue & in ,JSONContainer * container ) 354{ 355if (& in != this ) 356 { 357if (type == Type ::StringRepresentation ) 358 { 359StringRepresentation * oldStringRep = stringRep ; 360_init (in ,container ); 361if (oldStringRep ) 362 { 363oldStringRep -> releaseReference (); 364 } 365 } 366else 367 { 368_init (in ,container ); 369 } 370 } 371} 372 373/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 374 375JSONContainer 376 377!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 378 379JSONContainer ::JSONContainer (SourceManager * sourceManager ) 380 :m_slicePool (StringSlicePool ::Style ::Default ),m_sourceManager (sourceManager ) 381{ 382// Index 0 is the empty array or object 383_addRange (Range ::Type ::None ,0 ,0 ); 384} 385 386void JSONContainer ::reset () 387{ 388m_slicePool .clear (); 389 390m_freeRangeIndices .clear (); 391m_arrayValues .clear (); 392m_objectValues .clear (); 393 394_addRange (Range ::Type ::None ,0 ,0 ); 395 396m_currentView = nullptr ; 397} 398 399/* static */ bool JSONContainer ::areKeysUnique (const JSONKeyValue * keyValues ,Index keyValueCount ) 400{ 401for (Index i = 1 ;i < keyValueCount ;++ i ) 402 { 403const JSONKey key = keyValues [i ].key ; 404 405for (Int j = 0 ;j < i - 1 ;j ++ ) 406 { 407if (keyValues [j ].key == key ) 408 { 409return false; 410 } 411 } 412 } 413 414return true; 415} 416 417Index JSONContainer ::_addRange (Range ::Type type ,Index startIndex ,Index count ) 418{ 419if (m_freeRangeIndices .getCount ()> 0 ) 420 { 421const Index rangeIndex = m_freeRangeIndices .getLast (); 422m_freeRangeIndices .removeLast (); 423 424auto & range = m_ranges [rangeIndex ]; 425range .type = type ; 426range .startIndex = startIndex ; 427range .count = count ; 428range .capacity = count ; 429 430return rangeIndex ; 431 } 432else 433 { 434Range range ; 435range .type = type ; 436range .startIndex = startIndex ; 437range .count = count ; 438range .capacity = count ; 439 440m_ranges .add (range ); 441return m_ranges .getCount ()- 1 ; 442 } 443} 444 445JSONValue JSONContainer ::createArray (const JSONValue * values ,Index valuesCount ,SourceLoc loc ) 446{ 447if (valuesCount <=0 ) 448 { 449return JSONValue ::makeEmptyArray (loc ); 450 } 451 452JSONValue value ; 453value .type = JSONValue ::Type ::Array ; 454value .loc = loc ; 455value .rangeIndex = _addRange (Range ::Type ::Array ,m_arrayValues .getCount (),valuesCount ); 456 457m_arrayValues .addRange (values ,valuesCount ); 458return value ; 459} 460 461JSONValue JSONContainer ::createObject ( 462const JSONKeyValue * keyValues , 463Index keyValueCount , 464SourceLoc loc ) 465{ 466if (keyValueCount <=0 ) 467 { 468return JSONValue ::makeEmptyObject (loc ); 469 } 470 471JSONValue value ; 472value .type = JSONValue ::Type ::Object ; 473value .loc = loc ; 474value .rangeIndex = _addRange (Range ::Type ::Object ,m_objectValues .getCount (),keyValueCount ); 475 476m_objectValues .addRange (keyValues ,keyValueCount ); 477return value ; 478} 479 480JSONValue JSONContainer ::createString (const UnownedStringSlice & slice ,SourceLoc loc ) 481{ 482JSONValue value ; 483value .type = JSONValue ::Type ::StringValue ; 484value .loc = loc ; 485value .stringKey = getKey (slice ); 486return value ; 487} 488 489JSONKey JSONContainer ::getKey (const UnownedStringSlice & slice ) 490{ 491return JSONKey (m_slicePool .add (slice )); 492} 493 494JSONKey JSONContainer ::findKey (const UnownedStringSlice & slice )const 495{ 496const Index index = m_slicePool .findIndex (slice ); 497return (index < 0 ) ?JSONKey (0 ) :JSONKey (index ); 498} 499 500ConstArrayView < JSONValue > JSONContainer ::getArray (const JSONValue & in )const 501{ 502SLANG_ASSERT (in .type == JSONValue ::Type ::Array ); 503if (in .type != JSONValue ::Type ::Array || in .rangeIndex == 0 ) 504 { 505return ConstArrayView < JSONValue > ((const JSONValue * )nullptr ,0 ); 506 } 507const Range & range = m_ranges [in .rangeIndex ]; 508return ConstArrayView < JSONValue > (m_arrayValues .getBuffer ()+ range .startIndex ,range .count ); 509} 510 511ConstArrayView < JSONKeyValue > JSONContainer ::getObject (const JSONValue & in )const 512{ 513SLANG_ASSERT (in .type == JSONValue ::Type ::Object ); 514if (in .type != JSONValue ::Type ::Object || in .rangeIndex == 0 ) 515 { 516return ConstArrayView < JSONKeyValue > ((const JSONKeyValue * )nullptr ,0 ); 517 } 518 519const Range & range = m_ranges [in .rangeIndex ]; 520return ConstArrayView < JSONKeyValue > (m_objectValues .getBuffer ()+ range .startIndex ,range .count ); 521} 522 523ArrayView < JSONValue > JSONContainer ::getArray (const JSONValue & in ) 524{ 525SLANG_ASSERT (in .type == JSONValue ::Type ::Array ); 526if (in .type != JSONValue ::Type ::Array || in .rangeIndex == 0 ) 527 { 528return ArrayView < JSONValue > ((JSONValue * )nullptr ,0 ); 529 } 530const Range & range = m_ranges [in .rangeIndex ]; 531SLANG_ASSERT ( 532range .startIndex <=m_arrayValues .getCount ()&& 533range .startIndex + range .count <=m_arrayValues .getCount ()); 534 535return ArrayView < JSONValue > (m_arrayValues .getBuffer ()+ range .startIndex ,range .count ); 536} 537 538ArrayView < JSONKeyValue > JSONContainer ::getObject (const JSONValue & in ) 539{ 540SLANG_ASSERT (in .type == JSONValue ::Type ::Object ); 541if (in .type != JSONValue ::Type ::Object || in .rangeIndex == 0 ) 542 { 543return ArrayView < JSONKeyValue > ((JSONKeyValue * )nullptr ,0 ); 544 } 545 546const Range & range = m_ranges [in .rangeIndex ]; 547return ArrayView < JSONKeyValue > (m_objectValues .getBuffer ()+ range .startIndex ,range .count ); 548} 549 550UnownedStringSlice JSONContainer ::getLexeme (const JSONValue & in ) 551{ 552SLANG_ASSERT (JSONValue ::isLexeme (in .type )); 553if (!JSONValue ::isLexeme (in .type )) 554 { 555return UnownedStringSlice (); 556 } 557 558if (!(m_currentView && m_currentView -> getRange ().contains (in .loc ))) 559 { 560m_currentView = m_sourceManager -> findSourceView (in .loc ); 561if (!m_currentView ) 562 { 563return UnownedStringSlice (); 564 } 565 } 566 567const auto offset = m_currentView -> getRange ().getOffset (in .loc ); 568SourceFile * sourceFile = m_currentView -> getSourceFile (); 569 570return UnownedStringSlice (sourceFile -> getContent ().begin ()+ offset ,in .length ); 571} 572 573UnownedStringSlice JSONContainer ::getString (const JSONValue & in ) 574{ 575switch (in .type ) 576 { 577case JSONValue ::Type ::StringValue : 578 { 579return getStringFromKey (in .stringKey ); 580 } 581case JSONValue ::Type ::StringLexeme : 582 { 583auto slice = getTransientString (in ); 584auto handle = m_slicePool .add (slice ); 585return m_slicePool .getSlice (handle ); 586 } 587case JSONValue ::Type ::StringRepresentation : 588 { 589return StringRepresentation ::asSlice (in .stringRep ); 590 } 591case JSONValue ::Type ::Null : 592 { 593return UnownedStringSlice (); 594 } 595default : 596break ; 597 } 598 599SLANG_ASSERT (!"Not a string type" ); 600return UnownedStringSlice (); 601} 602 603UnownedStringSlice JSONContainer ::getTransientString (const JSONValue & in ) 604{ 605switch (in .type ) 606 { 607case JSONValue ::Type ::StringRepresentation : 608 { 609return StringRepresentation ::asSlice (in .stringRep ); 610 } 611case JSONValue ::Type ::StringValue : 612 { 613return getStringFromKey (in .stringKey ); 614 } 615case JSONValue ::Type ::StringLexeme : 616 { 617StringEscapeHandler * handler = 618StringEscapeUtil ::getHandler (StringEscapeUtil ::Style ::JSON ); 619 620UnownedStringSlice lexeme = getLexeme (in ); 621UnownedStringSlice unquoted = StringEscapeUtil ::unquote (handler ,lexeme ); 622 623if (handler -> isUnescapingNeeeded (unquoted )) 624 { 625m_buf .clear (); 626handler -> appendUnescaped (unquoted ,m_buf ); 627return m_buf .getUnownedSlice (); 628 } 629else 630 { 631return unquoted ; 632 } 633 } 634case JSONValue ::Type ::Null : 635 { 636return UnownedStringSlice (); 637 } 638 } 639 640SLANG_ASSERT (!"Not a string type" ); 641return UnownedStringSlice (); 642} 643 644JSONKey JSONContainer ::getStringKey (const JSONValue & in ) 645{ 646return (in .type == JSONValue ::Type ::StringValue ) ?in .stringKey 647 :getKey (getTransientString (in )); 648} 649 650bool JSONContainer ::asBool (const JSONValue & value ) 651{ 652switch (value .type ) 653 { 654case JSONValue ::Type ::IntegerLexeme : 655return asInteger (value )!= 0 ; 656case JSONValue ::Type ::FloatLexeme : 657return asFloat (value )!= 0.0 ; 658case JSONValue ::Type ::StringLexeme : 659return getTransientString (value ).caseInsensitiveEquals (toSlice ("true" ))|| 660getTransientString (value ).caseInsensitiveEquals (toSlice ("1" )); 661default : 662return value .asBool (); 663 } 664} 665 666JSONValue JSONContainer ::asValue (const JSONValue & inValue ) 667{ 668JSONValue value = inValue ; 669switch (value .type ) 670 { 671case JSONValue ::Type ::StringLexeme : 672 { 673const UnownedStringSlice slice = getTransientString (inValue ); 674value .stringKey = getKey (slice ); 675value .type = JSONValue ::Type ::StringValue ; 676break ; 677 } 678case JSONValue ::Type ::IntegerLexeme : 679 { 680value .floatValue = value .asFloat (); 681value .type = JSONValue ::Type ::IntegerValue ; 682break ; 683 } 684case JSONValue ::Type ::FloatLexeme : 685 { 686value .floatValue = value .asFloat (); 687value .type = JSONValue ::Type ::FloatValue ; 688break ; 689 } 690default : 691break ; 692 } 693 694return value ; 695} 696 697void JSONContainer ::_clearSourceManagerDependency (JSONValue * ioValues ,Index count ) 698{ 699for (Index i = 0 ;i < count ;++ i ) 700 { 701auto & value = ioValues [i ]; 702value = asValue (value ); 703value .loc = SourceLoc (); 704 } 705} 706 707void JSONContainer ::clearSourceManagerDependency (JSONValue * ioValues ,Index valuesCount ) 708{ 709_clearSourceManagerDependency (ioValues ,valuesCount ); 710 711// We need to find ranges that are available 712for (auto & range :m_ranges ) 713 { 714switch (range .type ) 715 { 716case Range ::Type ::Array : 717 { 718_clearSourceManagerDependency ( 719m_arrayValues .getBuffer ()+ range .startIndex , 720range .count ); 721break ; 722 } 723case Range ::Type ::Object : 724 { 725const Index count = range .count ; 726auto pairs = m_objectValues .getBuffer ()+ range .startIndex ; 727 728for (Index i = 0 ;i < count ;++ i ) 729 { 730auto & pair = pairs [i ]; 731pair .keyLoc = SourceLoc (); 732pair .value = asValue (pair .value ); 733pair .value .loc = SourceLoc (); 734 } 735break ; 736 } 737default : 738break ; 739 } 740 } 741 742// Remove the source manager 743m_sourceManager = nullptr ; 744} 745 746int64_t JSONContainer ::asInteger (const JSONValue & value ) 747{ 748switch (value .type ) 749 { 750case JSONValue ::Type ::IntegerLexeme : 751 { 752UnownedStringSlice slice = getLexeme (value ); 753int64_t intValue ; 754if (SLANG_SUCCEEDED (StringUtil ::parseInt64 (slice ,intValue ))) 755 { 756return intValue ; 757 } 758SLANG_ASSERT (!"Couldn't convert int" ); 759return 0 ; 760 } 761case JSONValue ::Type ::FloatLexeme : 762return int64_t (asFloat (value )); 763default : 764return value .asInteger (); 765 } 766} 767 768double JSONContainer ::asFloat (const JSONValue & value ) 769{ 770switch (value .type ) 771 { 772case JSONValue ::Type ::IntegerLexeme : 773return double (asInteger (value )); 774case JSONValue ::Type ::FloatLexeme : 775 { 776UnownedStringSlice slice = getLexeme (value ); 777double floatValue ; 778if (SLANG_SUCCEEDED (StringUtil ::parseDouble (slice ,floatValue ))) 779 { 780return floatValue ; 781 } 782SLANG_ASSERT (!"Couldn't convert double" ); 783return 0.0 ; 784 } 785default : 786return value .asFloat (); 787 } 788} 789 790Index JSONContainer ::findObjectIndex (const JSONValue & obj ,JSONKey key )const 791{ 792auto pairs = getObject (obj ); 793return pairs .findFirstIndex ( 794 [key ](const JSONKeyValue & pair )-> bool {return pair .key == key ; }); 795} 796 797JSONValue JSONContainer ::findObjectValue (const JSONValue & obj ,JSONKey key )const 798{ 799auto pairs = getObject (obj ); 800const Index index = 801pairs .findFirstIndex ([key ](const JSONKeyValue & pair )-> bool {return pair .key == key ; }); 802return (index >=0 ) ?pairs [index ].value :JSONValue ::makeInvalid (); 803} 804 805JSONValue & JSONContainer ::getAt (const JSONValue & array ,Index index ) 806{ 807SLANG_ASSERT (array .type == JSONValue ::Type ::Array ); 808const Range & range = m_ranges [array .rangeIndex ]; 809 810SLANG_ASSERT (index >=0 && index < range .count ); 811return m_arrayValues [range .startIndex + index ]; 812} 813 814void JSONContainer ::addToArray (JSONValue & array ,const JSONValue & value ) 815{ 816SLANG_ASSERT (array .type == JSONValue ::Type ::Array ); 817if (array .type == JSONValue ::Type ::Array ) 818 { 819// If it's empty 820if (array .rangeIndex == 0 ) 821 { 822// We can just add to the end 823array .rangeIndex = _addRange (Range ::Type ::Array ,m_arrayValues .getCount (),1 ); 824m_arrayValues .add (value ); 825 } 826else 827 { 828_add (m_ranges [array .rangeIndex ],m_arrayValues ,value ); 829 } 830 } 831} 832 833Index JSONContainer ::findKeyGlobalIndex (const JSONValue & obj ,JSONKey key ) 834{ 835SLANG_ASSERT (obj .type == JSONValue ::Type ::Object ); 836if (obj .type != JSONValue ::Type ::Object ) 837 { 838return -1 ; 839 } 840 841auto buf = m_objectValues .getBuffer (); 842 843const Range & range = m_ranges [obj .rangeIndex ]; 844for (Index i = range .startIndex ;i < range .startIndex + range .count ;++ i ) 845 { 846if (buf [i ].key == key ) 847 { 848return i ; 849 } 850 } 851 852return -1 ; 853} 854 855Index JSONContainer ::findKeyGlobalIndex (const JSONValue & obj ,const UnownedStringSlice & slice ) 856{ 857Index keyIndex = m_slicePool .findIndex (slice ); 858if (keyIndex < 0 ) 859 { 860return -1 ; 861 } 862 863return findKeyGlobalIndex (obj ,JSONKey (keyIndex )); 864} 865 866void JSONContainer ::_removeKey (JSONValue & obj ,Index globalIndex ) 867{ 868Range & range = m_ranges [obj .rangeIndex ]; 869const auto localIndex = globalIndex + range .startIndex ; 870 871if (localIndex < range .count - 1 ) 872 { 873auto localBuf = m_objectValues .getBuffer ()+ range .startIndex ; 874 ::memmove ( 875 (void * )(localBuf + localIndex ), 876 (void * )(localBuf + localIndex + 1 ), 877sizeof (* localBuf )* (range .count - (localIndex + 1 ))); 878 } 879 880-- range .count ; 881} 882 883bool JSONContainer ::removeKey (JSONValue & obj ,JSONKey key ) 884{ 885const Index globalIndex = findKeyGlobalIndex (obj ,key ); 886if (globalIndex >=0 ) 887 { 888_removeKey (obj ,globalIndex ); 889return true; 890 } 891return false; 892} 893 894bool JSONContainer ::removeKey (JSONValue & obj ,const UnownedStringSlice & slice ) 895{ 896const Index globalIndex = findKeyGlobalIndex (obj ,slice ); 897if (globalIndex >=0 ) 898 { 899_removeKey (obj ,globalIndex ); 900return true; 901 } 902return false; 903} 904 905template < typename T > 906/* static */ void JSONContainer ::_add (Range & ioRange ,List < T >& ioList ,const T & value ) 907{ 908// If we have capacity, we can add to the end 909if (ioRange .count < ioRange .capacity ) 910 { 911ioList [ioRange .startIndex + ioRange .count ++ ]= value ; 912return ; 913 } 914 915// If we are at the end, we can just add 916if (ioRange .startIndex + ioRange .capacity == ioList .getCount ()) 917 { 918ioList .add (value ); 919ioRange .capacity ++ ; 920ioRange .count ++ ; 921return ; 922 } 923 924// Okay we have no choice but to make new space at the end 925// So there's no place to add. We want to move to the end with an extra space. 926 927const Index newStartIndex = ioList .getCount (); 928ioList .growToCount (newStartIndex + ioRange .count + 1 ); 929 930auto buffer = ioList .getBuffer (); 931 ::memmove ( 932 (void * )(buffer + newStartIndex ), 933 (void * )(buffer + ioRange .startIndex ), 934sizeof (* buffer )* ioRange .count ); 935 936buffer [newStartIndex + ioRange .count ]= value ; 937 938ioRange .startIndex = newStartIndex ; 939ioRange .count ++ ; 940ioRange .capacity ++ ; 941} 942 943 944void JSONContainer ::setKeyValue (JSONValue & obj ,JSONKey key ,const JSONValue & value ,SourceLoc loc ) 945{ 946SLANG_ASSERT (obj .type == JSONValue ::Type ::Object ); 947if (obj .type != JSONValue ::Type ::Object ) 948 { 949return ; 950 } 951 952const JSONKeyValue keyValue {key ,loc ,value }; 953if (obj .rangeIndex == 0 ) 954 { 955// We need a new range and add to the end 956obj .rangeIndex = _addRange (Range ::Type ::Object ,m_objectValues .getCount (),1 ); 957m_objectValues .add (keyValue ); 958return ; 959 } 960 961const Index globalIndex = findKeyGlobalIndex (obj ,key ); 962if (globalIndex >=0 ) 963 { 964auto & dst = m_objectValues [globalIndex ]; 965SLANG_ASSERT (dst .key == key ); 966dst = keyValue ; 967return ; 968 } 969 970Range & range = m_ranges [obj .rangeIndex ]; 971_add (range ,m_objectValues ,keyValue ); 972} 973 974void JSONContainer ::_destroyRange (Index rangeIndex ) 975{ 976auto & range = m_ranges [rangeIndex ]; 977 978// If the range is at the end, shrink it 979switch (range .type ) 980 { 981case Range ::Type ::Array : 982 { 983if (range .startIndex + range .capacity == m_arrayValues .getCount ()) 984 { 985m_arrayValues .setCount (range .startIndex ); 986 } 987break ; 988 } 989case Range ::Type ::Object : 990 { 991if (range .startIndex + range .capacity == m_objectValues .getCount ()) 992 { 993m_objectValues .setCount (range .startIndex ); 994 } 995break ; 996 } 997default : 998break ; 999 } 1000 1001range .type = Range ::Type ::Destroyed ; 1002m_freeRangeIndices .add (rangeIndex ); 1003} 1004 1005void JSONContainer ::destroy (JSONValue & value ) 1006{ 1007if (value .needsDestroy ()) 1008 { 1009_destroyRange (value .rangeIndex ); 1010 } 1011value .type = JSONValue ::Type ::Invalid ; 1012} 1013 1014void JSONContainer ::destroyRecursively (JSONValue & inValue ) 1015{ 1016if (!(inValue .needsDestroy ()&& m_ranges [inValue .rangeIndex ].isActive ())) 1017 { 1018inValue .type = JSONValue ::Type ::Invalid ; 1019return ; 1020 } 1021 1022inValue .type = JSONValue ::Type ::Invalid ; 1023 1024List < Range > activeRanges ; 1025 1026activeRanges .add (m_ranges [inValue .rangeIndex ]); 1027_destroyRange (inValue .rangeIndex ); 1028 1029while (activeRanges .getCount ()) 1030 { 1031const Range range = activeRanges .getLast (); 1032activeRanges .removeLast (); 1033 1034auto type = range .type ; 1035const Index count = range .count ; 1036 1037if (type == Range ::Type ::Array ) 1038 { 1039auto * buf = m_arrayValues .getBuffer ()+ range .startIndex ; 1040 1041for (Index i = 0 ;i < count ;++ i ) 1042 { 1043auto & value = buf [i ]; 1044// If we have an active range, add to work list, and destroy 1045if (value .needsDestroy ()&& m_ranges [value .rangeIndex ].isActive ()) 1046 { 1047activeRanges .add (m_ranges [value .rangeIndex ]); 1048_destroyRange (value .rangeIndex ); 1049 } 1050value .type = JSONValue ::Type ::Invalid ; 1051 } 1052 } 1053else 1054 { 1055SLANG_ASSERT (type == Range ::Type ::Object ); 1056 1057auto * buf = m_objectValues .getBuffer ()+ range .startIndex ; 1058 1059for (Index i = 0 ;i < count ;++ i ) 1060 { 1061auto & keyValue = buf [i ]; 1062auto & value = keyValue .value ; 1063// We want to mark that it's in the list so that if we have a badly formed tree we 1064// don't read 1065if (value .needsDestroy ()&& m_ranges [value .rangeIndex ].isActive ()) 1066 { 1067activeRanges .add (m_ranges [value .rangeIndex ]); 1068_destroyRange (value .rangeIndex ); 1069 } 1070value .type = JSONValue ::Type ::Invalid ; 1071 } 1072 } 1073 } 1074} 1075 1076bool JSONContainer ::areEqual (const JSONValue * a ,const JSONValue * b ,Index count ) 1077{ 1078for (Index i = 0 ;i < count ;++ i ) 1079 { 1080if (!areEqual (a [i ],b [i ])) 1081 { 1082return false; 1083 } 1084 } 1085 1086return true; 1087} 1088 1089 1090/* static */ bool JSONContainer ::_sameKeyOrder ( 1091const JSONKeyValue * a , 1092const JSONKeyValue * b , 1093Index count ) 1094{ 1095for (Index i = 0 ;i < count ;++ i ) 1096 { 1097if (a [i ].key != b [i ].key ) 1098 { 1099return false; 1100 } 1101 } 1102return true; 1103} 1104 1105bool JSONContainer ::_areEqualOrderedKeys (const JSONKeyValue * a ,const JSONKeyValue * b ,Index count ) 1106{ 1107for (Index i = 0 ;i < count ;++ i ) 1108 { 1109const auto & curA = a [i ]; 1110const auto & curB = b [i ]; 1111 1112if (curA .key != curB .key || !areEqual (curA .value ,curB .value )) 1113 { 1114return false; 1115 } 1116 } 1117return true; 1118} 1119 1120bool JSONContainer ::_areEqualValues (const JSONKeyValue * a ,const JSONKeyValue * b ,Index count ) 1121{ 1122for (Index i = 0 ;i < count ;++ i ) 1123 { 1124if (!areEqual (a [i ].value ,b [i ].value )) 1125 { 1126return false; 1127 } 1128 } 1129return true; 1130} 1131 1132bool JSONContainer ::areEqual (const JSONKeyValue * a ,const JSONKeyValue * b ,Index count ) 1133{ 1134if (count == 0 ) 1135 { 1136return true; 1137 } 1138 1139if (count == 1 ) 1140 { 1141return _areEqualOrderedKeys (a ,b ,count ); 1142 } 1143else if (_sameKeyOrder (a ,b ,count )) 1144 { 1145return _areEqualValues (a ,b ,count ); 1146 } 1147else 1148 { 1149// We need to compare with keys in the same order 1150List < JSONKeyValue > sortedAs ; 1151sortedAs .addRange (a ,count ); 1152 1153List < JSONKeyValue > sortedBs ; 1154sortedBs .addRange (b ,count ); 1155 1156sortedAs .sort ( 1157 [](const JSONKeyValue & a ,const JSONKeyValue & b )-> bool {return a .key < b .key ; }); 1158sortedBs .sort ( 1159 [](const JSONKeyValue & a ,const JSONKeyValue & b )-> bool {return a .key < b .key ; }); 1160 1161return _areEqualOrderedKeys (sortedAs .getBuffer (),sortedBs .getBuffer (),count ); 1162 } 1163} 1164 1165bool JSONContainer ::areEqual (const JSONValue & a ,const UnownedStringSlice & slice ) 1166{ 1167return a .getKind ()== JSONValue ::Kind ::String && getTransientString (a )== slice ; 1168} 1169 1170bool JSONContainer ::areEqual (const JSONValue & a ,const JSONValue & b ) 1171{ 1172if (& a == & b ) 1173 { 1174return true; 1175 } 1176 1177if (a .type == b .type ) 1178 { 1179switch (a .type ) 1180 { 1181default : 1182// Invalid are never equal 1183case JSONValue ::Type ::Invalid : 1184return false; 1185case JSONValue ::Type ::True : 1186case JSONValue ::Type ::False : 1187case JSONValue ::Type ::Null : 1188 { 1189return true; 1190 } 1191case JSONValue ::Type ::IntegerLexeme : 1192return asInteger (a )== asInteger (b ); 1193case JSONValue ::Type ::FloatLexeme : 1194return asFloat (a )== asFloat (b ); 1195case JSONValue ::Type ::StringLexeme : 1196 { 1197// If the lexemes are equal they are equal 1198UnownedStringSlice lexemeA = getLexeme (a ); 1199UnownedStringSlice lexemeB = getLexeme (b ); 1200// Else we want to decode the string to be sure if they are equal. 1201return lexemeA == lexemeB || getStringKey (a )== getStringKey (b ); 1202 } 1203case JSONValue ::Type ::IntegerValue : 1204return a .intValue == b .intValue ; 1205case JSONValue ::Type ::FloatValue : 1206return a .floatValue == b .floatValue ; 1207case JSONValue ::Type ::StringValue : 1208return a .stringKey == b .stringKey ; 1209case JSONValue ::Type ::StringRepresentation : 1210 { 1211return a .stringRep == b .stringRep || StringRepresentation ::asSlice (a .stringRep )== 1212StringRepresentation ::asSlice (b .stringRep ); 1213 } 1214case JSONValue ::Type ::Array : 1215 { 1216if (a .rangeIndex == b .rangeIndex ) 1217 { 1218return true; 1219 } 1220auto arrayA = getArray (a ); 1221auto arrayB = getArray (b ); 1222 1223const Index count = arrayA .getCount (); 1224return (count == arrayB .getCount ())&& 1225areEqual (arrayA .getBuffer (),arrayB .getBuffer (),count ); 1226 } 1227case JSONValue ::Type ::Object : 1228 { 1229if (a .rangeIndex == b .rangeIndex ) 1230 { 1231return true; 1232 } 1233const auto aValues = getObject (a ); 1234const auto bValues = getObject (b ); 1235 1236const Index count = aValues .getCount (); 1237return (count == bValues .getCount ())&& 1238areEqual (aValues .getBuffer (),bValues .getBuffer (),count ); 1239 } 1240 } 1241 } 1242 1243// If they are the same kind, and float/int/string we can convert to compare 1244const JSONValue ::Kind kind = a .getKind (); 1245if (kind == b .getKind ()) 1246 { 1247switch (kind ) 1248 { 1249case JSONValue ::Kind ::String : 1250return getStringKey (a )== getStringKey (b ); 1251case JSONValue ::Kind ::Integer : 1252return asInteger (a )== asInteger (b ); 1253case JSONValue ::Kind ::Float : 1254return asFloat (a )== asFloat (b ); 1255default : 1256break ; 1257 } 1258 } 1259 1260return false; 1261} 1262 1263void JSONContainer ::traverseRecursively (const JSONValue & value ,JSONListener * listener ) 1264{ 1265typedef JSONValue ::Type Type ; 1266 1267switch (value .type ) 1268 { 1269case Type ::True : 1270return listener -> addBoolValue (true,value .loc ); 1271case Type ::False : 1272return listener -> addBoolValue (false,value .loc ); 1273case Type ::Null : 1274return listener -> addNullValue (value .loc ); 1275 1276case Type ::StringLexeme : 1277return listener -> addLexemeValue (JSONTokenType ::StringLiteral ,getLexeme (value ),value .loc ); 1278case Type ::IntegerLexeme : 1279return listener -> addLexemeValue (JSONTokenType ::IntegerLiteral ,getLexeme (value ),value .loc ); 1280case Type ::FloatLexeme : 1281return listener -> addLexemeValue (JSONTokenType ::FloatLiteral ,getLexeme (value ),value .loc ); 1282 1283case Type ::IntegerValue : 1284return listener -> addIntegerValue (value .intValue ,value .loc ); 1285case Type ::FloatValue : 1286return listener -> addFloatValue (value .floatValue ,value .loc ); 1287case Type ::StringValue : 1288 { 1289const auto slice = getStringFromKey (value .stringKey ); 1290return listener -> addStringValue (slice ,value .loc ); 1291 } 1292case Type ::StringRepresentation : 1293 { 1294return listener -> addStringValue (getTransientString (value ),value .loc ); 1295 } 1296case Type ::Array : 1297 { 1298listener -> startArray (value .loc ); 1299 1300const auto arr = getArray (value ); 1301 1302for (const auto & arrayValue :arr ) 1303 { 1304traverseRecursively (arrayValue ,listener ); 1305 } 1306 1307listener -> endArray (SourceLoc ()); 1308break ; 1309 } 1310case Type ::Object : 1311 { 1312listener -> startObject (value .loc ); 1313 1314const auto obj = getObject (value ); 1315 1316for (const auto & objKeyValue :obj ) 1317 { 1318// Emit the key 1319const auto keyString = getStringFromKey (objKeyValue .key ); 1320listener -> addUnquotedKey (keyString ,objKeyValue .keyLoc ); 1321 1322// Emit the value associated with the key 1323traverseRecursively (objKeyValue .value ,listener ); 1324 } 1325 1326listener -> endObject (SourceLoc ()); 1327break ; 1328 } 1329default : 1330 { 1331SLANG_ASSERT (!"Invalid type" ); 1332return ; 1333 } 1334 } 1335} 1336 1337/* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 1338 1339JSONBuilder 1340 1341!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ 1342 1343JSONBuilder ::JSONBuilder (JSONContainer * container ,Flags flags ) 1344 :m_container (container ),m_flags (flags ) 1345{ 1346m_state .m_kind = State ::Kind ::Root ; 1347m_state .m_startIndex = 0 ; 1348m_state .resetKey (); 1349 1350m_rootValue .reset (); 1351} 1352 1353void JSONBuilder ::reset () 1354{ 1355// Reset the state 1356m_state .m_kind = State ::Kind ::Root ; 1357m_state .m_startIndex = 0 ; 1358m_state .resetKey (); 1359 1360// Clear the work values 1361m_rootValue .reset (); 1362 1363// Clear the lists 1364m_stateStack .clear (); 1365m_values .clear (); 1366m_keyValues .clear (); 1367} 1368 1369void JSONBuilder ::_popState () 1370{ 1371SLANG_ASSERT (m_stateStack .getCount ()> 0 ); 1372 1373// Reset the end depending on typpe 1374switch (m_state .m_kind ) 1375 { 1376case State ::Kind ::Array : 1377 { 1378m_values .setCount (m_state .m_startIndex ); 1379break ; 1380 } 1381case State ::Kind ::Object : 1382 { 1383m_keyValues .setCount (m_state .m_startIndex ); 1384break ; 1385 } 1386 } 1387 1388// Pop from the stack 1389m_state = m_stateStack .getLast (); 1390m_stateStack .removeLast (); 1391} 1392 1393Index JSONBuilder ::_findKeyIndex (JSONKey key )const 1394{ 1395SLANG_ASSERT (m_state .m_kind == State ::Kind ::Object ); 1396const Index count = m_keyValues .getCount (); 1397for (Index i = m_state .m_startIndex ;i < count ;++ i ) 1398 { 1399auto & keyValue = m_keyValues [i ]; 1400// If we find the key return it's index 1401if (keyValue .key == key ) 1402 { 1403return i ; 1404 } 1405 } 1406return -1 ; 1407} 1408 1409void JSONBuilder ::_add (const JSONValue & value ) 1410{ 1411SLANG_ASSERT (value .isValid ()); 1412switch (m_state .m_kind ) 1413 { 1414case State ::Kind ::Root : 1415 { 1416SLANG_ASSERT (!m_rootValue .isValid ()); 1417m_rootValue = value ; 1418break ; 1419 } 1420case State ::Kind ::Array : 1421 { 1422m_values .add (value ); 1423break ; 1424 } 1425case State ::Kind ::Object : 1426 { 1427SLANG_ASSERT (m_state .hasKey ()); 1428 1429JSONKeyValue keyValue ; 1430keyValue .key = m_state .m_key ; 1431keyValue .keyLoc = m_state .m_keyLoc ; 1432keyValue .value = value ; 1433 1434const Index index = _findKeyIndex (keyValue .key ); 1435if (index >=0 ) 1436 { 1437m_keyValues [index ]= keyValue ; 1438 } 1439else 1440 { 1441m_keyValues .add (keyValue ); 1442 } 1443 1444m_state .resetKey (); 1445break ; 1446 } 1447 } 1448} 1449 1450void JSONBuilder ::startObject (SourceLoc loc ) 1451{ 1452m_stateStack .add (m_state ); 1453m_state .m_kind = State ::Kind ::Object ; 1454m_state .m_startIndex = m_keyValues .getCount (); 1455m_state .m_loc = loc ; 1456m_state .resetKey (); 1457} 1458 1459void JSONBuilder ::endObject (SourceLoc loc ) 1460{ 1461SLANG_UNUSED (loc ); 1462 1463SLANG_ASSERT (m_state .m_kind == State ::Kind ::Object ); 1464 1465const Index count = m_keyValues .getCount ()- m_state .m_startIndex ; 1466const JSONValue value = m_container -> createObject ( 1467m_keyValues .getBuffer ()+ m_state .m_startIndex , 1468count , 1469m_state .m_loc ); 1470 1471// Pop current state 1472_popState (); 1473// Add the value to the current state 1474_add (value ); 1475} 1476 1477void JSONBuilder ::startArray (SourceLoc loc ) 1478{ 1479m_stateStack .add (m_state ); 1480m_state .m_kind = State ::Kind ::Array ; 1481m_state .m_startIndex = m_values .getCount (); 1482m_state .m_loc = loc ; 1483m_state .resetKey (); 1484} 1485 1486void JSONBuilder ::endArray (SourceLoc loc ) 1487{ 1488SLANG_UNUSED (loc ); 1489 1490SLANG_ASSERT (m_state .m_kind == State ::Kind ::Array ); 1491 1492const Index count = m_values .getCount ()- m_state .m_startIndex ; 1493const JSONValue value = 1494m_container -> createArray (m_values .getBuffer ()+ m_state .m_startIndex ,count ,m_state .m_loc ); 1495 1496// Pop current state 1497_popState (); 1498// Add the value to the current state 1499_add (value ); 1500} 1501 1502void JSONBuilder ::addQuotedKey (const UnownedStringSlice & key ,SourceLoc loc ) 1503{ 1504// We need to decode 1505m_work .clear (); 1506StringEscapeHandler * handler = StringEscapeUtil ::getHandler (StringEscapeUtil ::Style ::JSON ); 1507StringEscapeUtil ::appendUnquoted (handler ,key ,m_work ); 1508addUnquotedKey (m_work .getUnownedSlice (),loc ); 1509} 1510 1511void JSONBuilder ::addUnquotedKey (const UnownedStringSlice & key ,SourceLoc loc ) 1512{ 1513SLANG_ASSERT (!m_state .hasKey ()); 1514m_state .setKey (m_container -> getKey (key ),loc ); 1515} 1516 1517void JSONBuilder ::addLexemeValue (JSONTokenType type ,const UnownedStringSlice & value ,SourceLoc loc ) 1518{ 1519switch (type ) 1520 { 1521case JSONTokenType ::True : 1522return _add (JSONValue ::makeBool (true,loc )); 1523case JSONTokenType ::False : 1524return _add (JSONValue ::makeBool (false,loc )); 1525case JSONTokenType ::Null : 1526return _add (JSONValue ::makeNull (loc )); 1527 1528case JSONTokenType ::IntegerLiteral : 1529 { 1530if (m_flags & Flag ::ConvertLexemes ) 1531 { 1532int64_t intValue = -1 ; 1533auto res = StringUtil ::parseInt64 (value ,intValue ); 1534SLANG_UNUSED (res ); 1535SLANG_ASSERT (SLANG_SUCCEEDED (res )); 1536_add (JSONValue ::makeInt (intValue ,loc )); 1537 } 1538else 1539 { 1540SLANG_ASSERT (loc .isValid ()); 1541_add (JSONValue ::makeLexeme (JSONValue ::Type ::IntegerLexeme ,loc ,value .getLength ())); 1542 } 1543break ; 1544 } 1545case JSONTokenType ::FloatLiteral : 1546 { 1547if (m_flags & Flag ::ConvertLexemes ) 1548 { 1549double floatValue = 0 ; 1550auto res = StringUtil ::parseDouble (value ,floatValue ); 1551SLANG_UNUSED (res ); 1552SLANG_ASSERT (SLANG_SUCCEEDED (res )); 1553_add (JSONValue ::makeFloat (floatValue ,loc )); 1554 } 1555else 1556 { 1557SLANG_ASSERT (loc .isValid ()); 1558_add (JSONValue ::makeLexeme (JSONValue ::Type ::FloatLexeme ,loc ,value .getLength ())); 1559 } 1560break ; 1561 } 1562case JSONTokenType ::StringLiteral : 1563 { 1564if (m_flags & Flag ::ConvertLexemes ) 1565 { 1566auto handler = StringEscapeUtil ::getHandler (StringEscapeUtil ::Style ::JSON ); 1567StringBuilder buf ; 1568StringEscapeUtil ::appendUnquoted (handler ,value ,buf ); 1569 1570_add (m_container -> createString (buf .getUnownedSlice (),loc )); 1571 } 1572else 1573 { 1574SLANG_ASSERT (loc .isValid ()); 1575_add (JSONValue ::makeLexeme (JSONValue ::Type ::StringLexeme ,loc ,value .getLength ())); 1576 } 1577break ; 1578 } 1579default : 1580 { 1581SLANG_ASSERT (!"Unhandled type" ); 1582 } 1583 } 1584} 1585 1586void JSONBuilder ::addIntegerValue (int64_t value ,SourceLoc loc ) 1587{ 1588_add (JSONValue ::makeInt (value ,loc )); 1589} 1590 1591void JSONBuilder ::addFloatValue (double value ,SourceLoc loc ) 1592{ 1593_add (JSONValue ::makeFloat (value ,loc )); 1594} 1595 1596void JSONBuilder ::addBoolValue (bool value ,SourceLoc loc ) 1597{ 1598_add (JSONValue ::makeBool (value ,loc )); 1599} 1600 1601void JSONBuilder ::addStringValue (const UnownedStringSlice & slice ,SourceLoc loc ) 1602{ 1603_add (m_container -> createString (slice ,loc )); 1604} 1605 1606void JSONBuilder ::addNullValue (SourceLoc loc ) 1607{ 1608_add (JSONValue ::makeNull (loc )); 1609} 1610 1611}// namespace Slang