| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626 | 
							- {
 
-   LkJSON v1.07
 
-   06 november 2009
 
- * Copyright (c) 2006,2007,2008,2009 Leonid Koninin
 
- * leon_kon@users.sourceforge.net
 
- * All rights reserved.
 
- *
 
- * Redistribution and use in source and binary forms, with or without
 
- * modification, are permitted provided that the following conditions are met:
 
- *     * Redistributions of source code must retain the above copyright
 
- *       notice, this list of conditions and the following disclaimer.
 
- *     * Redistributions in binary form must reproduce the above copyright
 
- *       notice, this list of conditions and the following disclaimer in the
 
- *       documentation and/or other materials provided with the distribution.
 
- *     * Neither the name of the <organization> nor the
 
- *       names of its contributors may be used to endorse or promote products
 
- *       derived from this software without specific prior written permission.
 
- *
 
- * THIS SOFTWARE IS PROVIDED BY Leonid Koninin ``AS IS'' AND ANY
 
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 
- * DISCLAIMED. IN NO EVENT SHALL Leonid Koninin BE LIABLE FOR ANY
 
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-   changes:
 
-   v1.07 06/11/2009 * fixed a bug in js_string - thanks to Andrew G. Khodotov
 
-                    * fixed error with double-slashes - thanks to anonymous user
 
-                    * fixed a BOM bug in parser, thanks to jasper_dale
 
-   v1.06 13/03/2009 * fixed a bug in string parsing routine
 
-                    * looked routine from the Adrian M. Jones, and get some
 
-                      ideas from it; thanks a lot, Adrian!
 
-                    * checked error reported by phpop and fix it in the string
 
-                      routine; also, thanks for advice.
 
-   v1.05 26/01/2009 + added port to D2009 by Daniele Teti, thanx a lot! really,
 
-                      i haven't the 2009 version, so i can't play with it. I was
 
-                      add USE_D2009 directive below, disabled by default
 
-                    * fixed two small bugs in parsing object: errors with empty
 
-                      object and list; thanx to RSDN's delphi forum members
 
-                    * fixed "[2229135] Value deletion is broken" tracker
 
-                      issue, thanx to anonymous sender provided code for
 
-                      tree version
 
-                    * fixed js_string according to "[1917047] (much) faster
 
-                      js_string Parse" tracker issue by Joao Inacio; a lot of
 
-                      thanx, great speedup!
 
-   v1.04 05/04/2008 + a declaration of Field property moved from TlkJSONobject
 
-                      to TlkJSONbase; thanx for idea to Andrey Lukyanov; this
 
-                      improve objects use, look the bottom of SAMPLE2.DPR
 
-                    * fixed field name in TlkJSONobject to WideString
 
-   v1.03 14/03/2008 + added a code for generating readable JSON text, sended to
 
-                      me by Kusnassriyanto Saiful Bahri, thanx to him!
 
-                    * from this version, library distributed with BSD
 
-                      license, more pleasure for commercial programmers :)
 
-                    * was rewritten internal storing of objects, repacing
 
-                      hash tables with balanced trees (AA tree, by classic
 
-                      author's variant). On mine machine, with enabled fastmm,
 
-                      tree variant is about 30% slower in from-zero creation,
 
-                      but about 50% faster in parsing; also deletion of
 
-                      objects will be much faster than a hash-one.
 
-                      Hashes (old-style) can be switched on by enabling
 
-                      USE_HASH directive below
 
-   v1.02 14/09/2007 * fix mistypes in diffrent places; thanx for reports
 
-                      to Aleksandr Fedorov and Tobias Wrede
 
-   v1.01 18/05/2007 * fix small bug in new text generation routine, check
 
-                      library for leaks by fastmm4; thanx for idea and comments
 
-                      for Glynn Owen
 
-   v1.00 12/05/2007 * some fixes in new code (mistypes, mistypes...)
 
-                    * also many fixes by ideas of Henri Gourvest - big thanx
 
-                      for him again; he send me code for thread-safe initializing
 
-                      of hash table, some FPC-compatible issues (not tested by
 
-                      myself) and better code for localization in latest
 
-                      delphi versions; very, very big thanx!
 
-                    * rewritten procedure of json text generating, with wich
 
-                      work of it speeds up 4-5 times (on test) its good for
 
-                      a large objects
 
-                    * started a large work for making source code self-doc
 
-                      (not autodoc!)
 
-   v0.99 10/05/2007 + add functions to list and object:
 
-                       function getInt(idx: Integer): Integer;
 
-                       function getString(idx: Integer): String;
 
-                       function getWideString(idx: Integer):WideString;
 
-                       function getDouble(idx: Integer): Double;
 
-                       function getBoolean(idx: Integer): Boolean;
 
-                    + add overloaded functions to object:
 
-                       function getDouble(nm: String): Double; overload;
 
-                       function getInt(nm: String): Integer; overload;
 
-                       function getString(nm: String): String; overload;
 
-                       function getWideString(nm: String): WideString; overload;
 
-                       function getBoolean(nm: String): Boolean; overload;
 
-                    * changed storing mech of TlkJSONcustomlist descendants from
 
-                      dynamic array to TList; this gives us great speedup with
 
-                      lesser changes; thanx for idea to Henri Gourvest
 
-                    * also reworked hashtable to work with TList, so it also
 
-                      increase speed of work
 
-   v0.98 09/05/2007 * fix small bug in work with WideStrings(UTF8), thanx to
 
-                      IVO GELOV to description and sources
 
-   v0.97 10/04/2007 + add capabilities to work with KOL delphi projects; for
 
-                      this will define KOL variable in begin of text; of course,
 
-                      in this case object TlkJSONstreamed is not compiled.
 
-   v0.96 03/30/2007 + add TlkJSONFuncEnum and method ForEach in all
 
-                      TlkJSONcustomlist descendants
 
-                    + add property UseHash(r/o) to TlkJSONobject, and parameter
 
-                      UseHash:Boolean to object constructors; set it to false
 
-                      allow to disable using of hash-table, what can increase
 
-                      speed of work in case of objects with low number of
 
-                      methods(fields); [by default it is true]
 
-                    + added conditional compile directive DOTNET for use in .Net
 
-                      based delphi versions; remove dot in declaration below
 
-                      (thanx for idea and sample code to Tim Radford)
 
-                    + added property HashOf to TlkHashTable to allow use of
 
-                      users hash functions; on enter is widestring, on exit is
 
-                      cardinal (32 bit unsigned). Original HashOf renamed to
 
-                      DefaultHashOf
 
-                    * hash table object of TlkJSONobject wrapped by property called
 
-                      HashTable
 
-                    * fixed some minor bugs
 
-   v0.95 03/29/2007 + add object TlkJSONstreamed what descendant of TlkJSON and
 
-                      able to load/save JSON objects from/to streams/files.
 
-                    * fixed small bug in generating of unicode strings representation
 
-   v0.94 03/27/2007 + add properties NameOf and FieldByIndex to TlkJSONobject
 
-                    * fix small error in parsing unicode chars
 
-                    * small changes in hashing code (try to speed up)
 
-   v0.93 03/05/2007 + add overloaded functions to list and object
 
-                    + add enum type TlkJSONtypes
 
-                    + add functions: SelfType:TlkJSONtypes and
 
-                      SelfTypeName: String to every TlkJSONbase child
 
-                    * fix mistype 'IndefOfName' to 'IndexOfName'
 
-                    * fix mistype 'IndefOfObject' to 'IndexOfObject'
 
-   v0.92 03/02/2007 + add some fix to TlkJSON.ParseText to fix bug with parsing
 
-                      objects - object methods not always added properly
 
-                      to hash array (thanx to Chris Matheson)
 
-   ...
 
- }
 
- unit uLkJSON;
 
- {$IFDEF fpc}
 
-   {$MODE objfpc}
 
-   {$H+}
 
-   {.$DEFINE HAVE_FORMATSETTING}
 
- {$ELSE}
 
-   {$IF RTLVersion > 14.00}
 
-     {$DEFINE HAVE_FORMATSETTING}
 
-     {$IF RTLVersion > 19.00}
 
-       {$DEFINE USE_D2009}
 
-     {$IFEND}
 
-   {$IFEND}
 
- {$ENDIF}
 
- interface
 
- {.$DEFINE USE_D2009}
 
- {.$DEFINE KOL}
 
- {.$define DOTNET}
 
- {$DEFINE THREADSAFE}
 
- {$DEFINE NEW_STYLE_GENERATE}
 
- {.$DEFINE USE_HASH}
 
- {.$DEFINE TCB_EXT}
 
- uses windows,
 
-   SysUtils,
 
- {$IFNDEF KOL}
 
-   classes,
 
- {$ELSE}
 
-   kol,
 
- {$ENDIF}
 
-   variants;
 
- type
 
-   TlkJSONtypes = (jsBase, jsNumber, jsString, jsBoolean, jsNull,
 
-     jsList, jsObject);
 
- {$IFDEF DOTNET}
 
-   TlkJSONdotnetclass = class
 
-   public
 
-     constructor Create;
 
-     destructor Destroy; override;
 
-     procedure AfterConstruction; virtual;
 
-     procedure BeforeDestruction; virtual;
 
-   end;
 
- {$ENDIF DOTNET}
 
-   TlkJSONbase = class{$IFDEF DOTNET}(TlkJSONdotnetclass){$ENDIF}
 
-   protected
 
-     function GetValue: variant; virtual;
 
-     procedure SetValue(const AValue: variant); virtual;
 
-     function GetChild(idx: Integer): TlkJSONbase; virtual;
 
-     procedure SetChild(idx: Integer; const AValue: TlkJSONbase);
 
-       virtual;
 
-     function GetCount: Integer; virtual;
 
-     function GetField(AName: Variant):TlkJSONbase; virtual;
 
-   public
 
-     property Field[AName: Variant]: TlkJSONbase read GetField;
 
-     property Count: Integer read GetCount;
 
-     property Child[idx: Integer]: TlkJSONbase read GetChild write SetChild;
 
-     property Value: variant read GetValue write SetValue;
 
-     class function SelfType: TlkJSONtypes; virtual;
 
-     class function SelfTypeName: string; virtual;
 
-   end;
 
-   TlkJSONnumber = class(TlkJSONbase)
 
-   protected
 
-     FValue: extended;
 
-     function GetValue: Variant; override;
 
-     procedure SetValue(const AValue: Variant); override;
 
-   public
 
-     procedure AfterConstruction; override;
 
-     class function Generate(AValue: extended = 0): TlkJSONnumber;
 
-     class function SelfType: TlkJSONtypes; override;
 
-     class function SelfTypeName: string; override;
 
-   end;
 
-   TlkJSONstring = class(TlkJSONbase)
 
-   protected
 
-     FValue: WideString;
 
-     function GetValue: Variant; override;
 
-     procedure SetValue(const AValue: Variant); override;
 
-   public
 
-     procedure AfterConstruction; override;
 
-     class function Generate(const wsValue: WideString = ''):
 
-       TlkJSONstring;
 
-     class function SelfType: TlkJSONtypes; override;
 
-     class function SelfTypeName: string; override;
 
-   end;
 
-   TlkJSONboolean = class(TlkJSONbase)
 
-   protected
 
-     FValue: Boolean;
 
-     function GetValue: Variant; override;
 
-     procedure SetValue(const AValue: Variant); override;
 
-   public
 
-     procedure AfterConstruction; override;
 
-     class function Generate(AValue: Boolean = true): TlkJSONboolean;
 
-     class function SelfType: TlkJSONtypes; override;
 
-     class function SelfTypeName: string; override;
 
-   end;
 
-   TlkJSONnull = class(TlkJSONbase)
 
-   protected
 
-     function GetValue: Variant; override;
 
-     function Generate: TlkJSONnull;
 
-   public
 
-     class function SelfType: TlkJSONtypes; override;
 
-     class function SelfTypeName: string; override;
 
-   end;
 
-   TlkJSONFuncEnum = procedure(ElName: string; Elem: TlkJSONbase;
 
-     data: pointer; var Continue: Boolean) of object;
 
-   TlkJSONcustomlist = class(TlkJSONbase)
 
-   protected
 
- //    FValue: array of TlkJSONbase;
 
-     fList: TList;
 
-     function GetCount: Integer; override;
 
-     function GetChild(idx: Integer): TlkJSONbase; override;
 
-     procedure SetChild(idx: Integer; const AValue: TlkJSONbase);
 
-       override;
 
-     function ForEachElement(idx: Integer; var nm: string):
 
-       TlkJSONbase; virtual;
 
-     function GetField(AName: Variant):TlkJSONbase; override;
 
-     function _Add(obj: TlkJSONbase): Integer; virtual;
 
-     procedure _Delete(iIndex: Integer); virtual;
 
-     function _IndexOf(obj: TlkJSONbase): Integer; virtual;
 
-   public
 
-     procedure ForEach(fnCallBack: TlkJSONFuncEnum; pUserData:
 
-       pointer);
 
-     procedure AfterConstruction; override;
 
-     procedure BeforeDestruction; override;
 
-     function getInt(idx: Integer): Integer; virtual;
 
-     function getString(idx: Integer): string; virtual;
 
-     function getWideString(idx: Integer): WideString; virtual;
 
-     function getDouble(idx: Integer): Double; virtual;
 
-     function getBoolean(idx: Integer): Boolean; virtual;
 
-   end;
 
-   TlkJSONlist = class(TlkJSONcustomlist)
 
-   protected
 
-   public
 
-     function Add(obj: TlkJSONbase): Integer; overload;
 
-     function Add(aboolean: Boolean): Integer; overload;
 
-     function Add(nmb: double): Integer; overload;
 
-     function Add(s: string): Integer; overload;
 
-     function Add(const ws: WideString): Integer; overload;
 
-     function Add(inmb: Integer): Integer; overload;
 
-     procedure Delete(idx: Integer);
 
-     function IndexOf(obj: TlkJSONbase): Integer;
 
-     class function Generate: TlkJSONlist;
 
-     class function SelfType: TlkJSONtypes; override;
 
-     class function SelfTypeName: string; override;
 
-   end;
 
-   TlkJSONobjectmethod = class(TlkJSONbase)
 
-   protected
 
-     FValue: TlkJSONbase;
 
-     FName: WideString;
 
-     procedure SetName(const AValue: WideString);
 
-   public
 
-     property ObjValue: TlkJSONbase read FValue;
 
-     procedure AfterConstruction; override;
 
-     procedure BeforeDestruction; override;
 
-     property Name: WideString read FName write SetName;
 
-     class function Generate(const aname: WideString; aobj: TlkJSONbase):
 
-       TlkJSONobjectmethod;
 
-   end;
 
- {$IFDEF USE_HASH}
 
-   PlkHashItem = ^TlkHashItem;
 
-   TlkHashItem = packed record
 
-     hash: cardinal;
 
-     index: Integer;
 
-   end;
 
-   TlkHashFunction = function(const ws: WideString): cardinal of
 
-     object;
 
-   TlkHashTable = class
 
-   private
 
-     FParent: TObject; // TCB:parent for check chaining op.
 
-     FHashFunction: TlkHashFunction;
 
-     procedure SetHashFunction(const AValue: TlkHashFunction);
 
-   protected
 
-     a_x: array[0..255] of TList;
 
-     procedure hswap(j, k, l: Integer);
 
-     function InTable(const ws: WideString; var i, j, k: cardinal):
 
-       Boolean;
 
-   public
 
-     function counters: string;
 
-     function DefaultHashOf(const ws: WideString): cardinal;
 
-     function SimpleHashOf(const ws: WideString): cardinal;
 
-     property HashOf: TlkHashFunction read FHashFunction write
 
-       SetHashFunction;
 
-     function IndexOf(const ws: WideString): Integer;
 
-     procedure AddPair(const ws: WideString; idx: Integer);
 
-     procedure Delete(const ws: WideString);
 
-     constructor Create;
 
-     destructor Destroy; override;
 
-   end;
 
- {$ELSE}
 
- // implementation based on "Arne Andersson, Balanced Search Trees Made Simpler"
 
-   PlkBalNode = ^TlkBalNode;
 
-   TlkBalNode = packed record
 
-     left,right: PlkBalNode;
 
-     level: byte;
 
-     key: Integer;
 
-     nm: WideString;
 
-   end;
 
-   TlkBalTree = class
 
-   protected
 
-     fdeleted,flast,fbottom,froot: PlkBalNode;
 
-     procedure skew(var t:PlkBalNode);
 
-     procedure split(var t:PlkBalNode);
 
-   public
 
-     function counters: string;
 
-     procedure Clear;
 
-     function Insert(const ws: WideString; x: Integer): Boolean;
 
-     function Delete(const ws: WideString): Boolean;
 
-     function IndexOf(const ws: WideString): Integer;
 
-     constructor Create;
 
-     destructor Destroy; override;
 
-   end;
 
- {$ENDIF USE_HASH}
 
-   TlkJSONobject = class(TlkJSONcustomlist)
 
-   protected
 
- {$IFDEF USE_HASH}
 
-     ht: TlkHashTable;
 
- {$ELSE}
 
-     ht: TlkBalTree;
 
- {$ENDIF USE_HASH}
 
-     FUseHash: Boolean;
 
-     function GetFieldByIndex(idx: Integer): TlkJSONbase;
 
-     function GetNameOf(idx: Integer): WideString;
 
-     procedure SetFieldByIndex(idx: Integer; const AValue: TlkJSONbase);
 
- {$IFDEF USE_HASH}
 
-     function GetHashTable: TlkHashTable;
 
- {$ELSE}
 
-     function GetHashTable: TlkBalTree;
 
- {$ENDIF USE_HASH}
 
-     function ForEachElement(idx: Integer; var nm: string): TlkJSONbase;
 
-       override;
 
-     function GetField(AName: Variant):TlkJSONbase; override;
 
-   public
 
-     property UseHash: Boolean read FUseHash;
 
- {$IFDEF USE_HASH}
 
-     property HashTable: TlkHashTable read GetHashTable;
 
- {$ELSE}
 
-     property HashTable: TlkBalTree read GetHashTable;
 
- {$ENDIF USE_HASH}
 
-     function Add(const aname: WideString; aobj: TlkJSONbase): Integer;
 
-       overload;
 
-     function OldGetField(nm: WideString): TlkJSONbase;
 
-     procedure OldSetField(nm: WideString; const AValue: TlkJSONbase);
 
-     function Add(const aname: WideString; aboolean: Boolean): Integer; overload;
 
-     function Add(const aname: WideString; nmb: double): Integer; overload;
 
-     function Add(const aname: WideString; s: string): Integer; overload;
 
-     function Add(const aname: WideString; const ws: WideString): Integer;
 
-       overload;
 
-     function Add(const aname: WideString; inmb: Integer): Integer; overload;
 
-     procedure Delete(idx: Integer);
 
-     function IndexOfName(const aname: WideString): Integer;
 
-     function IndexOfObject(aobj: TlkJSONbase): Integer;
 
-     property Field[nm: WideString]: TlkJSONbase read OldGetField
 
-       write OldSetField; default;
 
-     constructor Create(bUseHash: Boolean = true);
 
-     destructor Destroy; override;
 
-     class function Generate(AUseHash: Boolean = true): TlkJSONobject;
 
-     class function SelfType: TlkJSONtypes; override;
 
-     class function SelfTypeName: string; override;
 
-     property FieldByIndex[idx: Integer]: TlkJSONbase read GetFieldByIndex
 
-     write SetFieldByIndex;
 
-     property NameOf[idx: Integer]: WideString read GetNameOf;
 
-     function getDouble(idx: Integer): Double; overload; override;
 
-     function getInt(idx: Integer): Integer; overload; override;
 
-     function getString(idx: Integer): string; overload; override;
 
-     function getWideString(idx: Integer): WideString; overload; override;
 
-     function getBoolean(idx: Integer): Boolean; overload; override;
 
-     function {$ifdef TCB_EXT}getDoubleFromName{$else}getDouble{$endif}
 
-       (nm: string): Double; overload;
 
-     function {$ifdef TCB_EXT}getIntFromName{$else}getInt{$endif}
 
-       (nm: string): Integer; overload;
 
-     function {$ifdef TCB_EXT}getStringFromName{$else}getString{$endif}
 
-       (nm: string): string; overload;
 
-     function {$ifdef TCB_EXT}getWideStringFromName{$else}getWideString{$endif}
 
-       (nm: string): WideString; overload;
 
-     function {$ifdef TCB_EXT}getBooleanFromName{$else}getBoolean{$endif}
 
-       (nm: string): Boolean; overload;
 
-   end;
 
-   TlkJSON = class
 
-   public
 
-     class function ParseText(const txt: string): TlkJSONbase;
 
-     class function GenerateText(obj: TlkJSONbase): string;
 
-   end;
 
- {$IFNDEF KOL}
 
-   TlkJSONstreamed = class(TlkJSON)
 
-     class function LoadFromStream(src: TStream): TlkJSONbase;
 
-     class procedure SaveToStream(obj: TlkJSONbase; dst: TStream);
 
-     class function LoadFromFile(srcname: string): TlkJSONbase;
 
-     class procedure SaveToFile(obj: TlkJSONbase; dstname: string);
 
-   end;
 
- {$ENDIF}
 
- function GenerateReadableText(vObj: TlkJSONbase; var vLevel:
 
-   Integer): string;
 
- implementation
 
- uses math,strutils;
 
- type
 
-   ElkIntException = class(Exception)
 
-   public
 
-     idx: Integer;
 
-     constructor Create(idx: Integer; msg: string);
 
-   end;
 
- // author of next two functions is Kusnassriyanto Saiful Bahri
 
- function Indent(vTab: Integer): string;
 
- begin
 
-   result := DupeString('  ', vTab);
 
- end;
 
- function GenerateReadableText(vObj: TlkJSONbase; var vLevel:
 
-   Integer): string;
 
- var
 
-   i: Integer;
 
-   vStr: string;
 
-   xs: TlkJSONstring;
 
- begin
 
-   vLevel := vLevel + 1;
 
-   if vObj is TlkJSONObject then
 
-     begin
 
-       vStr := '';
 
-       for i := 0 to TlkJSONobject(vObj).Count - 1 do
 
-         begin
 
-           if vStr <> '' then
 
-             begin
 
-               vStr := vStr + ','#13#10;
 
-             end;
 
-           vStr := vStr + Indent(vLevel) +
 
-             GenerateReadableText(TlkJSONobject(vObj).Child[i], vLevel);
 
-         end;
 
-       if vStr <> '' then
 
-         begin
 
-           vStr := '{'#13#10 + vStr + #13#10 + Indent(vLevel - 1) + '}';
 
-         end
 
-       else
 
-         begin
 
-           vStr := '{}';
 
-         end;
 
-       result := vStr;
 
-     end
 
-   else if vObj is TlkJSONList then
 
-     begin
 
-       vStr := '';
 
-       for i := 0 to TlkJSONList(vObj).Count - 1 do
 
-         begin
 
-           if vStr <> '' then
 
-             begin
 
-               vStr := vStr + ','#13#10;
 
-             end;
 
-           vStr := vStr + Indent(vLevel) +
 
-               GenerateReadableText(TlkJSONList(vObj).Child[i], vLevel);
 
-         end;
 
-       if vStr <> '' then
 
-         begin
 
-           vStr := '['#13#10 + vStr + #13#10 + Indent(vLevel - 1) + ']';
 
-         end
 
-       else
 
-         begin
 
-           vStr := '[]';
 
-         end;
 
-       result := vStr;
 
-     end
 
-   else if vObj is TlkJSONobjectmethod then
 
-     begin
 
-       vStr := '';
 
-       xs := TlkJSONstring.Create;
 
-       try
 
-         xs.Value := TlkJSONobjectMethod(vObj).Name;
 
-         vStr := GenerateReadableText(xs, vLevel);
 
-         vLevel := vLevel - 1;
 
-         vStr := vStr + ':' + GenerateReadableText(TlkJSONbase(
 
-           TlkJSONobjectmethod(vObj).ObjValue), vLevel);
 
-       //vStr := vStr + ':' + GenerateReadableText(TlkJSONbase(vObj), vLevel);
 
-         vLevel := vLevel + 1;
 
-         result := vStr;
 
-       finally
 
-         xs.Free;
 
-       end;
 
-     end
 
-   else
 
-     begin
 
-       if vObj is TlkJSONobjectmethod then
 
-         begin
 
-           if TlkJSONobjectMethod(vObj).Name <> '' then
 
-             begin
 
-             end;
 
-         end;
 
-       result := TlkJSON.GenerateText(vObj);
 
-     end;
 
-   vLevel := vLevel - 1;
 
- end;
 
- // author of this routine is IVO GELOV
 
- function code2utf(iNumber: Integer): UTF8String;
 
- begin
 
-   if iNumber < 128 then Result := chr(iNumber)
 
-   else if iNumber < 2048 then
 
-     Result := chr((iNumber shr 6) + 192) + chr((iNumber and 63) + 128)
 
-   else if iNumber < 65536 then
 
-     Result := chr((iNumber shr 12) + 224) + chr(((iNumber shr 6) and
 
-       63) + 128) + chr((iNumber and 63) + 128)
 
-   else if iNumber < 2097152 then
 
-     Result := chr((iNumber shr 18) + 240) + chr(((iNumber shr 12) and
 
-       63) + 128) + chr(((iNumber shr 6) and 63) + 128) +
 
-       chr((iNumber and 63) + 128);
 
- end;
 
- { TlkJSONbase }
 
- function TlkJSONbase.GetChild(idx: Integer): TlkJSONbase;
 
- begin
 
-   result := nil;
 
- end;
 
- function TlkJSONbase.GetCount: Integer;
 
- begin
 
-   result := 0;
 
- end;
 
- function TlkJSONbase.GetField(AName: Variant):TlkJSONbase;
 
- begin
 
-   result := self;
 
- end;
 
- function TlkJSONbase.GetValue: variant;
 
- begin
 
-   result := variants.Null;
 
- end;
 
- class function TlkJSONbase.SelfType: TlkJSONtypes;
 
- begin
 
-   result := jsBase;
 
- end;
 
- class function TlkJSONbase.SelfTypeName: string;
 
- begin
 
-   result := 'jsBase';
 
- end;
 
- procedure TlkJSONbase.SetChild(idx: Integer; const AValue:
 
-   TlkJSONbase);
 
- begin
 
- end;
 
- procedure TlkJSONbase.SetValue(const AValue: variant);
 
- begin
 
- end;
 
- { TlkJSONnumber }
 
- procedure TlkJSONnumber.AfterConstruction;
 
- begin
 
-   inherited;
 
-   FValue := 0;
 
- end;
 
- class function TlkJSONnumber.Generate(AValue: extended):
 
-   TlkJSONnumber;
 
- begin
 
-   result := TlkJSONnumber.Create;
 
-   result.FValue := AValue;
 
- end;
 
- function TlkJSONnumber.GetValue: Variant;
 
- begin
 
-   result := FValue;
 
- end;
 
- class function TlkJSONnumber.SelfType: TlkJSONtypes;
 
- begin
 
-   result := jsNumber;
 
- end;
 
- class function TlkJSONnumber.SelfTypeName: string;
 
- begin
 
-   result := 'jsNumber';
 
- end;
 
- procedure TlkJSONnumber.SetValue(const AValue: Variant);
 
- begin
 
-   FValue := VarAsType(AValue, varDouble);
 
- end;
 
- { TlkJSONstring }
 
- procedure TlkJSONstring.AfterConstruction;
 
- begin
 
-   inherited;
 
-   FValue := '';
 
- end;
 
- class function TlkJSONstring.Generate(const wsValue: WideString):
 
-   TlkJSONstring;
 
- begin
 
-   result := TlkJSONstring.Create;
 
-   result.FValue := wsValue;
 
- end;
 
- function TlkJSONstring.GetValue: Variant;
 
- begin
 
-   result := FValue;
 
- end;
 
- class function TlkJSONstring.SelfType: TlkJSONtypes;
 
- begin
 
-   result := jsString;
 
- end;
 
- class function TlkJSONstring.SelfTypeName: string;
 
- begin
 
-   result := 'jsString';
 
- end;
 
- procedure TlkJSONstring.SetValue(const AValue: Variant);
 
- begin
 
-   FValue := VarToWideStr(AValue);
 
- end;
 
- { TlkJSONboolean }
 
- procedure TlkJSONboolean.AfterConstruction;
 
- begin
 
-   FValue := false;
 
- end;
 
- class function TlkJSONboolean.Generate(AValue: Boolean):
 
-   TlkJSONboolean;
 
- begin
 
-   result := TlkJSONboolean.Create;
 
-   result.Value := AValue;
 
- end;
 
- function TlkJSONboolean.GetValue: Variant;
 
- begin
 
-   result := FValue;
 
- end;
 
- class function TlkJSONboolean.SelfType: TlkJSONtypes;
 
- begin
 
-   Result := jsBoolean;
 
- end;
 
- class function TlkJSONboolean.SelfTypeName: string;
 
- begin
 
-   Result := 'jsBoolean';
 
- end;
 
- procedure TlkJSONboolean.SetValue(const AValue: Variant);
 
- begin
 
-   FValue := boolean(AValue);
 
- end;
 
- { TlkJSONnull }
 
- function TlkJSONnull.Generate: TlkJSONnull;
 
- begin
 
-   result := TlkJSONnull.Create;
 
- end;
 
- function TlkJSONnull.GetValue: Variant;
 
- begin
 
-   result := variants.Null;
 
- end;
 
- class function TlkJSONnull.SelfType: TlkJSONtypes;
 
- begin
 
-   result := jsNull;
 
- end;
 
- class function TlkJSONnull.SelfTypeName: string;
 
- begin
 
-   result := 'jsNull';
 
- end;
 
- { TlkJSONcustomlist }
 
- function TlkJSONcustomlist._Add(obj: TlkJSONbase): Integer;
 
- begin
 
-   if not Assigned(obj) then
 
-     begin
 
-       result := -1;
 
-       exit;
 
-     end;
 
-   result := fList.Add(obj);
 
- end;
 
- procedure TlkJSONcustomlist.AfterConstruction;
 
- begin
 
-   inherited;
 
-   fList := TList.Create;
 
- end;
 
- procedure TlkJSONcustomlist.BeforeDestruction;
 
- var
 
-   i: Integer;
 
- begin
 
-   for i := (Count - 1) downto 0 do _Delete(i);
 
-   fList.Free;
 
-   inherited;
 
- end;
 
- // renamed
 
- procedure TlkJSONcustomlist._Delete(iIndex: Integer);
 
- var
 
-   idx: Integer;
 
- begin
 
-   if not ((iIndex < 0) or (iIndex >= Count)) then
 
-     begin
 
-       if fList.Items[iIndex] <> nil then
 
-         TlkJSONbase(fList.Items[iIndex]).Free;
 
-       idx := pred(fList.Count);
 
-       if iIndex<idx then
 
-         begin
 
-           fList.Items[iIndex] := fList.Items[idx];
 
-           fList.Delete(idx);
 
-         end
 
-       else
 
-         begin
 
-           fList.Delete(iIndex);
 
-         end;
 
-     end;
 
- end;
 
- function TlkJSONcustomlist.GetChild(idx: Integer): TlkJSONbase;
 
- begin
 
-   if (idx < 0) or (idx >= Count) then
 
-     begin
 
-       result := nil;
 
-     end
 
-   else
 
-     begin
 
-       result := fList.Items[idx];
 
-     end;
 
- end;
 
- function TlkJSONcustomlist.GetCount: Integer;
 
- begin
 
-   result := fList.Count;
 
- end;
 
- function TlkJSONcustomlist._IndexOf(obj: TlkJSONbase): Integer;
 
- begin
 
-   result := fList.IndexOf(obj);
 
- end;
 
- procedure TlkJSONcustomlist.SetChild(idx: Integer; const AValue:
 
-   TlkJSONbase);
 
- begin
 
-   if not ((idx < 0) or (idx >= Count)) then
 
-     begin
 
-       if fList.Items[idx] <> nil then
 
-         TlkJSONbase(fList.Items[idx]).Free;
 
-       fList.Items[idx] := AValue;
 
-     end;
 
- end;
 
- procedure TlkJSONcustomlist.ForEach(fnCallBack: TlkJSONFuncEnum;
 
-   pUserData:
 
-   pointer);
 
- var
 
-   iCount: Integer;
 
-   IsContinue: Boolean;
 
-   anJSON: TlkJSONbase;
 
-   wsObject: string;
 
- begin
 
-   if not assigned(fnCallBack) then exit;
 
-   IsContinue := true;
 
-   for iCount := 0 to GetCount - 1 do
 
-     begin
 
-       anJSON := ForEachElement(iCount, wsObject);
 
-       if assigned(anJSON) then
 
-         fnCallBack(wsObject, anJSON, pUserData, IsContinue);
 
-       if not IsContinue then break;
 
-     end;
 
- end;
 
- ///---- renamed to here
 
- function TlkJSONcustomlist.GetField(AName: Variant):TlkJSONbase;
 
- var
 
-   index: Integer;
 
- begin
 
-   if VarIsNumeric(AName) then
 
-     begin
 
-       index := integer(AName);
 
-       result := GetChild(index);
 
-     end
 
-   else
 
-     begin
 
-       result := inherited GetField(AName);
 
-     end;
 
- end;
 
- function TlkJSONcustomlist.ForEachElement(idx: Integer; var nm:
 
-   string): TlkJSONbase;
 
- begin
 
-   nm := inttostr(idx);
 
-   result := GetChild(idx);
 
- end;
 
- function TlkJSONcustomlist.getDouble(idx: Integer): Double;
 
- var
 
-   jn: TlkJSONnumber;
 
- begin
 
-   jn := Child[idx] as TlkJSONnumber;
 
-   if not assigned(jn) then result := 0
 
-   else result := jn.Value;
 
- end;
 
- function TlkJSONcustomlist.getInt(idx: Integer): Integer;
 
- var
 
-   jn: TlkJSONnumber;
 
- begin
 
-   jn := Child[idx] as TlkJSONnumber;
 
-   if not assigned(jn) then result := 0
 
-   else result := round(int(jn.Value));
 
- end;
 
- function TlkJSONcustomlist.getString(idx: Integer): string;
 
- var
 
-   js: TlkJSONstring;
 
- begin
 
-   js := Child[idx] as TlkJSONstring;
 
-   if not assigned(js) then result := ''
 
-   else result := VarToStr(js.Value);
 
- end;
 
- function TlkJSONcustomlist.getWideString(idx: Integer): WideString;
 
- var
 
-   js: TlkJSONstring;
 
- begin
 
-   js := Child[idx] as TlkJSONstring;
 
-   if not assigned(js) then result := ''
 
-   else result := VarToWideStr(js.Value);
 
- end;
 
- function TlkJSONcustomlist.getBoolean(idx: Integer): Boolean;
 
- var
 
-   jb: TlkJSONboolean;
 
- begin
 
-   jb := Child[idx] as TlkJSONboolean;
 
-   if not assigned(jb) then result := false
 
-   else result := jb.Value;
 
- end;
 
- { TlkJSONobjectmethod }
 
- procedure TlkJSONobjectmethod.AfterConstruction;
 
- begin
 
-   inherited;
 
-   FValue := nil;
 
-   FName := '';
 
- end;
 
- procedure TlkJSONobjectmethod.BeforeDestruction;
 
- begin
 
-   FName := '';
 
-   if FValue <> nil then
 
-     begin
 
-       FValue.Free;
 
-       FValue := nil;
 
-     end;
 
-   inherited;
 
- end;
 
- class function TlkJSONobjectmethod.Generate(const aname: WideString;
 
-   aobj: TlkJSONbase): TlkJSONobjectmethod;
 
- begin
 
-   result := TlkJSONobjectmethod.Create;
 
-   result.FName := aname;
 
-   result.FValue := aobj;
 
- end;
 
- procedure TlkJSONobjectmethod.SetName(const AValue: WideString);
 
- begin
 
-   FName := AValue;
 
- end;
 
- { TlkJSONlist }
 
- function TlkJSONlist.Add(obj: TlkJSONbase): Integer;
 
- begin
 
-   result := _Add(obj);
 
- end;
 
- function TlkJSONlist.Add(nmb: double): Integer;
 
- begin
 
-   Result := self.Add(TlkJSONnumber.Generate(nmb));
 
- end;
 
- function TlkJSONlist.Add(aboolean: Boolean): Integer;
 
- begin
 
-   Result := self.Add(TlkJSONboolean.Generate(aboolean));
 
- end;
 
- function TlkJSONlist.Add(inmb: Integer): Integer;
 
- begin
 
-   Result := self.Add(TlkJSONnumber.Generate(inmb));
 
- end;
 
- function TlkJSONlist.Add(const ws: WideString): Integer;
 
- begin
 
-   Result := self.Add(TlkJSONstring.Generate(ws));
 
- end;
 
- function TlkJSONlist.Add(s: string): Integer;
 
- begin
 
-   Result := self.Add(TlkJSONstring.Generate(s));
 
- end;
 
- procedure TlkJSONlist.Delete(idx: Integer);
 
- begin
 
-   _Delete(idx);
 
- end;
 
- class function TlkJSONlist.Generate: TlkJSONlist;
 
- begin
 
-   result := TlkJSONlist.Create;
 
- end;
 
- function TlkJSONlist.IndexOf(obj: TlkJSONbase): Integer;
 
- begin
 
-   result := _IndexOf(obj);
 
- end;
 
- class function TlkJSONlist.SelfType: TlkJSONtypes;
 
- begin
 
-   result := jsList;
 
- end;
 
- class function TlkJSONlist.SelfTypeName: string;
 
- begin
 
-   result := 'jsList';
 
- end;
 
- { TlkJSONobject }
 
- function TlkJSONobject.Add(const aname: WideString; aobj:
 
-   TlkJSONbase):
 
-   Integer;
 
- var
 
-   mth: TlkJSONobjectmethod;
 
- begin
 
-   if not assigned(aobj) then
 
-     begin
 
-       result := -1;
 
-       exit;
 
-     end;
 
-   mth := TlkJSONobjectmethod.Create;
 
-   mth.FName := aname;
 
-   mth.FValue := aobj;
 
-   result := self._Add(mth);
 
-   if FUseHash then
 
- {$IFDEF USE_HASH}
 
-     ht.AddPair(aname, result);
 
- {$ELSE}
 
-     ht.Insert(aname, result);
 
- {$ENDIF USE_HASH}
 
- end;
 
- procedure TlkJSONobject.Delete(idx: Integer);
 
- var
 
-   i,j,k:cardinal;
 
-   mth: TlkJSONobjectmethod;
 
- begin
 
-   if (idx >= 0) and (idx < Count) then
 
-     begin
 
- //      mth := FValue[idx] as TlkJSONobjectmethod;
 
-       mth := TlkJSONobjectmethod(fList.Items[idx]);
 
-       if FUseHash then
 
-         begin
 
-           ht.Delete(mth.FName);
 
-         end;
 
-     end;
 
-   _Delete(idx);
 
- {$ifdef USE_HASH}
 
-   if (idx<Count) and (FUseHash) then
 
-     begin
 
-       mth := TlkJSONobjectmethod(fList.Items[idx]);
 
-       ht.AddPair(mth.FName,idx);
 
-     end;
 
- {$endif}
 
- end;
 
- class function TlkJSONobject.Generate(AUseHash: Boolean = true):
 
-   TlkJSONobject;
 
- begin
 
-   result := TlkJSONobject.Create(AUseHash);
 
- end;
 
- function TlkJSONobject.OldGetField(nm: WideString): TlkJSONbase;
 
- var
 
-   mth: TlkJSONobjectmethod;
 
-   i: Integer;
 
- begin
 
-   i := IndexOfName(nm);
 
-   if i = -1 then
 
-     begin
 
-       result := nil;
 
-     end
 
-   else
 
-     begin
 
- //      mth := TlkJSONobjectmethod(FValue[i]);
 
-       mth := TlkJSONobjectmethod(fList.Items[i]);
 
-       result := mth.FValue;
 
-     end;
 
- end;
 
- function TlkJSONobject.IndexOfName(const aname: WideString): Integer;
 
- var
 
-   mth: TlkJSONobjectmethod;
 
-   i: Integer;
 
- begin
 
-   if not FUseHash then
 
-     begin
 
-       result := -1;
 
-       for i := 0 to Count - 1 do
 
-         begin
 
- //          mth := TlkJSONobjectmethod(FValue[i]);
 
-           mth := TlkJSONobjectmethod(fList.Items[i]);
 
-           if mth.Name = aname then
 
-             begin
 
-               result := i;
 
-               break;
 
-             end;
 
-         end;
 
-     end
 
-   else
 
-     begin
 
-       result := ht.IndexOf(aname);
 
-     end;
 
- end;
 
- function TlkJSONobject.IndexOfObject(aobj: TlkJSONbase): Integer;
 
- var
 
-   mth: TlkJSONobjectmethod;
 
-   i: Integer;
 
- begin
 
-   result := -1;
 
-   for i := 0 to Count - 1 do
 
-     begin
 
- //      mth := TlkJSONobjectmethod(FValue[i]);
 
-       mth := TlkJSONobjectmethod(fList.Items[i]);
 
-       if mth.FValue = aobj then
 
-         begin
 
-           result := i;
 
-           break;
 
-         end;
 
-     end;
 
- end;
 
- procedure TlkJSONobject.OldSetField(nm: WideString; const AValue:
 
-   TlkJSONbase);
 
- var
 
-   mth: TlkJSONobjectmethod;
 
-   i: Integer;
 
- begin
 
-   i := IndexOfName(nm);
 
-   if i <> -1 then
 
-     begin
 
- //      mth := TlkJSONobjectmethod(FValue[i]);
 
-       mth := TlkJSONobjectmethod(fList.Items[i]);
 
-       mth.FValue := AValue;
 
-     end;
 
- end;
 
- function TlkJSONobject.Add(const aname: WideString; nmb: double):
 
-   Integer;
 
- begin
 
-   Result := self.Add(aname, TlkJSONnumber.Generate(nmb));
 
- end;
 
- function TlkJSONobject.Add(const aname: WideString; aboolean: Boolean):
 
-   Integer;
 
- begin
 
-   Result := self.Add(aname, TlkJSONboolean.Generate(aboolean));
 
- end;
 
- function TlkJSONobject.Add(const aname: WideString; s: string):
 
-   Integer;
 
- begin
 
-   Result := self.Add(aname, TlkJSONstring.Generate(s));
 
- end;
 
- function TlkJSONobject.Add(const aname: WideString; inmb: Integer):
 
-   Integer;
 
- begin
 
-   Result := self.Add(aname, TlkJSONnumber.Generate(inmb));
 
- end;
 
- function TlkJSONobject.Add(const aname, ws: WideString): Integer;
 
- begin
 
-   Result := self.Add(aname, TlkJSONstring.Generate(ws));
 
- end;
 
- class function TlkJSONobject.SelfType: TlkJSONtypes;
 
- begin
 
-   Result := jsObject;
 
- end;
 
- class function TlkJSONobject.SelfTypeName: string;
 
- begin
 
-   Result := 'jsObject';
 
- end;
 
- function TlkJSONobject.GetFieldByIndex(idx: Integer): TlkJSONbase;
 
- var
 
-   nm: WideString;
 
- begin
 
-   nm := GetNameOf(idx);
 
-   if nm <> '' then
 
-     begin
 
-       result := Field[nm];
 
-     end
 
-   else
 
-     begin
 
-       result := nil;
 
-     end;
 
- end;
 
- function TlkJSONobject.GetNameOf(idx: Integer): WideString;
 
- var
 
-   mth: TlkJSONobjectmethod;
 
- begin
 
-   if (idx < 0) or (idx >= Count) then
 
-     begin
 
-       result := '';
 
-     end
 
-   else
 
-     begin
 
-       mth := Child[idx] as TlkJSONobjectmethod;
 
-       result := mth.Name;
 
-     end;
 
- end;
 
- procedure TlkJSONobject.SetFieldByIndex(idx: Integer;
 
-   const AValue: TlkJSONbase);
 
- var
 
-   nm: WideString;
 
- begin
 
-   nm := GetNameOf(idx);
 
-   if nm <> '' then
 
-     begin
 
-       Field[nm] := AValue;
 
-     end;
 
- end;
 
- function TlkJSONobject.ForEachElement(idx: Integer;
 
-   var nm: string): TlkJSONbase;
 
- begin
 
-   nm := GetNameOf(idx);
 
-   result := GetFieldByIndex(idx);
 
- end;
 
- function TlkJSONobject.GetField(AName: Variant):TlkJSONbase;
 
- begin
 
-   if VarIsStr(AName) then
 
-     result := OldGetField(VarToWideStr(AName))
 
-   else
 
-     result := inherited GetField(AName);
 
- end;
 
- {$IFDEF USE_HASH}
 
- function TlkJSONobject.GetHashTable: TlkHashTable;
 
- {$ELSE}
 
- function TlkJSONobject.GetHashTable: TlkBalTree;
 
- {$ENDIF USE_HASH}
 
- begin
 
-   result := ht;
 
- end;
 
- constructor TlkJSONobject.Create(bUseHash: Boolean);
 
- begin
 
-   inherited Create;
 
-   FUseHash := bUseHash;
 
- {$IFDEF USE_HASH}
 
-   ht := TlkHashTable.Create;
 
-   ht.FParent := self;
 
- {$ELSE}
 
-   ht := TlkBalTree.Create;
 
- {$ENDIF}
 
- end;
 
- destructor TlkJSONobject.Destroy;
 
- begin
 
-   if assigned(ht) then FreeAndNil(ht);
 
-   inherited;
 
- end;
 
- function TlkJSONobject.getDouble(idx: Integer): Double;
 
- var
 
-   jn: TlkJSONnumber;
 
- begin
 
-   jn := FieldByIndex[idx] as TlkJSONnumber;
 
-   if not assigned(jn) then result := 0
 
-   else result := jn.Value;
 
- end;
 
- function TlkJSONobject.getInt(idx: Integer): Integer;
 
- var
 
-   jn: TlkJSONnumber;
 
- begin
 
-   jn := FieldByIndex[idx] as TlkJSONnumber;
 
-   if not assigned(jn) then result := 0
 
-   else result := round(int(jn.Value));
 
- end;
 
- function TlkJSONobject.getString(idx: Integer): string;
 
- var
 
-   js: TlkJSONstring;
 
- begin
 
-   js := FieldByIndex[idx] as TlkJSONstring;
 
-   if not assigned(js) then result := ''
 
-   else result := vartostr(js.Value);
 
- end;
 
- function TlkJSONobject.getWideString(idx: Integer): WideString;
 
- var
 
-   js: TlkJSONstring;
 
- begin
 
-   js := FieldByIndex[idx] as TlkJSONstring;
 
-   if not assigned(js) then result := ''
 
-   else result := VarToWideStr(js.Value);
 
- end;
 
- {$ifdef TCB_EXT}
 
- function TlkJSONobject.getDoubleFromName(nm: string): Double;
 
- {$else}
 
- function TlkJSONobject.getDouble(nm: string): Double;
 
- {$endif}
 
- begin
 
-   result := getDouble(IndexOfName(nm));
 
- end;
 
- {$ifdef TCB_EXT}
 
- function TlkJSONobject.getIntFromName(nm: string): Integer;
 
- {$else}
 
- function TlkJSONobject.getInt(nm: string): Integer;
 
- {$endif}
 
- begin
 
-   result := getInt(IndexOfName(nm));
 
- end;
 
- {$ifdef TCB_EXT}
 
- function TlkJSONobject.getStringFromName(nm: string): string;
 
- {$else}
 
- function TlkJSONobject.getString(nm: string): string;
 
- {$endif}
 
- begin
 
-   result := getString(IndexOfName(nm));
 
- end;
 
- {$ifdef TCB_EXT}
 
- function TlkJSONobject.getWideStringFromName(nm: string): WideString;
 
- {$else}
 
- function TlkJSONobject.getWideString(nm: string): WideString;
 
- {$endif}
 
- begin
 
-   result := getWideString(IndexOfName(nm));
 
- end;
 
- function TlkJSONobject.getBoolean(idx: Integer): Boolean;
 
- var
 
-   jb: TlkJSONboolean;
 
- begin
 
-   jb := FieldByIndex[idx] as TlkJSONboolean;
 
-   if not assigned(jb) then result := false
 
-   else result := jb.Value;
 
- end;
 
- {$ifdef TCB_EXT}
 
- function TlkJSONobject.getBooleanFromName(nm: string): Boolean;
 
- {$else}
 
- function TlkJSONobject.getBoolean(nm: string): Boolean;
 
- {$endif}
 
- begin
 
-   result := getBoolean(IndexOfName(nm));
 
- end;
 
- { TlkJSON }
 
- class function TlkJSON.GenerateText(obj: TlkJSONbase): string;
 
- var
 
- {$IFDEF HAVE_FORMATSETTING}
 
-   fs: TFormatSettings;
 
- {$ENDIF}
 
-   pt1, pt0, pt2: PChar;
 
-   ptsz: cardinal;
 
- {$IFNDEF NEW_STYLE_GENERATE}
 
-   function gn_base(obj: TlkJSONbase): string;
 
-   var
 
-     ws: string;
 
-     i, j: Integer;
 
-     xs: TlkJSONstring;
 
-   begin
 
-     result := '';
 
-     if not assigned(obj) then exit;
 
-     if obj is TlkJSONnumber then
 
-       begin
 
- {$IFDEF HAVE_FORMATSETTING}
 
-         result := FloatToStr(TlkJSONnumber(obj).FValue, fs);
 
- {$ELSE}
 
-         result := FloatToStr(TlkJSONnumber(obj).FValue);
 
-         i := pos(DecimalSeparator, result);
 
-         if (DecimalSeparator <> '.') and (i > 0) then
 
-           result[i] := '.';
 
- {$ENDIF}
 
-       end
 
-     else if obj is TlkJSONstring then
 
-       begin
 
-         ws := UTF8Encode(TlkJSONstring(obj).FValue);
 
-         i := 1;
 
-         result := '"';
 
-         while i <= length(ws) do
 
-           begin
 
-             case ws[i] of
 
-               '/', '\', '"': result := result + '\' + ws[i];
 
-               #8: result := result + '\b';
 
-               #9: result := result + '\t';
 
-               #10: result := result + '\n';
 
-               #13: result := result + '\r';
 
-               #12: result := result + '\f';
 
-             else
 
-               if ord(ws[i]) < 32 then
 
-                 result := result + '\u' + inttohex(ord(ws[i]), 4)
 
-               else
 
-                 result := result + ws[i];
 
-             end;
 
-             inc(i);
 
-           end;
 
-         result := result + '"';
 
-       end
 
-     else if obj is TlkJSONboolean then
 
-       begin
 
-         if TlkJSONboolean(obj).FValue then
 
-           result := 'true'
 
-         else
 
-           result := 'false';
 
-       end
 
-     else if obj is TlkJSONnull then
 
-       begin
 
-         result := 'null';
 
-       end
 
-     else if obj is TlkJSONlist then
 
-       begin
 
-         result := '[';
 
-         j := TlkJSONobject(obj).Count - 1;
 
-         for i := 0 to j do
 
-           begin
 
-             if i > 0 then result := result + ',';
 
-             result := result + gn_base(TlkJSONlist(obj).Child[i]);
 
-           end;
 
-         result := result + ']';
 
-       end
 
-     else if obj is TlkJSONobjectmethod then
 
-       begin
 
-         try
 
-           xs := TlkJSONstring.Create;
 
-           xs.FValue := TlkJSONobjectmethod(obj).FName;
 
-           result := gn_base(TlkJSONbase(xs)) + ':';
 
-           result := result +
 
-             gn_base(TlkJSONbase(TlkJSONobjectmethod(obj).FValue));
 
-         finally
 
-           if assigned(xs) then FreeAndNil(xs);
 
-         end;
 
-       end
 
-     else if obj is TlkJSONobject then
 
-       begin
 
-         result := '{';
 
-         j := TlkJSONobject(obj).Count - 1;
 
-         for i := 0 to j do
 
-           begin
 
-             if i > 0 then result := result + ',';
 
-             result := result + gn_base(TlkJSONobject(obj).Child[i]);
 
-           end;
 
-         result := result + '}';
 
-       end;
 
-   end;
 
- {$ELSE}
 
-   procedure get_more_memory;
 
-   var
 
-     delta: cardinal;
 
-   begin
 
-     delta := 50000;
 
-     if pt0 = nil then
 
-       begin
 
-         pt0 := AllocMem(delta);
 
-         ptsz := 0;
 
-         pt1 := pt0;
 
-       end
 
-     else
 
-       begin
 
-         ReallocMem(pt0, ptsz + delta);
 
-         pt1 := pointer(cardinal(pt0) + ptsz);
 
-       end;
 
-     ptsz := ptsz + delta;
 
-     pt2 := pointer(cardinal(pt1) + delta);
 
-   end;
 
-   procedure mem_ch(ch: char);
 
-   begin
 
-     if pt1 >= pt2 then get_more_memory;
 
-     pt1^ := ch;
 
-     inc(pt1);
 
-   end;
 
-   procedure mem_write(rs: string);
 
-   var
 
-     i: Integer;
 
-   begin
 
-     for i := 1 to length(rs) do
 
-       begin
 
-         if pt1 >= pt2 then get_more_memory;
 
-         pt1^ := rs[i];
 
-         inc(pt1);
 
-       end;
 
-   end;
 
-   procedure gn_base(obj: TlkJSONbase);
 
-   var
 
-     ws: string;
 
-     i, j: Integer;
 
-     xs: TlkJSONstring;
 
-   begin
 
-     if not assigned(obj) then exit;
 
-     if obj is TlkJSONnumber then
 
-       begin
 
- {$IFDEF HAVE_FORMATSETTING}
 
-         mem_write(FloatToStr(TlkJSONnumber(obj).FValue, fs));
 
- {$ELSE}
 
-         ws := FloatToStr(TlkJSONnumber(obj).FValue);
 
-         i := pos(DecimalSeparator, ws);
 
-         if (DecimalSeparator <> '.') and (i > 0) then ws[i] := '.';
 
-         mem_write(ws);
 
- {$ENDIF}
 
-       end
 
-     else if obj is TlkJSONstring then
 
-       begin
 
-         ws := UTF8Encode(TlkJSONstring(obj).FValue);
 
-         i := 1;
 
-         mem_ch('"');
 
-         while i <= length(ws) do
 
-           begin
 
-             case ws[i] of
 
-               '/', '\', '"':
 
-                 begin
 
-                   mem_ch('\');
 
-                   mem_ch(ws[i]);
 
-                 end;
 
-               #8: mem_write('\b');
 
-               #9: mem_write('\t');
 
-               #10: mem_write('\n');
 
-               #13: mem_write('\r');
 
-               #12: mem_write('\f');
 
-             else
 
-               if ord(ws[i]) < 32 then
 
-                 mem_write('\u' + inttohex(ord(ws[i]), 4))
 
-               else
 
-                 mem_ch(ws[i]);
 
-             end;
 
-             inc(i);
 
-           end;
 
-         mem_ch('"');
 
-       end
 
-     else if obj is TlkJSONboolean then
 
-       begin
 
-         if TlkJSONboolean(obj).FValue then
 
-           mem_write('true')
 
-         else
 
-           mem_write('false');
 
-       end
 
-     else if obj is TlkJSONnull then
 
-       begin
 
-         mem_write('null');
 
-       end
 
-     else if obj is TlkJSONlist then
 
-       begin
 
-         mem_ch('[');
 
-         j := TlkJSONobject(obj).Count - 1;
 
-         for i := 0 to j do
 
-           begin
 
-             if i > 0 then mem_ch(',');
 
-             gn_base(TlkJSONlist(obj).Child[i]);
 
-           end;
 
-         mem_ch(']');
 
-       end
 
-     else if obj is TlkJSONobjectmethod then
 
-       begin
 
-         try
 
-           xs := TlkJSONstring.Create;
 
-           xs.FValue := TlkJSONobjectmethod(obj).FName;
 
-           gn_base(TlkJSONbase(xs));
 
-           mem_ch(':');
 
-           gn_base(TlkJSONbase(TlkJSONobjectmethod(obj).FValue));
 
-         finally
 
-           if assigned(xs) then FreeAndNil(xs);
 
-         end;
 
-       end
 
-     else if obj is TlkJSONobject then
 
-       begin
 
-         mem_ch('{');
 
-         j := TlkJSONobject(obj).Count - 1;
 
-         for i := 0 to j do
 
-           begin
 
-             if i > 0 then mem_ch(',');
 
-             gn_base(TlkJSONobject(obj).Child[i]);
 
-           end;
 
-         mem_ch('}');
 
-       end;
 
-   end;
 
- {$ENDIF NEW_STYLE_GENERATE}
 
- begin
 
- {$IFDEF HAVE_FORMATSETTING}
 
-   GetLocaleFormatSettings(GetThreadLocale, fs);
 
-   fs.DecimalSeparator := '.';
 
- {$ENDIF}
 
- {$IFDEF NEW_STYLE_GENERATE}
 
-   pt0 := nil;
 
-   get_more_memory;
 
-   gn_base(obj);
 
-   mem_ch(#0);
 
-   result := string(pt0);
 
-   freemem(pt0);
 
- {$ELSE}
 
-   result := gn_base(obj);
 
- {$ENDIF}
 
- end;
 
- class function TlkJSON.ParseText(const txt: string): TlkJSONbase;
 
- {$IFDEF HAVE_FORMATSETTING}
 
- var
 
-   fs: TFormatSettings;
 
- {$ENDIF}
 
-   function js_base(idx: Integer; var ridx: Integer; var o:
 
-     TlkJSONbase): Boolean; forward;
 
-   function xe(idx: Integer): Boolean;
 
-   {$IFDEF FPC}inline;
 
-   {$ENDIF}
 
-   begin
 
-     result := idx <= length(txt);
 
-   end;
 
-   procedure skip_spc(var idx: Integer);
 
-   {$IFDEF FPC}inline;
 
-   {$ENDIF}
 
-   begin
 
-     while (xe(idx)) and (ord(txt[idx]) < 33) do
 
-       inc(idx);
 
-   end;
 
-   procedure add_child(var o, c: TlkJSONbase);
 
-   var
 
-     i: Integer;
 
-   begin
 
-     if o = nil then
 
-       begin
 
-         o := c;
 
-       end
 
-     else
 
-       begin
 
-         if o is TlkJSONobjectmethod then
 
-           begin
 
-             TlkJSONobjectmethod(o).FValue := c;
 
-           end
 
-         else if o is TlkJSONlist then
 
-           begin
 
-             TlkJSONlist(o)._Add(c);
 
-           end
 
-         else if o is TlkJSONobject then
 
-           begin
 
-             i := TlkJSONobject(o)._Add(c);
 
-             if TlkJSONobject(o).UseHash then
 
- {$IFDEF USE_HASH}
 
-               TlkJSONobject(o).ht.AddPair(TlkJSONobjectmethod(c).Name, i);
 
- {$ELSE}
 
-               TlkJSONobject(o).ht.Insert(TlkJSONobjectmethod(c).Name, i);
 
- {$ENDIF USE_HASH}
 
-           end;
 
-       end;
 
-   end;
 
-   function js_boolean(idx: Integer; var ridx: Integer; var o:
 
-     TlkJSONbase): Boolean;
 
-   var
 
-     js: TlkJSONboolean;
 
-   begin
 
-     skip_spc(idx);
 
-     if copy(txt, idx, 4) = 'true' then
 
-       begin
 
-         result := true;
 
-         ridx := idx + 4;
 
-         js := TlkJSONboolean.Create;
 
-         js.FValue := true;
 
-         add_child(o, TlkJSONbase(js));
 
-       end
 
-     else if copy(txt, idx, 5) = 'false' then
 
-       begin
 
-         result := true;
 
-         ridx := idx + 5;
 
-         js := TlkJSONboolean.Create;
 
-         js.FValue := false;
 
-         add_child(o, TlkJSONbase(js));
 
-       end
 
-     else
 
-       begin
 
-         result := false;
 
-       end;
 
-   end;
 
-   function js_null(idx: Integer; var ridx: Integer; var o:
 
-     TlkJSONbase): Boolean;
 
-   var
 
-     js: TlkJSONnull;
 
-   begin
 
-     skip_spc(idx);
 
-     if copy(txt, idx, 4) = 'null' then
 
-       begin
 
-         result := true;
 
-         ridx := idx + 4;
 
-         js := TlkJSONnull.Create;
 
-         add_child(o, TlkJSONbase(js));
 
-       end
 
-     else
 
-       begin
 
-         result := false;
 
-       end;
 
-   end;
 
-   function js_integer(idx: Integer; var ridx: Integer): Boolean;
 
-   begin
 
-     result := false;
 
-     while (xe(idx)) and (txt[idx] in ['0'..'9']) do
 
-       begin
 
-         result := true;
 
-         inc(idx);
 
-       end;
 
-     if result then ridx := idx;
 
-   end;
 
-   function js_number(idx: Integer; var ridx: Integer; var o:
 
-     TlkJSONbase): Boolean;
 
-   var
 
-     js: TlkJSONnumber;
 
-     ws: string;
 
-   {$IFNDEF HAVE_FORMATSETTING}
 
-     i: Integer;
 
-   {$ENDIF}
 
-   begin
 
-     skip_spc(idx);
 
-     result := xe(idx);
 
-     if not result then exit;
 
-     if txt[idx] in ['+', '-'] then
 
-       begin
 
-         inc(idx);
 
-         result := xe(idx);
 
-       end;
 
-     if not result then exit;
 
-     result := js_integer(idx, idx);
 
-     if not result then exit;
 
-     if (xe(idx)) and (txt[idx] = '.') then
 
-       begin
 
-         inc(idx);
 
-         result := js_integer(idx, idx);
 
-         if not result then exit;
 
-       end;
 
-     if (xe(idx)) and (txt[idx] in ['e', 'E']) then
 
-       begin
 
-         inc(idx);
 
-         if (xe(idx)) and (txt[idx] in ['+', '-']) then inc(idx);
 
-         result := js_integer(idx, idx);
 
-         if not result then exit;
 
-       end;
 
-     if not result then exit;
 
-     js := TlkJSONnumber.Create;
 
-     ws := copy(txt, ridx, idx - ridx);
 
- {$IFDEF HAVE_FORMATSETTING}
 
-     js.FValue := StrToFloat(ws, fs);
 
- {$ELSE}
 
-     i := pos('.', ws);
 
-     if (DecimalSeparator <> '.') and (i > 0) then
 
-       ws[pos('.', ws)] := DecimalSeparator;
 
-     js.FValue := StrToFloat(ws);
 
- {$ENDIF}
 
-     add_child(o, TlkJSONbase(js));
 
-     ridx := idx;
 
-   end;
 
- {
 
- }
 
-   function js_string(idx: Integer; var ridx: Integer; var o:
 
-     TlkJSONbase): Boolean;
 
-     function strSpecialChars(const s: string): string;
 
-     var
 
-       i, j : integer;
 
-     begin
 
-       i := Pos('\', s);
 
-       if (i = 0) then
 
-         Result := s
 
-       else
 
-       begin
 
-         Result := Copy(s, 1, i-1);
 
-         j := i;
 
-         repeat
 
-           if (s[j] = '\') then
 
-           begin
 
-             inc(j);
 
-             case s[j] of
 
-               '\': Result := Result + '\';
 
-               '"': Result := Result + '"';
 
-               '''': Result := Result + '''';
 
-               '/': Result := Result + '/';
 
-               'b': Result := Result + #8;
 
-               'f': Result := Result + #12;
 
-               'n': Result := Result + #10;
 
-               'r': Result := Result + #13;
 
-               't': Result := Result + #9;
 
-               'u':
 
-                 begin
 
-                   Result := Result + code2utf(strtoint('$' + copy(s, j + 1, 4)));
 
-                   inc(j, 4);
 
-                 end;
 
-             end;
 
-           end
 
-           else
 
-             Result := Result + s[j];
 
-           inc(j);
 
-         until j > length(s);
 
-       end;
 
-     end;
 
-   var
 
-     js: TlkJSONstring;
 
-     fin: Boolean;
 
-     ws: String;
 
-     i,j,widx: Integer;
 
-   begin
 
-     skip_spc(idx);
 
-     result := xe(idx) and (txt[idx] = '"');
 
-     if not result then exit;
 
-     inc(idx);
 
-     widx := idx;
 
-     fin:=false;
 
-     REPEAT
 
-       i := 0;
 
-       j := 0;
 
-       while (widx<=length(txt)) and (j=0) do
 
-         begin
 
-           if (i=0) and (txt[widx]='\') then i:=widx;
 
-           if (j=0) and (txt[widx]='"') then j:=widx;
 
-           inc(widx);
 
-         end;
 
- // incorrect string!!!
 
-       if j=0 then
 
-         begin
 
-           result := false;
 
-           exit;
 
-         end;
 
- // if we have no slashed chars in string
 
-       if (i=0) or (j<i) then
 
-         begin
 
-           ws := copy(txt,idx,j-idx);
 
-           idx := j;
 
-           fin := true;
 
-         end
 
- // if i>0 and j>=i - skip slashed char
 
-       else
 
-         begin
 
-           widx:=i+2;
 
-         end;
 
-     UNTIL fin;
 
-     ws := strSpecialChars(ws);
 
-     inc(idx);
 
-     js := TlkJSONstring.Create;
 
- {$ifdef USE_D2009}
 
-     js.FValue := UTF8ToString(ws);
 
- {$else}
 
-     js.FValue := UTF8Decode(ws);
 
- {$endif}
 
-     add_child(o, TlkJSONbase(js));
 
-     ridx := idx;
 
-   end;
 
-   function js_list(idx: Integer; var ridx: Integer; var o:
 
-     TlkJSONbase): Boolean;
 
-   var
 
-     js: TlkJSONlist;
 
-   begin
 
-     result := false;
 
-     try
 
-       js := TlkJSONlist.Create;
 
-       skip_spc(idx);
 
-       result := xe(idx);
 
-       if not result then exit;
 
-       result := txt[idx] = '[';
 
-       if not result then exit;
 
-       inc(idx);
 
-       while js_base(idx, idx, TlkJSONbase(js)) do
 
-         begin
 
-           skip_spc(idx);
 
-           if (xe(idx)) and (txt[idx] = ',') then inc(idx);
 
-         end;
 
-       skip_spc(idx);
 
-       result := (xe(idx)) and (txt[idx] = ']');
 
-       if not result then exit;
 
-       inc(idx);
 
-     finally
 
-       if not result then
 
-         begin
 
-           js.Free;
 
-         end
 
-       else
 
-         begin
 
-           add_child(o, TlkJSONbase(js));
 
-           ridx := idx;
 
-         end;
 
-     end;
 
-   end;
 
-   function js_method(idx: Integer; var ridx: Integer; var o:
 
-     TlkJSONbase): Boolean;
 
-   var
 
-     mth: TlkJSONobjectmethod;
 
-     ws: TlkJSONstring;
 
-   begin
 
-     result := false;
 
-     try
 
-       ws := nil;
 
-       mth := TlkJSONobjectmethod.Create;
 
-       skip_spc(idx);
 
-       result := xe(idx);
 
-       if not result then exit;
 
-       result := js_string(idx, idx, TlkJSONbase(ws));
 
-       if not result then exit;
 
-       skip_spc(idx);
 
-       result := xe(idx) and (txt[idx] = ':');
 
-       if not result then exit;
 
-       inc(idx);
 
-       mth.FName := ws.FValue;
 
-       result := js_base(idx, idx, TlkJSONbase(mth));
 
-     finally
 
-       if ws <> nil then ws.Free;
 
-       if result then
 
-         begin
 
-           add_child(o, TlkJSONbase(mth));
 
-           ridx := idx;
 
-         end
 
-       else
 
-         begin
 
-           mth.Free;
 
-         end;
 
-     end;
 
-   end;
 
-   function js_object(idx: Integer; var ridx: Integer; var o:
 
-     TlkJSONbase): Boolean;
 
-   var
 
-     js: TlkJSONobject;
 
-   begin
 
-     result := false;
 
-     try
 
-       js := TlkJSONobject.Create;
 
-       skip_spc(idx);
 
-       result := xe(idx);
 
-       if not result then exit;
 
-       result := txt[idx] = '{';
 
-       if not result then exit;
 
-       inc(idx);
 
-       while js_method(idx, idx, TlkJSONbase(js)) do
 
-         begin
 
-           skip_spc(idx);
 
-           if (xe(idx)) and (txt[idx] = ',') then inc(idx);
 
-         end;
 
-       skip_spc(idx);  
 
-       result := (xe(idx)) and (txt[idx] = '}');
 
-       if not result then exit;
 
-       inc(idx);
 
-     finally
 
-       if not result then
 
-         begin
 
-           js.Free;
 
-         end
 
-       else
 
-         begin
 
-           add_child(o, TlkJSONbase(js));
 
-           ridx := idx;
 
-         end;
 
-     end;
 
-   end;
 
-   function js_base(idx: Integer; var ridx: Integer; var o:
 
-     TlkJSONbase): Boolean;
 
-   begin
 
-     skip_spc(idx);
 
-     result := js_boolean(idx, idx, o);
 
-     if not result then result := js_null(idx, idx, o);
 
-     if not result then result := js_number(idx, idx, o);
 
-     if not result then result := js_string(idx, idx, o);
 
-     if not result then result := js_list(idx, idx, o);
 
-     if not result then result := js_object(idx, idx, o);
 
-     if result then ridx := idx;
 
-   end;
 
- var
 
-   idx: Integer;
 
- begin
 
- {$IFDEF HAVE_FORMATSETTING}
 
-   GetLocaleFormatSettings(GetThreadLocale, fs);
 
-   fs.DecimalSeparator := '.';
 
- {$ENDIF}
 
-   result := nil;
 
-   if txt = '' then exit;
 
-   try
 
-     idx := 1;
 
-     // skip a BOM utf8 marker
 
-     if copy(txt,idx,3)=#239#187#191 then
 
-       begin
 
-         inc(idx,3);
 
-     // if there are only a BOM - exit;
 
-         if idx>length(txt) then exit;
 
-       end;
 
-     if not js_base(idx, idx, result) then FreeAndNil(result);
 
-   except
 
-     if assigned(result) then FreeAndNil(result);
 
-   end;
 
- end;
 
- { ElkIntException }
 
- constructor ElkIntException.Create(idx: Integer; msg: string);
 
- begin
 
-   self.idx := idx;
 
-   inherited Create(msg);
 
- end;
 
- { TlkHashTable }
 
- {$IFDEF USE_HASH}
 
- procedure TlkHashTable.AddPair(const ws: WideString; idx: Integer);
 
- var
 
-   i, j, k: cardinal;
 
-   p: PlkHashItem;
 
-   find: boolean;
 
- begin
 
-   find := false;
 
-   if InTable(ws, i, j, k) then
 
-     begin
 
- // if string is already in table, changing index
 
-       if TlkJSONobject(FParent).GetNameOf(PlkHashItem(a_x[j].Items[k])^.index) = ws then
 
-         begin
 
-            PlkHashItem(a_x[j].Items[k])^.index := idx;
 
-            find := true;
 
-         end;
 
-     end;
 
-   if find = false then
 
-     begin
 
-       GetMem(p,sizeof(TlkHashItem));
 
-       k := a_x[j].Add(p);
 
-       p^.hash := i;
 
-       p^.index := idx;
 
-       while (k>0) and (PlkHashItem(a_x[j].Items[k])^.hash < PlkHashItem(a_x[j].Items[k-1])^.hash) do
 
-         begin
 
-           a_x[j].Exchange(k,k-1);
 
-           dec(k);
 
-         end;
 
-     end;
 
- end;
 
- function TlkHashTable.counters: string;
 
- var
 
-   i, j: Integer;
 
-   ws: string;
 
- begin
 
-   ws := '';
 
-   for i := 0 to 15 do
 
-     begin
 
-       for j := 0 to 15 do
 
- //        ws := ws + format('%.3d ', [length(a_h[i * 16 + j])]);
 
-         ws := ws + format('%.3d ', [a_x[i * 16 + j].Count]);
 
-       ws := ws + #13#10;
 
-     end;
 
-   result := ws;
 
- end;
 
- procedure TlkHashTable.Delete(const ws: WideString);
 
- var
 
-   i, j, k: cardinal;
 
- begin
 
-   if InTable(ws, i, j, k) then
 
-     begin
 
- //      while k < high(a_h[j]) do
 
- //        begin
 
- //          hswap(j, k, k + 1);
 
- //          inc(k);
 
- //        end;
 
- //      SetLength(a_h[j], k);
 
-       FreeMem(a_x[j].Items[k]);
 
-       a_x[j].Delete(k);
 
-     end;
 
- end;
 
- {$IFDEF THREADSAFE}
 
- const
 
-   rnd_table: array[0..255] of byte =
 
-   (216, 191, 234, 201, 12, 163, 190, 205, 128, 199, 210, 17, 52, 43,
 
-     38, 149, 40, 207, 186, 89, 92, 179, 142, 93, 208, 215, 162,
 
-     161, 132, 59, 246, 37, 120, 223, 138, 233, 172, 195, 94, 237, 32,
 
-     231, 114, 49, 212, 75, 198, 181, 200, 239, 90, 121, 252, 211,
 
-     46, 125, 112, 247, 66, 193, 36, 91, 150, 69, 24, 255, 42, 9, 76,
 
-     227, 254, 13, 192, 7, 18, 81, 116, 107, 102, 213, 104, 15, 250,
 
-     153, 156, 243, 206, 157, 16, 23, 226, 225, 196, 123, 54, 101,
 
-     184, 31, 202, 41, 236, 3, 158, 45, 96, 39, 178, 113, 20, 139, 6,
 
-     245, 8, 47, 154, 185, 60, 19, 110, 189, 176, 55, 130, 1, 100,
 
-     155, 214, 133, 88, 63, 106, 73, 140, 35, 62, 77, 0, 71, 82, 145,
 
-     180,
 
-     171, 166, 21, 168, 79, 58, 217, 220, 51, 14, 221, 80, 87, 34, 33,
 
-     4, 187, 118, 165, 248, 95, 10, 105, 44, 67, 222, 109, 160, 103,
 
-     242, 177, 84, 203, 70, 53, 72, 111, 218, 249, 124, 83, 174, 253,
 
-     240, 119, 194, 65, 164, 219, 22, 197, 152, 127, 170, 137, 204,
 
-     99, 126, 141, 64, 135, 146, 209, 244, 235, 230, 85, 232, 143,
 
-     122, 25, 28, 115, 78, 29, 144, 151, 98, 97, 68, 251, 182, 229,
 
-     56,
 
-     159, 74, 169, 108, 131, 30, 173, 224, 167, 50, 241, 148, 11, 134,
 
-     117, 136, 175, 26, 57, 188, 147, 238, 61, 48, 183, 2, 129,
 
-     228, 27, 86, 5);
 
- {$ELSE}
 
- var
 
-   rnd_table: array[0..255] of byte;
 
- {$ENDIF}
 
- function TlkHashTable.DefaultHashOf(const ws: WideString): cardinal;
 
- {$IFDEF DOTNET}
 
- var
 
-   i, j: Integer;
 
-   x1, x2, x3, x4: byte;
 
- begin
 
-   result := 0;
 
- //  result := 0;
 
-   x1 := 0;
 
-   x2 := 1;
 
-   for i := 1 to length(ws) do
 
-     begin
 
-       j := ord(ws[i]);
 
- // first version of hashing
 
-       x1 := (x1 + j) {and $FF};
 
-       x2 := (x2 + 1 + (j shr 8)) {and $FF};
 
-       x3 := rnd_table[x1];
 
-       x4 := rnd_table[x3];
 
-       result := ((x1 * x4) + (x2 * x3)) xor result;
 
-     end;
 
- end;
 
- {$ELSE}
 
- var
 
-   x1, x2, x3, x4: byte;
 
-   p: PWideChar;
 
- begin
 
-   result := 0;
 
-   x1 := 0;
 
-   x2 := 1;
 
-   p := PWideChar(ws);
 
-   while p^ <> #0 do
 
-     begin
 
-       inc(x1, ord(p^)) {and $FF};
 
-       inc(x2, 1 + (ord(p^) shr 8)) {and $FF};
 
-       x3 := rnd_table[x1];
 
-       x4 := rnd_table[x3];
 
-       result := ((x1 * x4) + (x2 * x3)) xor result;
 
-       inc(p);
 
-     end;
 
- end;
 
- {$ENDIF}
 
- procedure TlkHashTable.hswap(j, k, l: Integer);
 
- //var
 
- //  h: TlkHashItem;
 
- begin
 
- //  h := a_h[j, k];
 
- //  a_h[j, k] := a_h[j, l];
 
- //  a_h[j, l] := h;
 
-   a_x[j].Exchange(k, l);
 
- end;
 
- function TlkHashTable.IndexOf(const ws: WideString): Integer;
 
- var
 
-   i, j, k: Cardinal;
 
- begin
 
-   if not InTable(ws, i, j, k) then
 
-     begin
 
-       result := -1;
 
-     end
 
-   else
 
-     begin
 
- //      result := a_h[j, k].index;
 
-       result := PlkHashItem(a_x[j].Items[k])^.index;
 
-     end;
 
- end;
 
- function TlkHashTable.InTable(const ws: WideString; var i, j, k:
 
-   cardinal):
 
-   Boolean;
 
- var
 
-   l, wu, wl: Integer;
 
-   x: Cardinal;
 
-   fin: Boolean;
 
- begin
 
-   i := HashOf(ws);
 
-   j := i and $FF;
 
-   result := false;
 
- {using "binary" search always, because array is sorted}
 
-   if a_x[j].Count-1 >= 0 then
 
-     begin
 
-       wl := 0;
 
-       wu := a_x[j].Count-1;
 
-       repeat
 
-         fin := true;
 
-         if PlkHashItem(a_x[j].Items[wl])^.hash = i then
 
-           begin
 
-             k := wl;
 
-             result := true;
 
-           end
 
-         else if PlkHashItem(a_x[j].Items[wu])^.hash = i then
 
-           begin
 
-             k := wu;
 
-             result := true;
 
-           end
 
-         else if (wu - wl) > 1 then
 
-           begin
 
-             fin := false;
 
-             x := (wl + wu) shr 1;
 
-             if PlkHashItem(a_x[j].Items[x])^.hash > i then
 
-               begin
 
-                 wu := x;
 
-               end
 
-             else
 
-               begin
 
-                 wl := x;
 
-               end;
 
-           end;
 
-       until fin;
 
-     end;
 
- // verify k index in chain
 
-   if result = true then
 
-     begin
 
-       while (k > 0) and (PlkHashItem(a_x[j].Items[k])^.hash = PlkHashItem(a_x[j].Items[k-1])^.hash) do dec(k);
 
-       repeat
 
-         fin := true;
 
-         if TlkJSONobject(FParent).GetNameOf(PlkHashItem(a_x[j].Items[k])^.index) <> ws then
 
-           begin
 
-             if k < a_x[j].Count-1 then
 
-               begin
 
-                 inc(k);
 
-                 fin := false;
 
-               end
 
-             else
 
-               begin
 
-                 result := false;
 
-               end;
 
-           end
 
-         else
 
-           begin
 
-             result := true;
 
-           end;
 
-       until fin;
 
-     end;
 
- end;
 
- {$IFNDEF THREADSAFE}
 
- procedure init_rnd;
 
- var
 
-   x0: Integer;
 
-   i: Integer;
 
- begin
 
-   x0 := 5;
 
-   for i := 0 to 255 do
 
-     begin
 
-       x0 := (x0 * 29 + 71) and $FF;
 
-       rnd_table[i] := x0;
 
-     end;
 
- end;
 
- {$ENDIF}
 
- procedure TlkHashTable.SetHashFunction(const AValue:
 
-   TlkHashFunction);
 
- begin
 
-   FHashFunction := AValue;
 
- end;
 
- constructor TlkHashTable.Create;
 
- var
 
-   i: Integer;
 
- begin
 
-   inherited;
 
- //  for i := 0 to 255 do SetLength(a_h[i], 0);
 
-   for i := 0 to 255 do a_x[i] := TList.Create;
 
-   HashOf := {$IFDEF FPC}@{$ENDIF}DefaultHashOf;
 
- end;
 
- destructor TlkHashTable.Destroy;
 
- var
 
-   i, j: Integer;
 
- begin
 
- //  for i := 0 to 255 do SetLength(a_h[i], 0);
 
-   for i := 0 to 255 do
 
-     begin
 
-       for j := 0 to a_x[i].Count - 1 do Freemem(a_x[i].Items[j]);
 
-       a_x[i].Free;
 
-     end;
 
-   inherited;
 
- end;
 
- function TlkHashTable.SimpleHashOf(const ws: WideString): cardinal;
 
- var
 
-   i: Integer;
 
- begin
 
-   result := length(ws);
 
-   for i := 1 to length(ws) do result := result + ord(ws[i]);
 
- end;
 
- {$ENDIF USE_HASH}
 
- { TlkJSONstreamed }
 
- {$IFNDEF KOL}
 
- class function TlkJSONstreamed.LoadFromFile(srcname: string):
 
-   TlkJSONbase;
 
- var
 
-   fs: TFileStream;
 
- begin
 
-   result := nil;
 
-   if not FileExists(srcname) then exit;
 
-   try
 
-     fs := TFileStream.Create(srcname, fmOpenRead);
 
-     result := LoadFromStream(fs);
 
-   finally
 
-     if Assigned(fs) then FreeAndNil(fs);
 
-   end;
 
- end;
 
- class function TlkJSONstreamed.LoadFromStream(src: TStream):
 
-   TlkJSONbase;
 
- var
 
-   ws: string;
 
-   len: int64;
 
- begin
 
-   result := nil;
 
-   if not assigned(src) then exit;
 
-   len := src.Size - src.Position;
 
-   SetLength(ws, len);
 
-   src.Read(pchar(ws)^, len);
 
-   result := ParseText(ws);
 
- end;
 
- class procedure TlkJSONstreamed.SaveToFile(obj: TlkJSONbase;
 
-   dstname: string);
 
- var
 
-   fs: TFileStream;
 
- begin
 
-   if not assigned(obj) then exit;
 
-   try
 
-     fs := TFileStream.Create(dstname, fmCreate);
 
-     SaveToStream(obj, fs);
 
-   finally
 
-     if Assigned(fs) then FreeAndNil(fs);
 
-   end;
 
- end;
 
- class procedure TlkJSONstreamed.SaveToStream(obj: TlkJSONbase;
 
-   dst: TStream);
 
- var
 
-   ws: string;
 
- begin
 
-   if not assigned(obj) then exit;
 
-   if not assigned(dst) then exit;
 
-   ws := GenerateText(obj);
 
-   dst.Write(pchar(ws)^, length(ws));
 
- end;
 
- {$ENDIF}
 
- { TlkJSONdotnetclass }
 
- {$IFDEF DOTNET}
 
- procedure TlkJSONdotnetclass.AfterConstruction;
 
- begin
 
- end;
 
- procedure TlkJSONdotnetclass.BeforeDestruction;
 
- begin
 
- end;
 
- constructor TlkJSONdotnetclass.Create;
 
- begin
 
-   inherited;
 
-   AfterConstruction;
 
- end;
 
- destructor TlkJSONdotnetclass.Destroy;
 
- begin
 
-   BeforeDestruction;
 
-   inherited;
 
- end;
 
- {$ENDIF DOTNET}
 
- { TlkBalTree }
 
- {$IFNDEF USE_HASH}
 
- procedure TlkBalTree.Clear;
 
-   procedure rec(t: PlkBalNode);
 
-   begin
 
-     if t.left<>fbottom then rec(t.left);
 
-     if t.right<>fbottom then rec(t.right);
 
-     t.nm := '';
 
-     dispose(t);
 
-   end;
 
- begin
 
-   if froot<>fbottom then rec(froot);
 
-   froot := fbottom;
 
-   fdeleted := fbottom;
 
- end;
 
- function TlkBalTree.counters: string;
 
- begin
 
-   result := format('Balanced tree root node level is %d',[froot.level]);
 
- end;
 
- constructor TlkBalTree.Create;
 
- begin
 
-   inherited Create;
 
-   new(fbottom);
 
-   fbottom.left := fbottom;
 
-   fbottom.right := fbottom;
 
-   fbottom.level := 0;
 
-   fdeleted := fbottom;
 
-   froot := fbottom;
 
- end;
 
- function TlkBalTree.Delete(const ws: WideString): Boolean;
 
-   procedure UpdateKeys(t: PlkBalNode; idx: integer);
 
-   begin
 
-     if t <> fbottom then begin
 
-       if t.key > idx then
 
-         t.key := t.key - 1;
 
-       UpdateKeys(t.left, idx);
 
-       UpdateKeys(t.right, idx);
 
-     end;
 
-   end;
 
-   function del(var t: PlkBalNode): Boolean;
 
-   begin
 
-     result := false;
 
-     if t<>fbottom then begin
 
-       flast := t;
 
-       if ws<t.nm then
 
-         result := del(t.left)
 
-       else begin
 
-         fdeleted := t;
 
-         result := del(t.right);
 
-       end;
 
-       if (t = flast) and (fdeleted <> fbottom) and (ws = fdeleted.nm) then begin
 
-         UpdateKeys(froot, fdeleted.key);
 
-         fdeleted.key := t.key;
 
-         fdeleted.nm := t.nm;
 
-         t := t.right;
 
-         flast.nm := '';
 
-         dispose(flast);
 
-         result := true;
 
-       end
 
-       else if (t.left.level < (t.level - 1)) or (t.right.level < (t.level - 1)) then begin
 
-         t.level := t.level - 1;
 
-         if t.right.level > t.level then
 
-           t.right.level := t.level;
 
-         skew(t);
 
-         skew(t.right);
 
-         skew(t.right.right);
 
-         split(t);
 
-         split(t.right);
 
-       end;
 
-     end;
 
-   end;
 
- {
 
- // mine version, buggy, see tracker message
 
- // [ 2229135 ] Value deletion is broken by "Nobody/Anonymous - nobody"
 
-   function del(var t: PlkBalNode): Boolean;
 
-   begin
 
-     result := false;
 
-     if t<>fbottom then
 
-       begin
 
-         flast := t;
 
-         if ws<t.nm then
 
-           result := del(t.left)
 
-         else
 
-           begin
 
-             fdeleted := t;
 
-             result := del(t.right);
 
-           end;
 
-         if (t = flast) and (fdeleted<>fbottom) and (ws = t.nm) then
 
-           begin
 
-             fdeleted.key := t.key;
 
-             fdeleted.nm := t.nm;
 
-             t := t.right;
 
-             flast.nm := '';
 
-             dispose(flast);
 
-             result := true;
 
-           end
 
-         else if (t.left.level<(t.level-1)) or (t.right.level<(t.level-1)) then
 
-           begin
 
-             t.level := t.level-1;
 
-             if t.right.level>t.level then t.right.level := t.level;
 
-             skew(t);
 
-             skew(t.right);
 
-             skew(t.right.right);
 
-             split(t);
 
-             split(t.right);
 
-           end;
 
-       end;
 
-   end;
 
- }
 
- begin
 
-   result := del(froot);
 
- end;
 
- destructor TlkBalTree.Destroy;
 
- begin
 
-   Clear;
 
-   dispose(fbottom);
 
-   inherited;
 
- end;
 
- function TlkBalTree.IndexOf(const ws: WideString): Integer;
 
- var
 
-   tk: PlkBalNode;
 
- begin
 
-   result := -1;
 
-   tk := froot;
 
-   while (result=-1) and (tk<>fbottom) do
 
-     begin
 
-       if tk.nm = ws then result := tk.key
 
-       else if ws<tk.nm then tk := tk.left
 
-       else tk := tk.right;
 
-     end;
 
- end;
 
- function TlkBalTree.Insert(const ws: WideString; x: Integer): Boolean;
 
-   function ins(var t: PlkBalNode): Boolean;
 
-   begin
 
-     if t = fbottom then
 
-       begin
 
-         new(t);
 
-         t.key := x;
 
-         t.nm := ws;
 
-         t.left := fbottom;
 
-         t.right := fbottom;
 
-         t.level := 1;
 
-         result := true;
 
-       end
 
-     else
 
-       begin
 
-         if ws < t.nm then
 
-           result := ins(t.left)
 
-         else if ws > t.nm then
 
-           result := ins(t.right)
 
-         else result := false;
 
-         skew(t);
 
-         split(t);
 
-       end;
 
-   end;
 
- begin
 
-   result := ins(froot);
 
- end;
 
- procedure TlkBalTree.skew(var t: PlkBalNode);
 
- var
 
-   temp: PlkBalNode;
 
- begin
 
-   if t.left.level = t.level then
 
-     begin
 
-       temp := t;
 
-       t := t.left;
 
-       temp.left := t.right;
 
-       t.right := temp;
 
-     end;
 
- end;
 
- procedure TlkBalTree.split(var t: PlkBalNode);
 
- var
 
-   temp: PlkBalNode;
 
- begin
 
-   if t.right.right.level = t.level then
 
-     begin
 
-       temp := t;
 
-       t := t.right;
 
-       temp.right := t.left;
 
-       t.left := temp;
 
-       t.level := t.level+1;
 
-     end;
 
- end;
 
- {$ENDIF USE_HASH}
 
- initialization
 
- {$IFNDEF THREADSAFE}
 
- {$IFDEF USE_HASH}
 
-   init_rnd;
 
- {$ENDIF USE_HASH}
 
- {$ENDIF THREADSAFE}
 
- end.
 
 
  |