uLkJSON.pas 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626
  1. {
  2. LkJSON v1.07
  3. 06 november 2009
  4. * Copyright (c) 2006,2007,2008,2009 Leonid Koninin
  5. * leon_kon@users.sourceforge.net
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions are met:
  10. * * Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * * Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. * * Neither the name of the <organization> nor the
  16. * names of its contributors may be used to endorse or promote products
  17. * derived from this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY Leonid Koninin ``AS IS'' AND ANY
  20. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL Leonid Koninin BE LIABLE FOR ANY
  23. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  24. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  25. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  26. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  27. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  28. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. changes:
  30. v1.07 06/11/2009 * fixed a bug in js_string - thanks to Andrew G. Khodotov
  31. * fixed error with double-slashes - thanks to anonymous user
  32. * fixed a BOM bug in parser, thanks to jasper_dale
  33. v1.06 13/03/2009 * fixed a bug in string parsing routine
  34. * looked routine from the Adrian M. Jones, and get some
  35. ideas from it; thanks a lot, Adrian!
  36. * checked error reported by phpop and fix it in the string
  37. routine; also, thanks for advice.
  38. v1.05 26/01/2009 + added port to D2009 by Daniele Teti, thanx a lot! really,
  39. i haven't the 2009 version, so i can't play with it. I was
  40. add USE_D2009 directive below, disabled by default
  41. * fixed two small bugs in parsing object: errors with empty
  42. object and list; thanx to RSDN's delphi forum members
  43. * fixed "[2229135] Value deletion is broken" tracker
  44. issue, thanx to anonymous sender provided code for
  45. tree version
  46. * fixed js_string according to "[1917047] (much) faster
  47. js_string Parse" tracker issue by Joao Inacio; a lot of
  48. thanx, great speedup!
  49. v1.04 05/04/2008 + a declaration of Field property moved from TlkJSONobject
  50. to TlkJSONbase; thanx for idea to Andrey Lukyanov; this
  51. improve objects use, look the bottom of SAMPLE2.DPR
  52. * fixed field name in TlkJSONobject to WideString
  53. v1.03 14/03/2008 + added a code for generating readable JSON text, sended to
  54. me by Kusnassriyanto Saiful Bahri, thanx to him!
  55. * from this version, library distributed with BSD
  56. license, more pleasure for commercial programmers :)
  57. * was rewritten internal storing of objects, repacing
  58. hash tables with balanced trees (AA tree, by classic
  59. author's variant). On mine machine, with enabled fastmm,
  60. tree variant is about 30% slower in from-zero creation,
  61. but about 50% faster in parsing; also deletion of
  62. objects will be much faster than a hash-one.
  63. Hashes (old-style) can be switched on by enabling
  64. USE_HASH directive below
  65. v1.02 14/09/2007 * fix mistypes in diffrent places; thanx for reports
  66. to Aleksandr Fedorov and Tobias Wrede
  67. v1.01 18/05/2007 * fix small bug in new text generation routine, check
  68. library for leaks by fastmm4; thanx for idea and comments
  69. for Glynn Owen
  70. v1.00 12/05/2007 * some fixes in new code (mistypes, mistypes...)
  71. * also many fixes by ideas of Henri Gourvest - big thanx
  72. for him again; he send me code for thread-safe initializing
  73. of hash table, some FPC-compatible issues (not tested by
  74. myself) and better code for localization in latest
  75. delphi versions; very, very big thanx!
  76. * rewritten procedure of json text generating, with wich
  77. work of it speeds up 4-5 times (on test) its good for
  78. a large objects
  79. * started a large work for making source code self-doc
  80. (not autodoc!)
  81. v0.99 10/05/2007 + add functions to list and object:
  82. function getInt(idx: Integer): Integer;
  83. function getString(idx: Integer): String;
  84. function getWideString(idx: Integer):WideString;
  85. function getDouble(idx: Integer): Double;
  86. function getBoolean(idx: Integer): Boolean;
  87. + add overloaded functions to object:
  88. function getDouble(nm: String): Double; overload;
  89. function getInt(nm: String): Integer; overload;
  90. function getString(nm: String): String; overload;
  91. function getWideString(nm: String): WideString; overload;
  92. function getBoolean(nm: String): Boolean; overload;
  93. * changed storing mech of TlkJSONcustomlist descendants from
  94. dynamic array to TList; this gives us great speedup with
  95. lesser changes; thanx for idea to Henri Gourvest
  96. * also reworked hashtable to work with TList, so it also
  97. increase speed of work
  98. v0.98 09/05/2007 * fix small bug in work with WideStrings(UTF8), thanx to
  99. IVO GELOV to description and sources
  100. v0.97 10/04/2007 + add capabilities to work with KOL delphi projects; for
  101. this will define KOL variable in begin of text; of course,
  102. in this case object TlkJSONstreamed is not compiled.
  103. v0.96 03/30/2007 + add TlkJSONFuncEnum and method ForEach in all
  104. TlkJSONcustomlist descendants
  105. + add property UseHash(r/o) to TlkJSONobject, and parameter
  106. UseHash:Boolean to object constructors; set it to false
  107. allow to disable using of hash-table, what can increase
  108. speed of work in case of objects with low number of
  109. methods(fields); [by default it is true]
  110. + added conditional compile directive DOTNET for use in .Net
  111. based delphi versions; remove dot in declaration below
  112. (thanx for idea and sample code to Tim Radford)
  113. + added property HashOf to TlkHashTable to allow use of
  114. users hash functions; on enter is widestring, on exit is
  115. cardinal (32 bit unsigned). Original HashOf renamed to
  116. DefaultHashOf
  117. * hash table object of TlkJSONobject wrapped by property called
  118. HashTable
  119. * fixed some minor bugs
  120. v0.95 03/29/2007 + add object TlkJSONstreamed what descendant of TlkJSON and
  121. able to load/save JSON objects from/to streams/files.
  122. * fixed small bug in generating of unicode strings representation
  123. v0.94 03/27/2007 + add properties NameOf and FieldByIndex to TlkJSONobject
  124. * fix small error in parsing unicode chars
  125. * small changes in hashing code (try to speed up)
  126. v0.93 03/05/2007 + add overloaded functions to list and object
  127. + add enum type TlkJSONtypes
  128. + add functions: SelfType:TlkJSONtypes and
  129. SelfTypeName: String to every TlkJSONbase child
  130. * fix mistype 'IndefOfName' to 'IndexOfName'
  131. * fix mistype 'IndefOfObject' to 'IndexOfObject'
  132. v0.92 03/02/2007 + add some fix to TlkJSON.ParseText to fix bug with parsing
  133. objects - object methods not always added properly
  134. to hash array (thanx to Chris Matheson)
  135. ...
  136. }
  137. unit uLkJSON;
  138. {$IFDEF fpc}
  139. {$MODE objfpc}
  140. {$H+}
  141. {.$DEFINE HAVE_FORMATSETTING}
  142. {$ELSE}
  143. {$IF RTLVersion > 14.00}
  144. {$DEFINE HAVE_FORMATSETTING}
  145. {$IF RTLVersion > 19.00}
  146. {$DEFINE USE_D2009}
  147. {$IFEND}
  148. {$IFEND}
  149. {$ENDIF}
  150. interface
  151. {.$DEFINE USE_D2009}
  152. {.$DEFINE KOL}
  153. {.$define DOTNET}
  154. {$DEFINE THREADSAFE}
  155. {$DEFINE NEW_STYLE_GENERATE}
  156. {.$DEFINE USE_HASH}
  157. {.$DEFINE TCB_EXT}
  158. uses windows,
  159. SysUtils,
  160. {$IFNDEF KOL}
  161. classes,
  162. {$ELSE}
  163. kol,
  164. {$ENDIF}
  165. variants;
  166. type
  167. TlkJSONtypes = (jsBase, jsNumber, jsString, jsBoolean, jsNull,
  168. jsList, jsObject);
  169. {$IFDEF DOTNET}
  170. TlkJSONdotnetclass = class
  171. public
  172. constructor Create;
  173. destructor Destroy; override;
  174. procedure AfterConstruction; virtual;
  175. procedure BeforeDestruction; virtual;
  176. end;
  177. {$ENDIF DOTNET}
  178. TlkJSONbase = class{$IFDEF DOTNET}(TlkJSONdotnetclass){$ENDIF}
  179. protected
  180. function GetValue: variant; virtual;
  181. procedure SetValue(const AValue: variant); virtual;
  182. function GetChild(idx: Integer): TlkJSONbase; virtual;
  183. procedure SetChild(idx: Integer; const AValue: TlkJSONbase);
  184. virtual;
  185. function GetCount: Integer; virtual;
  186. function GetField(AName: Variant):TlkJSONbase; virtual;
  187. public
  188. property Field[AName: Variant]: TlkJSONbase read GetField;
  189. property Count: Integer read GetCount;
  190. property Child[idx: Integer]: TlkJSONbase read GetChild write SetChild;
  191. property Value: variant read GetValue write SetValue;
  192. class function SelfType: TlkJSONtypes; virtual;
  193. class function SelfTypeName: string; virtual;
  194. end;
  195. TlkJSONnumber = class(TlkJSONbase)
  196. protected
  197. FValue: extended;
  198. function GetValue: Variant; override;
  199. procedure SetValue(const AValue: Variant); override;
  200. public
  201. procedure AfterConstruction; override;
  202. class function Generate(AValue: extended = 0): TlkJSONnumber;
  203. class function SelfType: TlkJSONtypes; override;
  204. class function SelfTypeName: string; override;
  205. end;
  206. TlkJSONstring = class(TlkJSONbase)
  207. protected
  208. FValue: WideString;
  209. function GetValue: Variant; override;
  210. procedure SetValue(const AValue: Variant); override;
  211. public
  212. procedure AfterConstruction; override;
  213. class function Generate(const wsValue: WideString = ''):
  214. TlkJSONstring;
  215. class function SelfType: TlkJSONtypes; override;
  216. class function SelfTypeName: string; override;
  217. end;
  218. TlkJSONboolean = class(TlkJSONbase)
  219. protected
  220. FValue: Boolean;
  221. function GetValue: Variant; override;
  222. procedure SetValue(const AValue: Variant); override;
  223. public
  224. procedure AfterConstruction; override;
  225. class function Generate(AValue: Boolean = true): TlkJSONboolean;
  226. class function SelfType: TlkJSONtypes; override;
  227. class function SelfTypeName: string; override;
  228. end;
  229. TlkJSONnull = class(TlkJSONbase)
  230. protected
  231. function GetValue: Variant; override;
  232. function Generate: TlkJSONnull;
  233. public
  234. class function SelfType: TlkJSONtypes; override;
  235. class function SelfTypeName: string; override;
  236. end;
  237. TlkJSONFuncEnum = procedure(ElName: string; Elem: TlkJSONbase;
  238. data: pointer; var Continue: Boolean) of object;
  239. TlkJSONcustomlist = class(TlkJSONbase)
  240. protected
  241. // FValue: array of TlkJSONbase;
  242. fList: TList;
  243. function GetCount: Integer; override;
  244. function GetChild(idx: Integer): TlkJSONbase; override;
  245. procedure SetChild(idx: Integer; const AValue: TlkJSONbase);
  246. override;
  247. function ForEachElement(idx: Integer; var nm: string):
  248. TlkJSONbase; virtual;
  249. function GetField(AName: Variant):TlkJSONbase; override;
  250. function _Add(obj: TlkJSONbase): Integer; virtual;
  251. procedure _Delete(iIndex: Integer); virtual;
  252. function _IndexOf(obj: TlkJSONbase): Integer; virtual;
  253. public
  254. procedure ForEach(fnCallBack: TlkJSONFuncEnum; pUserData:
  255. pointer);
  256. procedure AfterConstruction; override;
  257. procedure BeforeDestruction; override;
  258. function getInt(idx: Integer): Integer; virtual;
  259. function getString(idx: Integer): string; virtual;
  260. function getWideString(idx: Integer): WideString; virtual;
  261. function getDouble(idx: Integer): Double; virtual;
  262. function getBoolean(idx: Integer): Boolean; virtual;
  263. end;
  264. TlkJSONlist = class(TlkJSONcustomlist)
  265. protected
  266. public
  267. function Add(obj: TlkJSONbase): Integer; overload;
  268. function Add(aboolean: Boolean): Integer; overload;
  269. function Add(nmb: double): Integer; overload;
  270. function Add(s: string): Integer; overload;
  271. function Add(const ws: WideString): Integer; overload;
  272. function Add(inmb: Integer): Integer; overload;
  273. procedure Delete(idx: Integer);
  274. function IndexOf(obj: TlkJSONbase): Integer;
  275. class function Generate: TlkJSONlist;
  276. class function SelfType: TlkJSONtypes; override;
  277. class function SelfTypeName: string; override;
  278. end;
  279. TlkJSONobjectmethod = class(TlkJSONbase)
  280. protected
  281. FValue: TlkJSONbase;
  282. FName: WideString;
  283. procedure SetName(const AValue: WideString);
  284. public
  285. property ObjValue: TlkJSONbase read FValue;
  286. procedure AfterConstruction; override;
  287. procedure BeforeDestruction; override;
  288. property Name: WideString read FName write SetName;
  289. class function Generate(const aname: WideString; aobj: TlkJSONbase):
  290. TlkJSONobjectmethod;
  291. end;
  292. {$IFDEF USE_HASH}
  293. PlkHashItem = ^TlkHashItem;
  294. TlkHashItem = packed record
  295. hash: cardinal;
  296. index: Integer;
  297. end;
  298. TlkHashFunction = function(const ws: WideString): cardinal of
  299. object;
  300. TlkHashTable = class
  301. private
  302. FParent: TObject; // TCB:parent for check chaining op.
  303. FHashFunction: TlkHashFunction;
  304. procedure SetHashFunction(const AValue: TlkHashFunction);
  305. protected
  306. a_x: array[0..255] of TList;
  307. procedure hswap(j, k, l: Integer);
  308. function InTable(const ws: WideString; var i, j, k: cardinal):
  309. Boolean;
  310. public
  311. function counters: string;
  312. function DefaultHashOf(const ws: WideString): cardinal;
  313. function SimpleHashOf(const ws: WideString): cardinal;
  314. property HashOf: TlkHashFunction read FHashFunction write
  315. SetHashFunction;
  316. function IndexOf(const ws: WideString): Integer;
  317. procedure AddPair(const ws: WideString; idx: Integer);
  318. procedure Delete(const ws: WideString);
  319. constructor Create;
  320. destructor Destroy; override;
  321. end;
  322. {$ELSE}
  323. // implementation based on "Arne Andersson, Balanced Search Trees Made Simpler"
  324. PlkBalNode = ^TlkBalNode;
  325. TlkBalNode = packed record
  326. left,right: PlkBalNode;
  327. level: byte;
  328. key: Integer;
  329. nm: WideString;
  330. end;
  331. TlkBalTree = class
  332. protected
  333. fdeleted,flast,fbottom,froot: PlkBalNode;
  334. procedure skew(var t:PlkBalNode);
  335. procedure split(var t:PlkBalNode);
  336. public
  337. function counters: string;
  338. procedure Clear;
  339. function Insert(const ws: WideString; x: Integer): Boolean;
  340. function Delete(const ws: WideString): Boolean;
  341. function IndexOf(const ws: WideString): Integer;
  342. constructor Create;
  343. destructor Destroy; override;
  344. end;
  345. {$ENDIF USE_HASH}
  346. TlkJSONobject = class(TlkJSONcustomlist)
  347. protected
  348. {$IFDEF USE_HASH}
  349. ht: TlkHashTable;
  350. {$ELSE}
  351. ht: TlkBalTree;
  352. {$ENDIF USE_HASH}
  353. FUseHash: Boolean;
  354. function GetFieldByIndex(idx: Integer): TlkJSONbase;
  355. function GetNameOf(idx: Integer): WideString;
  356. procedure SetFieldByIndex(idx: Integer; const AValue: TlkJSONbase);
  357. {$IFDEF USE_HASH}
  358. function GetHashTable: TlkHashTable;
  359. {$ELSE}
  360. function GetHashTable: TlkBalTree;
  361. {$ENDIF USE_HASH}
  362. function ForEachElement(idx: Integer; var nm: string): TlkJSONbase;
  363. override;
  364. function GetField(AName: Variant):TlkJSONbase; override;
  365. public
  366. property UseHash: Boolean read FUseHash;
  367. {$IFDEF USE_HASH}
  368. property HashTable: TlkHashTable read GetHashTable;
  369. {$ELSE}
  370. property HashTable: TlkBalTree read GetHashTable;
  371. {$ENDIF USE_HASH}
  372. function Add(const aname: WideString; aobj: TlkJSONbase): Integer;
  373. overload;
  374. function OldGetField(nm: WideString): TlkJSONbase;
  375. procedure OldSetField(nm: WideString; const AValue: TlkJSONbase);
  376. function Add(const aname: WideString; aboolean: Boolean): Integer; overload;
  377. function Add(const aname: WideString; nmb: double): Integer; overload;
  378. function Add(const aname: WideString; s: string): Integer; overload;
  379. function Add(const aname: WideString; const ws: WideString): Integer;
  380. overload;
  381. function Add(const aname: WideString; inmb: Integer): Integer; overload;
  382. procedure Delete(idx: Integer);
  383. function IndexOfName(const aname: WideString): Integer;
  384. function IndexOfObject(aobj: TlkJSONbase): Integer;
  385. property Field[nm: WideString]: TlkJSONbase read OldGetField
  386. write OldSetField; default;
  387. constructor Create(bUseHash: Boolean = true);
  388. destructor Destroy; override;
  389. class function Generate(AUseHash: Boolean = true): TlkJSONobject;
  390. class function SelfType: TlkJSONtypes; override;
  391. class function SelfTypeName: string; override;
  392. property FieldByIndex[idx: Integer]: TlkJSONbase read GetFieldByIndex
  393. write SetFieldByIndex;
  394. property NameOf[idx: Integer]: WideString read GetNameOf;
  395. function getDouble(idx: Integer): Double; overload; override;
  396. function getInt(idx: Integer): Integer; overload; override;
  397. function getString(idx: Integer): string; overload; override;
  398. function getWideString(idx: Integer): WideString; overload; override;
  399. function getBoolean(idx: Integer): Boolean; overload; override;
  400. function {$ifdef TCB_EXT}getDoubleFromName{$else}getDouble{$endif}
  401. (nm: string): Double; overload;
  402. function {$ifdef TCB_EXT}getIntFromName{$else}getInt{$endif}
  403. (nm: string): Integer; overload;
  404. function {$ifdef TCB_EXT}getStringFromName{$else}getString{$endif}
  405. (nm: string): string; overload;
  406. function {$ifdef TCB_EXT}getWideStringFromName{$else}getWideString{$endif}
  407. (nm: string): WideString; overload;
  408. function {$ifdef TCB_EXT}getBooleanFromName{$else}getBoolean{$endif}
  409. (nm: string): Boolean; overload;
  410. end;
  411. TlkJSON = class
  412. public
  413. class function ParseText(const txt: string): TlkJSONbase;
  414. class function GenerateText(obj: TlkJSONbase): string;
  415. end;
  416. {$IFNDEF KOL}
  417. TlkJSONstreamed = class(TlkJSON)
  418. class function LoadFromStream(src: TStream): TlkJSONbase;
  419. class procedure SaveToStream(obj: TlkJSONbase; dst: TStream);
  420. class function LoadFromFile(srcname: string): TlkJSONbase;
  421. class procedure SaveToFile(obj: TlkJSONbase; dstname: string);
  422. end;
  423. {$ENDIF}
  424. function GenerateReadableText(vObj: TlkJSONbase; var vLevel:
  425. Integer): string;
  426. implementation
  427. uses math,strutils;
  428. type
  429. ElkIntException = class(Exception)
  430. public
  431. idx: Integer;
  432. constructor Create(idx: Integer; msg: string);
  433. end;
  434. // author of next two functions is Kusnassriyanto Saiful Bahri
  435. function Indent(vTab: Integer): string;
  436. begin
  437. result := DupeString(' ', vTab);
  438. end;
  439. function GenerateReadableText(vObj: TlkJSONbase; var vLevel:
  440. Integer): string;
  441. var
  442. i: Integer;
  443. vStr: string;
  444. xs: TlkJSONstring;
  445. begin
  446. vLevel := vLevel + 1;
  447. if vObj is TlkJSONObject then
  448. begin
  449. vStr := '';
  450. for i := 0 to TlkJSONobject(vObj).Count - 1 do
  451. begin
  452. if vStr <> '' then
  453. begin
  454. vStr := vStr + ','#13#10;
  455. end;
  456. vStr := vStr + Indent(vLevel) +
  457. GenerateReadableText(TlkJSONobject(vObj).Child[i], vLevel);
  458. end;
  459. if vStr <> '' then
  460. begin
  461. vStr := '{'#13#10 + vStr + #13#10 + Indent(vLevel - 1) + '}';
  462. end
  463. else
  464. begin
  465. vStr := '{}';
  466. end;
  467. result := vStr;
  468. end
  469. else if vObj is TlkJSONList then
  470. begin
  471. vStr := '';
  472. for i := 0 to TlkJSONList(vObj).Count - 1 do
  473. begin
  474. if vStr <> '' then
  475. begin
  476. vStr := vStr + ','#13#10;
  477. end;
  478. vStr := vStr + Indent(vLevel) +
  479. GenerateReadableText(TlkJSONList(vObj).Child[i], vLevel);
  480. end;
  481. if vStr <> '' then
  482. begin
  483. vStr := '['#13#10 + vStr + #13#10 + Indent(vLevel - 1) + ']';
  484. end
  485. else
  486. begin
  487. vStr := '[]';
  488. end;
  489. result := vStr;
  490. end
  491. else if vObj is TlkJSONobjectmethod then
  492. begin
  493. vStr := '';
  494. xs := TlkJSONstring.Create;
  495. try
  496. xs.Value := TlkJSONobjectMethod(vObj).Name;
  497. vStr := GenerateReadableText(xs, vLevel);
  498. vLevel := vLevel - 1;
  499. vStr := vStr + ':' + GenerateReadableText(TlkJSONbase(
  500. TlkJSONobjectmethod(vObj).ObjValue), vLevel);
  501. //vStr := vStr + ':' + GenerateReadableText(TlkJSONbase(vObj), vLevel);
  502. vLevel := vLevel + 1;
  503. result := vStr;
  504. finally
  505. xs.Free;
  506. end;
  507. end
  508. else
  509. begin
  510. if vObj is TlkJSONobjectmethod then
  511. begin
  512. if TlkJSONobjectMethod(vObj).Name <> '' then
  513. begin
  514. end;
  515. end;
  516. result := TlkJSON.GenerateText(vObj);
  517. end;
  518. vLevel := vLevel - 1;
  519. end;
  520. // author of this routine is IVO GELOV
  521. function code2utf(iNumber: Integer): UTF8String;
  522. begin
  523. if iNumber < 128 then Result := chr(iNumber)
  524. else if iNumber < 2048 then
  525. Result := chr((iNumber shr 6) + 192) + chr((iNumber and 63) + 128)
  526. else if iNumber < 65536 then
  527. Result := chr((iNumber shr 12) + 224) + chr(((iNumber shr 6) and
  528. 63) + 128) + chr((iNumber and 63) + 128)
  529. else if iNumber < 2097152 then
  530. Result := chr((iNumber shr 18) + 240) + chr(((iNumber shr 12) and
  531. 63) + 128) + chr(((iNumber shr 6) and 63) + 128) +
  532. chr((iNumber and 63) + 128);
  533. end;
  534. { TlkJSONbase }
  535. function TlkJSONbase.GetChild(idx: Integer): TlkJSONbase;
  536. begin
  537. result := nil;
  538. end;
  539. function TlkJSONbase.GetCount: Integer;
  540. begin
  541. result := 0;
  542. end;
  543. function TlkJSONbase.GetField(AName: Variant):TlkJSONbase;
  544. begin
  545. result := self;
  546. end;
  547. function TlkJSONbase.GetValue: variant;
  548. begin
  549. result := variants.Null;
  550. end;
  551. class function TlkJSONbase.SelfType: TlkJSONtypes;
  552. begin
  553. result := jsBase;
  554. end;
  555. class function TlkJSONbase.SelfTypeName: string;
  556. begin
  557. result := 'jsBase';
  558. end;
  559. procedure TlkJSONbase.SetChild(idx: Integer; const AValue:
  560. TlkJSONbase);
  561. begin
  562. end;
  563. procedure TlkJSONbase.SetValue(const AValue: variant);
  564. begin
  565. end;
  566. { TlkJSONnumber }
  567. procedure TlkJSONnumber.AfterConstruction;
  568. begin
  569. inherited;
  570. FValue := 0;
  571. end;
  572. class function TlkJSONnumber.Generate(AValue: extended):
  573. TlkJSONnumber;
  574. begin
  575. result := TlkJSONnumber.Create;
  576. result.FValue := AValue;
  577. end;
  578. function TlkJSONnumber.GetValue: Variant;
  579. begin
  580. result := FValue;
  581. end;
  582. class function TlkJSONnumber.SelfType: TlkJSONtypes;
  583. begin
  584. result := jsNumber;
  585. end;
  586. class function TlkJSONnumber.SelfTypeName: string;
  587. begin
  588. result := 'jsNumber';
  589. end;
  590. procedure TlkJSONnumber.SetValue(const AValue: Variant);
  591. begin
  592. FValue := VarAsType(AValue, varDouble);
  593. end;
  594. { TlkJSONstring }
  595. procedure TlkJSONstring.AfterConstruction;
  596. begin
  597. inherited;
  598. FValue := '';
  599. end;
  600. class function TlkJSONstring.Generate(const wsValue: WideString):
  601. TlkJSONstring;
  602. begin
  603. result := TlkJSONstring.Create;
  604. result.FValue := wsValue;
  605. end;
  606. function TlkJSONstring.GetValue: Variant;
  607. begin
  608. result := FValue;
  609. end;
  610. class function TlkJSONstring.SelfType: TlkJSONtypes;
  611. begin
  612. result := jsString;
  613. end;
  614. class function TlkJSONstring.SelfTypeName: string;
  615. begin
  616. result := 'jsString';
  617. end;
  618. procedure TlkJSONstring.SetValue(const AValue: Variant);
  619. begin
  620. FValue := VarToWideStr(AValue);
  621. end;
  622. { TlkJSONboolean }
  623. procedure TlkJSONboolean.AfterConstruction;
  624. begin
  625. FValue := false;
  626. end;
  627. class function TlkJSONboolean.Generate(AValue: Boolean):
  628. TlkJSONboolean;
  629. begin
  630. result := TlkJSONboolean.Create;
  631. result.Value := AValue;
  632. end;
  633. function TlkJSONboolean.GetValue: Variant;
  634. begin
  635. result := FValue;
  636. end;
  637. class function TlkJSONboolean.SelfType: TlkJSONtypes;
  638. begin
  639. Result := jsBoolean;
  640. end;
  641. class function TlkJSONboolean.SelfTypeName: string;
  642. begin
  643. Result := 'jsBoolean';
  644. end;
  645. procedure TlkJSONboolean.SetValue(const AValue: Variant);
  646. begin
  647. FValue := boolean(AValue);
  648. end;
  649. { TlkJSONnull }
  650. function TlkJSONnull.Generate: TlkJSONnull;
  651. begin
  652. result := TlkJSONnull.Create;
  653. end;
  654. function TlkJSONnull.GetValue: Variant;
  655. begin
  656. result := variants.Null;
  657. end;
  658. class function TlkJSONnull.SelfType: TlkJSONtypes;
  659. begin
  660. result := jsNull;
  661. end;
  662. class function TlkJSONnull.SelfTypeName: string;
  663. begin
  664. result := 'jsNull';
  665. end;
  666. { TlkJSONcustomlist }
  667. function TlkJSONcustomlist._Add(obj: TlkJSONbase): Integer;
  668. begin
  669. if not Assigned(obj) then
  670. begin
  671. result := -1;
  672. exit;
  673. end;
  674. result := fList.Add(obj);
  675. end;
  676. procedure TlkJSONcustomlist.AfterConstruction;
  677. begin
  678. inherited;
  679. fList := TList.Create;
  680. end;
  681. procedure TlkJSONcustomlist.BeforeDestruction;
  682. var
  683. i: Integer;
  684. begin
  685. for i := (Count - 1) downto 0 do _Delete(i);
  686. fList.Free;
  687. inherited;
  688. end;
  689. // renamed
  690. procedure TlkJSONcustomlist._Delete(iIndex: Integer);
  691. var
  692. idx: Integer;
  693. begin
  694. if not ((iIndex < 0) or (iIndex >= Count)) then
  695. begin
  696. if fList.Items[iIndex] <> nil then
  697. TlkJSONbase(fList.Items[iIndex]).Free;
  698. idx := pred(fList.Count);
  699. if iIndex<idx then
  700. begin
  701. fList.Items[iIndex] := fList.Items[idx];
  702. fList.Delete(idx);
  703. end
  704. else
  705. begin
  706. fList.Delete(iIndex);
  707. end;
  708. end;
  709. end;
  710. function TlkJSONcustomlist.GetChild(idx: Integer): TlkJSONbase;
  711. begin
  712. if (idx < 0) or (idx >= Count) then
  713. begin
  714. result := nil;
  715. end
  716. else
  717. begin
  718. result := fList.Items[idx];
  719. end;
  720. end;
  721. function TlkJSONcustomlist.GetCount: Integer;
  722. begin
  723. result := fList.Count;
  724. end;
  725. function TlkJSONcustomlist._IndexOf(obj: TlkJSONbase): Integer;
  726. begin
  727. result := fList.IndexOf(obj);
  728. end;
  729. procedure TlkJSONcustomlist.SetChild(idx: Integer; const AValue:
  730. TlkJSONbase);
  731. begin
  732. if not ((idx < 0) or (idx >= Count)) then
  733. begin
  734. if fList.Items[idx] <> nil then
  735. TlkJSONbase(fList.Items[idx]).Free;
  736. fList.Items[idx] := AValue;
  737. end;
  738. end;
  739. procedure TlkJSONcustomlist.ForEach(fnCallBack: TlkJSONFuncEnum;
  740. pUserData:
  741. pointer);
  742. var
  743. iCount: Integer;
  744. IsContinue: Boolean;
  745. anJSON: TlkJSONbase;
  746. wsObject: string;
  747. begin
  748. if not assigned(fnCallBack) then exit;
  749. IsContinue := true;
  750. for iCount := 0 to GetCount - 1 do
  751. begin
  752. anJSON := ForEachElement(iCount, wsObject);
  753. if assigned(anJSON) then
  754. fnCallBack(wsObject, anJSON, pUserData, IsContinue);
  755. if not IsContinue then break;
  756. end;
  757. end;
  758. ///---- renamed to here
  759. function TlkJSONcustomlist.GetField(AName: Variant):TlkJSONbase;
  760. var
  761. index: Integer;
  762. begin
  763. if VarIsNumeric(AName) then
  764. begin
  765. index := integer(AName);
  766. result := GetChild(index);
  767. end
  768. else
  769. begin
  770. result := inherited GetField(AName);
  771. end;
  772. end;
  773. function TlkJSONcustomlist.ForEachElement(idx: Integer; var nm:
  774. string): TlkJSONbase;
  775. begin
  776. nm := inttostr(idx);
  777. result := GetChild(idx);
  778. end;
  779. function TlkJSONcustomlist.getDouble(idx: Integer): Double;
  780. var
  781. jn: TlkJSONnumber;
  782. begin
  783. jn := Child[idx] as TlkJSONnumber;
  784. if not assigned(jn) then result := 0
  785. else result := jn.Value;
  786. end;
  787. function TlkJSONcustomlist.getInt(idx: Integer): Integer;
  788. var
  789. jn: TlkJSONnumber;
  790. begin
  791. jn := Child[idx] as TlkJSONnumber;
  792. if not assigned(jn) then result := 0
  793. else result := round(int(jn.Value));
  794. end;
  795. function TlkJSONcustomlist.getString(idx: Integer): string;
  796. var
  797. js: TlkJSONstring;
  798. begin
  799. js := Child[idx] as TlkJSONstring;
  800. if not assigned(js) then result := ''
  801. else result := VarToStr(js.Value);
  802. end;
  803. function TlkJSONcustomlist.getWideString(idx: Integer): WideString;
  804. var
  805. js: TlkJSONstring;
  806. begin
  807. js := Child[idx] as TlkJSONstring;
  808. if not assigned(js) then result := ''
  809. else result := VarToWideStr(js.Value);
  810. end;
  811. function TlkJSONcustomlist.getBoolean(idx: Integer): Boolean;
  812. var
  813. jb: TlkJSONboolean;
  814. begin
  815. jb := Child[idx] as TlkJSONboolean;
  816. if not assigned(jb) then result := false
  817. else result := jb.Value;
  818. end;
  819. { TlkJSONobjectmethod }
  820. procedure TlkJSONobjectmethod.AfterConstruction;
  821. begin
  822. inherited;
  823. FValue := nil;
  824. FName := '';
  825. end;
  826. procedure TlkJSONobjectmethod.BeforeDestruction;
  827. begin
  828. FName := '';
  829. if FValue <> nil then
  830. begin
  831. FValue.Free;
  832. FValue := nil;
  833. end;
  834. inherited;
  835. end;
  836. class function TlkJSONobjectmethod.Generate(const aname: WideString;
  837. aobj: TlkJSONbase): TlkJSONobjectmethod;
  838. begin
  839. result := TlkJSONobjectmethod.Create;
  840. result.FName := aname;
  841. result.FValue := aobj;
  842. end;
  843. procedure TlkJSONobjectmethod.SetName(const AValue: WideString);
  844. begin
  845. FName := AValue;
  846. end;
  847. { TlkJSONlist }
  848. function TlkJSONlist.Add(obj: TlkJSONbase): Integer;
  849. begin
  850. result := _Add(obj);
  851. end;
  852. function TlkJSONlist.Add(nmb: double): Integer;
  853. begin
  854. Result := self.Add(TlkJSONnumber.Generate(nmb));
  855. end;
  856. function TlkJSONlist.Add(aboolean: Boolean): Integer;
  857. begin
  858. Result := self.Add(TlkJSONboolean.Generate(aboolean));
  859. end;
  860. function TlkJSONlist.Add(inmb: Integer): Integer;
  861. begin
  862. Result := self.Add(TlkJSONnumber.Generate(inmb));
  863. end;
  864. function TlkJSONlist.Add(const ws: WideString): Integer;
  865. begin
  866. Result := self.Add(TlkJSONstring.Generate(ws));
  867. end;
  868. function TlkJSONlist.Add(s: string): Integer;
  869. begin
  870. Result := self.Add(TlkJSONstring.Generate(s));
  871. end;
  872. procedure TlkJSONlist.Delete(idx: Integer);
  873. begin
  874. _Delete(idx);
  875. end;
  876. class function TlkJSONlist.Generate: TlkJSONlist;
  877. begin
  878. result := TlkJSONlist.Create;
  879. end;
  880. function TlkJSONlist.IndexOf(obj: TlkJSONbase): Integer;
  881. begin
  882. result := _IndexOf(obj);
  883. end;
  884. class function TlkJSONlist.SelfType: TlkJSONtypes;
  885. begin
  886. result := jsList;
  887. end;
  888. class function TlkJSONlist.SelfTypeName: string;
  889. begin
  890. result := 'jsList';
  891. end;
  892. { TlkJSONobject }
  893. function TlkJSONobject.Add(const aname: WideString; aobj:
  894. TlkJSONbase):
  895. Integer;
  896. var
  897. mth: TlkJSONobjectmethod;
  898. begin
  899. if not assigned(aobj) then
  900. begin
  901. result := -1;
  902. exit;
  903. end;
  904. mth := TlkJSONobjectmethod.Create;
  905. mth.FName := aname;
  906. mth.FValue := aobj;
  907. result := self._Add(mth);
  908. if FUseHash then
  909. {$IFDEF USE_HASH}
  910. ht.AddPair(aname, result);
  911. {$ELSE}
  912. ht.Insert(aname, result);
  913. {$ENDIF USE_HASH}
  914. end;
  915. procedure TlkJSONobject.Delete(idx: Integer);
  916. var
  917. i,j,k:cardinal;
  918. mth: TlkJSONobjectmethod;
  919. begin
  920. if (idx >= 0) and (idx < Count) then
  921. begin
  922. // mth := FValue[idx] as TlkJSONobjectmethod;
  923. mth := TlkJSONobjectmethod(fList.Items[idx]);
  924. if FUseHash then
  925. begin
  926. ht.Delete(mth.FName);
  927. end;
  928. end;
  929. _Delete(idx);
  930. {$ifdef USE_HASH}
  931. if (idx<Count) and (FUseHash) then
  932. begin
  933. mth := TlkJSONobjectmethod(fList.Items[idx]);
  934. ht.AddPair(mth.FName,idx);
  935. end;
  936. {$endif}
  937. end;
  938. class function TlkJSONobject.Generate(AUseHash: Boolean = true):
  939. TlkJSONobject;
  940. begin
  941. result := TlkJSONobject.Create(AUseHash);
  942. end;
  943. function TlkJSONobject.OldGetField(nm: WideString): TlkJSONbase;
  944. var
  945. mth: TlkJSONobjectmethod;
  946. i: Integer;
  947. begin
  948. i := IndexOfName(nm);
  949. if i = -1 then
  950. begin
  951. result := nil;
  952. end
  953. else
  954. begin
  955. // mth := TlkJSONobjectmethod(FValue[i]);
  956. mth := TlkJSONobjectmethod(fList.Items[i]);
  957. result := mth.FValue;
  958. end;
  959. end;
  960. function TlkJSONobject.IndexOfName(const aname: WideString): Integer;
  961. var
  962. mth: TlkJSONobjectmethod;
  963. i: Integer;
  964. begin
  965. if not FUseHash then
  966. begin
  967. result := -1;
  968. for i := 0 to Count - 1 do
  969. begin
  970. // mth := TlkJSONobjectmethod(FValue[i]);
  971. mth := TlkJSONobjectmethod(fList.Items[i]);
  972. if mth.Name = aname then
  973. begin
  974. result := i;
  975. break;
  976. end;
  977. end;
  978. end
  979. else
  980. begin
  981. result := ht.IndexOf(aname);
  982. end;
  983. end;
  984. function TlkJSONobject.IndexOfObject(aobj: TlkJSONbase): Integer;
  985. var
  986. mth: TlkJSONobjectmethod;
  987. i: Integer;
  988. begin
  989. result := -1;
  990. for i := 0 to Count - 1 do
  991. begin
  992. // mth := TlkJSONobjectmethod(FValue[i]);
  993. mth := TlkJSONobjectmethod(fList.Items[i]);
  994. if mth.FValue = aobj then
  995. begin
  996. result := i;
  997. break;
  998. end;
  999. end;
  1000. end;
  1001. procedure TlkJSONobject.OldSetField(nm: WideString; const AValue:
  1002. TlkJSONbase);
  1003. var
  1004. mth: TlkJSONobjectmethod;
  1005. i: Integer;
  1006. begin
  1007. i := IndexOfName(nm);
  1008. if i <> -1 then
  1009. begin
  1010. // mth := TlkJSONobjectmethod(FValue[i]);
  1011. mth := TlkJSONobjectmethod(fList.Items[i]);
  1012. mth.FValue := AValue;
  1013. end;
  1014. end;
  1015. function TlkJSONobject.Add(const aname: WideString; nmb: double):
  1016. Integer;
  1017. begin
  1018. Result := self.Add(aname, TlkJSONnumber.Generate(nmb));
  1019. end;
  1020. function TlkJSONobject.Add(const aname: WideString; aboolean: Boolean):
  1021. Integer;
  1022. begin
  1023. Result := self.Add(aname, TlkJSONboolean.Generate(aboolean));
  1024. end;
  1025. function TlkJSONobject.Add(const aname: WideString; s: string):
  1026. Integer;
  1027. begin
  1028. Result := self.Add(aname, TlkJSONstring.Generate(s));
  1029. end;
  1030. function TlkJSONobject.Add(const aname: WideString; inmb: Integer):
  1031. Integer;
  1032. begin
  1033. Result := self.Add(aname, TlkJSONnumber.Generate(inmb));
  1034. end;
  1035. function TlkJSONobject.Add(const aname, ws: WideString): Integer;
  1036. begin
  1037. Result := self.Add(aname, TlkJSONstring.Generate(ws));
  1038. end;
  1039. class function TlkJSONobject.SelfType: TlkJSONtypes;
  1040. begin
  1041. Result := jsObject;
  1042. end;
  1043. class function TlkJSONobject.SelfTypeName: string;
  1044. begin
  1045. Result := 'jsObject';
  1046. end;
  1047. function TlkJSONobject.GetFieldByIndex(idx: Integer): TlkJSONbase;
  1048. var
  1049. nm: WideString;
  1050. begin
  1051. nm := GetNameOf(idx);
  1052. if nm <> '' then
  1053. begin
  1054. result := Field[nm];
  1055. end
  1056. else
  1057. begin
  1058. result := nil;
  1059. end;
  1060. end;
  1061. function TlkJSONobject.GetNameOf(idx: Integer): WideString;
  1062. var
  1063. mth: TlkJSONobjectmethod;
  1064. begin
  1065. if (idx < 0) or (idx >= Count) then
  1066. begin
  1067. result := '';
  1068. end
  1069. else
  1070. begin
  1071. mth := Child[idx] as TlkJSONobjectmethod;
  1072. result := mth.Name;
  1073. end;
  1074. end;
  1075. procedure TlkJSONobject.SetFieldByIndex(idx: Integer;
  1076. const AValue: TlkJSONbase);
  1077. var
  1078. nm: WideString;
  1079. begin
  1080. nm := GetNameOf(idx);
  1081. if nm <> '' then
  1082. begin
  1083. Field[nm] := AValue;
  1084. end;
  1085. end;
  1086. function TlkJSONobject.ForEachElement(idx: Integer;
  1087. var nm: string): TlkJSONbase;
  1088. begin
  1089. nm := GetNameOf(idx);
  1090. result := GetFieldByIndex(idx);
  1091. end;
  1092. function TlkJSONobject.GetField(AName: Variant):TlkJSONbase;
  1093. begin
  1094. if VarIsStr(AName) then
  1095. result := OldGetField(VarToWideStr(AName))
  1096. else
  1097. result := inherited GetField(AName);
  1098. end;
  1099. {$IFDEF USE_HASH}
  1100. function TlkJSONobject.GetHashTable: TlkHashTable;
  1101. {$ELSE}
  1102. function TlkJSONobject.GetHashTable: TlkBalTree;
  1103. {$ENDIF USE_HASH}
  1104. begin
  1105. result := ht;
  1106. end;
  1107. constructor TlkJSONobject.Create(bUseHash: Boolean);
  1108. begin
  1109. inherited Create;
  1110. FUseHash := bUseHash;
  1111. {$IFDEF USE_HASH}
  1112. ht := TlkHashTable.Create;
  1113. ht.FParent := self;
  1114. {$ELSE}
  1115. ht := TlkBalTree.Create;
  1116. {$ENDIF}
  1117. end;
  1118. destructor TlkJSONobject.Destroy;
  1119. begin
  1120. if assigned(ht) then FreeAndNil(ht);
  1121. inherited;
  1122. end;
  1123. function TlkJSONobject.getDouble(idx: Integer): Double;
  1124. var
  1125. jn: TlkJSONnumber;
  1126. begin
  1127. jn := FieldByIndex[idx] as TlkJSONnumber;
  1128. if not assigned(jn) then result := 0
  1129. else result := jn.Value;
  1130. end;
  1131. function TlkJSONobject.getInt(idx: Integer): Integer;
  1132. var
  1133. jn: TlkJSONnumber;
  1134. begin
  1135. jn := FieldByIndex[idx] as TlkJSONnumber;
  1136. if not assigned(jn) then result := 0
  1137. else result := round(int(jn.Value));
  1138. end;
  1139. function TlkJSONobject.getString(idx: Integer): string;
  1140. var
  1141. js: TlkJSONstring;
  1142. begin
  1143. js := FieldByIndex[idx] as TlkJSONstring;
  1144. if not assigned(js) then result := ''
  1145. else result := vartostr(js.Value);
  1146. end;
  1147. function TlkJSONobject.getWideString(idx: Integer): WideString;
  1148. var
  1149. js: TlkJSONstring;
  1150. begin
  1151. js := FieldByIndex[idx] as TlkJSONstring;
  1152. if not assigned(js) then result := ''
  1153. else result := VarToWideStr(js.Value);
  1154. end;
  1155. {$ifdef TCB_EXT}
  1156. function TlkJSONobject.getDoubleFromName(nm: string): Double;
  1157. {$else}
  1158. function TlkJSONobject.getDouble(nm: string): Double;
  1159. {$endif}
  1160. begin
  1161. result := getDouble(IndexOfName(nm));
  1162. end;
  1163. {$ifdef TCB_EXT}
  1164. function TlkJSONobject.getIntFromName(nm: string): Integer;
  1165. {$else}
  1166. function TlkJSONobject.getInt(nm: string): Integer;
  1167. {$endif}
  1168. begin
  1169. result := getInt(IndexOfName(nm));
  1170. end;
  1171. {$ifdef TCB_EXT}
  1172. function TlkJSONobject.getStringFromName(nm: string): string;
  1173. {$else}
  1174. function TlkJSONobject.getString(nm: string): string;
  1175. {$endif}
  1176. begin
  1177. result := getString(IndexOfName(nm));
  1178. end;
  1179. {$ifdef TCB_EXT}
  1180. function TlkJSONobject.getWideStringFromName(nm: string): WideString;
  1181. {$else}
  1182. function TlkJSONobject.getWideString(nm: string): WideString;
  1183. {$endif}
  1184. begin
  1185. result := getWideString(IndexOfName(nm));
  1186. end;
  1187. function TlkJSONobject.getBoolean(idx: Integer): Boolean;
  1188. var
  1189. jb: TlkJSONboolean;
  1190. begin
  1191. jb := FieldByIndex[idx] as TlkJSONboolean;
  1192. if not assigned(jb) then result := false
  1193. else result := jb.Value;
  1194. end;
  1195. {$ifdef TCB_EXT}
  1196. function TlkJSONobject.getBooleanFromName(nm: string): Boolean;
  1197. {$else}
  1198. function TlkJSONobject.getBoolean(nm: string): Boolean;
  1199. {$endif}
  1200. begin
  1201. result := getBoolean(IndexOfName(nm));
  1202. end;
  1203. { TlkJSON }
  1204. class function TlkJSON.GenerateText(obj: TlkJSONbase): string;
  1205. var
  1206. {$IFDEF HAVE_FORMATSETTING}
  1207. fs: TFormatSettings;
  1208. {$ENDIF}
  1209. pt1, pt0, pt2: PChar;
  1210. ptsz: cardinal;
  1211. {$IFNDEF NEW_STYLE_GENERATE}
  1212. function gn_base(obj: TlkJSONbase): string;
  1213. var
  1214. ws: string;
  1215. i, j: Integer;
  1216. xs: TlkJSONstring;
  1217. begin
  1218. result := '';
  1219. if not assigned(obj) then exit;
  1220. if obj is TlkJSONnumber then
  1221. begin
  1222. {$IFDEF HAVE_FORMATSETTING}
  1223. result := FloatToStr(TlkJSONnumber(obj).FValue, fs);
  1224. {$ELSE}
  1225. result := FloatToStr(TlkJSONnumber(obj).FValue);
  1226. i := pos(DecimalSeparator, result);
  1227. if (DecimalSeparator <> '.') and (i > 0) then
  1228. result[i] := '.';
  1229. {$ENDIF}
  1230. end
  1231. else if obj is TlkJSONstring then
  1232. begin
  1233. ws := UTF8Encode(TlkJSONstring(obj).FValue);
  1234. i := 1;
  1235. result := '"';
  1236. while i <= length(ws) do
  1237. begin
  1238. case ws[i] of
  1239. '/', '\', '"': result := result + '\' + ws[i];
  1240. #8: result := result + '\b';
  1241. #9: result := result + '\t';
  1242. #10: result := result + '\n';
  1243. #13: result := result + '\r';
  1244. #12: result := result + '\f';
  1245. else
  1246. if ord(ws[i]) < 32 then
  1247. result := result + '\u' + inttohex(ord(ws[i]), 4)
  1248. else
  1249. result := result + ws[i];
  1250. end;
  1251. inc(i);
  1252. end;
  1253. result := result + '"';
  1254. end
  1255. else if obj is TlkJSONboolean then
  1256. begin
  1257. if TlkJSONboolean(obj).FValue then
  1258. result := 'true'
  1259. else
  1260. result := 'false';
  1261. end
  1262. else if obj is TlkJSONnull then
  1263. begin
  1264. result := 'null';
  1265. end
  1266. else if obj is TlkJSONlist then
  1267. begin
  1268. result := '[';
  1269. j := TlkJSONobject(obj).Count - 1;
  1270. for i := 0 to j do
  1271. begin
  1272. if i > 0 then result := result + ',';
  1273. result := result + gn_base(TlkJSONlist(obj).Child[i]);
  1274. end;
  1275. result := result + ']';
  1276. end
  1277. else if obj is TlkJSONobjectmethod then
  1278. begin
  1279. try
  1280. xs := TlkJSONstring.Create;
  1281. xs.FValue := TlkJSONobjectmethod(obj).FName;
  1282. result := gn_base(TlkJSONbase(xs)) + ':';
  1283. result := result +
  1284. gn_base(TlkJSONbase(TlkJSONobjectmethod(obj).FValue));
  1285. finally
  1286. if assigned(xs) then FreeAndNil(xs);
  1287. end;
  1288. end
  1289. else if obj is TlkJSONobject then
  1290. begin
  1291. result := '{';
  1292. j := TlkJSONobject(obj).Count - 1;
  1293. for i := 0 to j do
  1294. begin
  1295. if i > 0 then result := result + ',';
  1296. result := result + gn_base(TlkJSONobject(obj).Child[i]);
  1297. end;
  1298. result := result + '}';
  1299. end;
  1300. end;
  1301. {$ELSE}
  1302. procedure get_more_memory;
  1303. var
  1304. delta: cardinal;
  1305. begin
  1306. delta := 50000;
  1307. if pt0 = nil then
  1308. begin
  1309. pt0 := AllocMem(delta);
  1310. ptsz := 0;
  1311. pt1 := pt0;
  1312. end
  1313. else
  1314. begin
  1315. ReallocMem(pt0, ptsz + delta);
  1316. pt1 := pointer(cardinal(pt0) + ptsz);
  1317. end;
  1318. ptsz := ptsz + delta;
  1319. pt2 := pointer(cardinal(pt1) + delta);
  1320. end;
  1321. procedure mem_ch(ch: char);
  1322. begin
  1323. if pt1 >= pt2 then get_more_memory;
  1324. pt1^ := ch;
  1325. inc(pt1);
  1326. end;
  1327. procedure mem_write(rs: string);
  1328. var
  1329. i: Integer;
  1330. begin
  1331. for i := 1 to length(rs) do
  1332. begin
  1333. if pt1 >= pt2 then get_more_memory;
  1334. pt1^ := rs[i];
  1335. inc(pt1);
  1336. end;
  1337. end;
  1338. procedure gn_base(obj: TlkJSONbase);
  1339. var
  1340. ws: string;
  1341. i, j: Integer;
  1342. xs: TlkJSONstring;
  1343. begin
  1344. if not assigned(obj) then exit;
  1345. if obj is TlkJSONnumber then
  1346. begin
  1347. {$IFDEF HAVE_FORMATSETTING}
  1348. mem_write(FloatToStr(TlkJSONnumber(obj).FValue, fs));
  1349. {$ELSE}
  1350. ws := FloatToStr(TlkJSONnumber(obj).FValue);
  1351. i := pos(DecimalSeparator, ws);
  1352. if (DecimalSeparator <> '.') and (i > 0) then ws[i] := '.';
  1353. mem_write(ws);
  1354. {$ENDIF}
  1355. end
  1356. else if obj is TlkJSONstring then
  1357. begin
  1358. ws := UTF8Encode(TlkJSONstring(obj).FValue);
  1359. i := 1;
  1360. mem_ch('"');
  1361. while i <= length(ws) do
  1362. begin
  1363. case ws[i] of
  1364. '/', '\', '"':
  1365. begin
  1366. mem_ch('\');
  1367. mem_ch(ws[i]);
  1368. end;
  1369. #8: mem_write('\b');
  1370. #9: mem_write('\t');
  1371. #10: mem_write('\n');
  1372. #13: mem_write('\r');
  1373. #12: mem_write('\f');
  1374. else
  1375. if ord(ws[i]) < 32 then
  1376. mem_write('\u' + inttohex(ord(ws[i]), 4))
  1377. else
  1378. mem_ch(ws[i]);
  1379. end;
  1380. inc(i);
  1381. end;
  1382. mem_ch('"');
  1383. end
  1384. else if obj is TlkJSONboolean then
  1385. begin
  1386. if TlkJSONboolean(obj).FValue then
  1387. mem_write('true')
  1388. else
  1389. mem_write('false');
  1390. end
  1391. else if obj is TlkJSONnull then
  1392. begin
  1393. mem_write('null');
  1394. end
  1395. else if obj is TlkJSONlist then
  1396. begin
  1397. mem_ch('[');
  1398. j := TlkJSONobject(obj).Count - 1;
  1399. for i := 0 to j do
  1400. begin
  1401. if i > 0 then mem_ch(',');
  1402. gn_base(TlkJSONlist(obj).Child[i]);
  1403. end;
  1404. mem_ch(']');
  1405. end
  1406. else if obj is TlkJSONobjectmethod then
  1407. begin
  1408. try
  1409. xs := TlkJSONstring.Create;
  1410. xs.FValue := TlkJSONobjectmethod(obj).FName;
  1411. gn_base(TlkJSONbase(xs));
  1412. mem_ch(':');
  1413. gn_base(TlkJSONbase(TlkJSONobjectmethod(obj).FValue));
  1414. finally
  1415. if assigned(xs) then FreeAndNil(xs);
  1416. end;
  1417. end
  1418. else if obj is TlkJSONobject then
  1419. begin
  1420. mem_ch('{');
  1421. j := TlkJSONobject(obj).Count - 1;
  1422. for i := 0 to j do
  1423. begin
  1424. if i > 0 then mem_ch(',');
  1425. gn_base(TlkJSONobject(obj).Child[i]);
  1426. end;
  1427. mem_ch('}');
  1428. end;
  1429. end;
  1430. {$ENDIF NEW_STYLE_GENERATE}
  1431. begin
  1432. {$IFDEF HAVE_FORMATSETTING}
  1433. GetLocaleFormatSettings(GetThreadLocale, fs);
  1434. fs.DecimalSeparator := '.';
  1435. {$ENDIF}
  1436. {$IFDEF NEW_STYLE_GENERATE}
  1437. pt0 := nil;
  1438. get_more_memory;
  1439. gn_base(obj);
  1440. mem_ch(#0);
  1441. result := string(pt0);
  1442. freemem(pt0);
  1443. {$ELSE}
  1444. result := gn_base(obj);
  1445. {$ENDIF}
  1446. end;
  1447. class function TlkJSON.ParseText(const txt: string): TlkJSONbase;
  1448. {$IFDEF HAVE_FORMATSETTING}
  1449. var
  1450. fs: TFormatSettings;
  1451. {$ENDIF}
  1452. function js_base(idx: Integer; var ridx: Integer; var o:
  1453. TlkJSONbase): Boolean; forward;
  1454. function xe(idx: Integer): Boolean;
  1455. {$IFDEF FPC}inline;
  1456. {$ENDIF}
  1457. begin
  1458. result := idx <= length(txt);
  1459. end;
  1460. procedure skip_spc(var idx: Integer);
  1461. {$IFDEF FPC}inline;
  1462. {$ENDIF}
  1463. begin
  1464. while (xe(idx)) and (ord(txt[idx]) < 33) do
  1465. inc(idx);
  1466. end;
  1467. procedure add_child(var o, c: TlkJSONbase);
  1468. var
  1469. i: Integer;
  1470. begin
  1471. if o = nil then
  1472. begin
  1473. o := c;
  1474. end
  1475. else
  1476. begin
  1477. if o is TlkJSONobjectmethod then
  1478. begin
  1479. TlkJSONobjectmethod(o).FValue := c;
  1480. end
  1481. else if o is TlkJSONlist then
  1482. begin
  1483. TlkJSONlist(o)._Add(c);
  1484. end
  1485. else if o is TlkJSONobject then
  1486. begin
  1487. i := TlkJSONobject(o)._Add(c);
  1488. if TlkJSONobject(o).UseHash then
  1489. {$IFDEF USE_HASH}
  1490. TlkJSONobject(o).ht.AddPair(TlkJSONobjectmethod(c).Name, i);
  1491. {$ELSE}
  1492. TlkJSONobject(o).ht.Insert(TlkJSONobjectmethod(c).Name, i);
  1493. {$ENDIF USE_HASH}
  1494. end;
  1495. end;
  1496. end;
  1497. function js_boolean(idx: Integer; var ridx: Integer; var o:
  1498. TlkJSONbase): Boolean;
  1499. var
  1500. js: TlkJSONboolean;
  1501. begin
  1502. skip_spc(idx);
  1503. if copy(txt, idx, 4) = 'true' then
  1504. begin
  1505. result := true;
  1506. ridx := idx + 4;
  1507. js := TlkJSONboolean.Create;
  1508. js.FValue := true;
  1509. add_child(o, TlkJSONbase(js));
  1510. end
  1511. else if copy(txt, idx, 5) = 'false' then
  1512. begin
  1513. result := true;
  1514. ridx := idx + 5;
  1515. js := TlkJSONboolean.Create;
  1516. js.FValue := false;
  1517. add_child(o, TlkJSONbase(js));
  1518. end
  1519. else
  1520. begin
  1521. result := false;
  1522. end;
  1523. end;
  1524. function js_null(idx: Integer; var ridx: Integer; var o:
  1525. TlkJSONbase): Boolean;
  1526. var
  1527. js: TlkJSONnull;
  1528. begin
  1529. skip_spc(idx);
  1530. if copy(txt, idx, 4) = 'null' then
  1531. begin
  1532. result := true;
  1533. ridx := idx + 4;
  1534. js := TlkJSONnull.Create;
  1535. add_child(o, TlkJSONbase(js));
  1536. end
  1537. else
  1538. begin
  1539. result := false;
  1540. end;
  1541. end;
  1542. function js_integer(idx: Integer; var ridx: Integer): Boolean;
  1543. begin
  1544. result := false;
  1545. while (xe(idx)) and (txt[idx] in ['0'..'9']) do
  1546. begin
  1547. result := true;
  1548. inc(idx);
  1549. end;
  1550. if result then ridx := idx;
  1551. end;
  1552. function js_number(idx: Integer; var ridx: Integer; var o:
  1553. TlkJSONbase): Boolean;
  1554. var
  1555. js: TlkJSONnumber;
  1556. ws: string;
  1557. {$IFNDEF HAVE_FORMATSETTING}
  1558. i: Integer;
  1559. {$ENDIF}
  1560. begin
  1561. skip_spc(idx);
  1562. result := xe(idx);
  1563. if not result then exit;
  1564. if txt[idx] in ['+', '-'] then
  1565. begin
  1566. inc(idx);
  1567. result := xe(idx);
  1568. end;
  1569. if not result then exit;
  1570. result := js_integer(idx, idx);
  1571. if not result then exit;
  1572. if (xe(idx)) and (txt[idx] = '.') then
  1573. begin
  1574. inc(idx);
  1575. result := js_integer(idx, idx);
  1576. if not result then exit;
  1577. end;
  1578. if (xe(idx)) and (txt[idx] in ['e', 'E']) then
  1579. begin
  1580. inc(idx);
  1581. if (xe(idx)) and (txt[idx] in ['+', '-']) then inc(idx);
  1582. result := js_integer(idx, idx);
  1583. if not result then exit;
  1584. end;
  1585. if not result then exit;
  1586. js := TlkJSONnumber.Create;
  1587. ws := copy(txt, ridx, idx - ridx);
  1588. {$IFDEF HAVE_FORMATSETTING}
  1589. js.FValue := StrToFloat(ws, fs);
  1590. {$ELSE}
  1591. i := pos('.', ws);
  1592. if (DecimalSeparator <> '.') and (i > 0) then
  1593. ws[pos('.', ws)] := DecimalSeparator;
  1594. js.FValue := StrToFloat(ws);
  1595. {$ENDIF}
  1596. add_child(o, TlkJSONbase(js));
  1597. ridx := idx;
  1598. end;
  1599. {
  1600. }
  1601. function js_string(idx: Integer; var ridx: Integer; var o:
  1602. TlkJSONbase): Boolean;
  1603. function strSpecialChars(const s: string): string;
  1604. var
  1605. i, j : integer;
  1606. begin
  1607. i := Pos('\', s);
  1608. if (i = 0) then
  1609. Result := s
  1610. else
  1611. begin
  1612. Result := Copy(s, 1, i-1);
  1613. j := i;
  1614. repeat
  1615. if (s[j] = '\') then
  1616. begin
  1617. inc(j);
  1618. case s[j] of
  1619. '\': Result := Result + '\';
  1620. '"': Result := Result + '"';
  1621. '''': Result := Result + '''';
  1622. '/': Result := Result + '/';
  1623. 'b': Result := Result + #8;
  1624. 'f': Result := Result + #12;
  1625. 'n': Result := Result + #10;
  1626. 'r': Result := Result + #13;
  1627. 't': Result := Result + #9;
  1628. 'u':
  1629. begin
  1630. Result := Result + code2utf(strtoint('$' + copy(s, j + 1, 4)));
  1631. inc(j, 4);
  1632. end;
  1633. end;
  1634. end
  1635. else
  1636. Result := Result + s[j];
  1637. inc(j);
  1638. until j > length(s);
  1639. end;
  1640. end;
  1641. var
  1642. js: TlkJSONstring;
  1643. fin: Boolean;
  1644. ws: String;
  1645. i,j,widx: Integer;
  1646. begin
  1647. skip_spc(idx);
  1648. result := xe(idx) and (txt[idx] = '"');
  1649. if not result then exit;
  1650. inc(idx);
  1651. widx := idx;
  1652. fin:=false;
  1653. REPEAT
  1654. i := 0;
  1655. j := 0;
  1656. while (widx<=length(txt)) and (j=0) do
  1657. begin
  1658. if (i=0) and (txt[widx]='\') then i:=widx;
  1659. if (j=0) and (txt[widx]='"') then j:=widx;
  1660. inc(widx);
  1661. end;
  1662. // incorrect string!!!
  1663. if j=0 then
  1664. begin
  1665. result := false;
  1666. exit;
  1667. end;
  1668. // if we have no slashed chars in string
  1669. if (i=0) or (j<i) then
  1670. begin
  1671. ws := copy(txt,idx,j-idx);
  1672. idx := j;
  1673. fin := true;
  1674. end
  1675. // if i>0 and j>=i - skip slashed char
  1676. else
  1677. begin
  1678. widx:=i+2;
  1679. end;
  1680. UNTIL fin;
  1681. ws := strSpecialChars(ws);
  1682. inc(idx);
  1683. js := TlkJSONstring.Create;
  1684. {$ifdef USE_D2009}
  1685. js.FValue := UTF8ToString(ws);
  1686. {$else}
  1687. js.FValue := UTF8Decode(ws);
  1688. {$endif}
  1689. add_child(o, TlkJSONbase(js));
  1690. ridx := idx;
  1691. end;
  1692. function js_list(idx: Integer; var ridx: Integer; var o:
  1693. TlkJSONbase): Boolean;
  1694. var
  1695. js: TlkJSONlist;
  1696. begin
  1697. result := false;
  1698. try
  1699. js := TlkJSONlist.Create;
  1700. skip_spc(idx);
  1701. result := xe(idx);
  1702. if not result then exit;
  1703. result := txt[idx] = '[';
  1704. if not result then exit;
  1705. inc(idx);
  1706. while js_base(idx, idx, TlkJSONbase(js)) do
  1707. begin
  1708. skip_spc(idx);
  1709. if (xe(idx)) and (txt[idx] = ',') then inc(idx);
  1710. end;
  1711. skip_spc(idx);
  1712. result := (xe(idx)) and (txt[idx] = ']');
  1713. if not result then exit;
  1714. inc(idx);
  1715. finally
  1716. if not result then
  1717. begin
  1718. js.Free;
  1719. end
  1720. else
  1721. begin
  1722. add_child(o, TlkJSONbase(js));
  1723. ridx := idx;
  1724. end;
  1725. end;
  1726. end;
  1727. function js_method(idx: Integer; var ridx: Integer; var o:
  1728. TlkJSONbase): Boolean;
  1729. var
  1730. mth: TlkJSONobjectmethod;
  1731. ws: TlkJSONstring;
  1732. begin
  1733. result := false;
  1734. try
  1735. ws := nil;
  1736. mth := TlkJSONobjectmethod.Create;
  1737. skip_spc(idx);
  1738. result := xe(idx);
  1739. if not result then exit;
  1740. result := js_string(idx, idx, TlkJSONbase(ws));
  1741. if not result then exit;
  1742. skip_spc(idx);
  1743. result := xe(idx) and (txt[idx] = ':');
  1744. if not result then exit;
  1745. inc(idx);
  1746. mth.FName := ws.FValue;
  1747. result := js_base(idx, idx, TlkJSONbase(mth));
  1748. finally
  1749. if ws <> nil then ws.Free;
  1750. if result then
  1751. begin
  1752. add_child(o, TlkJSONbase(mth));
  1753. ridx := idx;
  1754. end
  1755. else
  1756. begin
  1757. mth.Free;
  1758. end;
  1759. end;
  1760. end;
  1761. function js_object(idx: Integer; var ridx: Integer; var o:
  1762. TlkJSONbase): Boolean;
  1763. var
  1764. js: TlkJSONobject;
  1765. begin
  1766. result := false;
  1767. try
  1768. js := TlkJSONobject.Create;
  1769. skip_spc(idx);
  1770. result := xe(idx);
  1771. if not result then exit;
  1772. result := txt[idx] = '{';
  1773. if not result then exit;
  1774. inc(idx);
  1775. while js_method(idx, idx, TlkJSONbase(js)) do
  1776. begin
  1777. skip_spc(idx);
  1778. if (xe(idx)) and (txt[idx] = ',') then inc(idx);
  1779. end;
  1780. skip_spc(idx);
  1781. result := (xe(idx)) and (txt[idx] = '}');
  1782. if not result then exit;
  1783. inc(idx);
  1784. finally
  1785. if not result then
  1786. begin
  1787. js.Free;
  1788. end
  1789. else
  1790. begin
  1791. add_child(o, TlkJSONbase(js));
  1792. ridx := idx;
  1793. end;
  1794. end;
  1795. end;
  1796. function js_base(idx: Integer; var ridx: Integer; var o:
  1797. TlkJSONbase): Boolean;
  1798. begin
  1799. skip_spc(idx);
  1800. result := js_boolean(idx, idx, o);
  1801. if not result then result := js_null(idx, idx, o);
  1802. if not result then result := js_number(idx, idx, o);
  1803. if not result then result := js_string(idx, idx, o);
  1804. if not result then result := js_list(idx, idx, o);
  1805. if not result then result := js_object(idx, idx, o);
  1806. if result then ridx := idx;
  1807. end;
  1808. var
  1809. idx: Integer;
  1810. begin
  1811. {$IFDEF HAVE_FORMATSETTING}
  1812. GetLocaleFormatSettings(GetThreadLocale, fs);
  1813. fs.DecimalSeparator := '.';
  1814. {$ENDIF}
  1815. result := nil;
  1816. if txt = '' then exit;
  1817. try
  1818. idx := 1;
  1819. // skip a BOM utf8 marker
  1820. if copy(txt,idx,3)=#239#187#191 then
  1821. begin
  1822. inc(idx,3);
  1823. // if there are only a BOM - exit;
  1824. if idx>length(txt) then exit;
  1825. end;
  1826. if not js_base(idx, idx, result) then FreeAndNil(result);
  1827. except
  1828. if assigned(result) then FreeAndNil(result);
  1829. end;
  1830. end;
  1831. { ElkIntException }
  1832. constructor ElkIntException.Create(idx: Integer; msg: string);
  1833. begin
  1834. self.idx := idx;
  1835. inherited Create(msg);
  1836. end;
  1837. { TlkHashTable }
  1838. {$IFDEF USE_HASH}
  1839. procedure TlkHashTable.AddPair(const ws: WideString; idx: Integer);
  1840. var
  1841. i, j, k: cardinal;
  1842. p: PlkHashItem;
  1843. find: boolean;
  1844. begin
  1845. find := false;
  1846. if InTable(ws, i, j, k) then
  1847. begin
  1848. // if string is already in table, changing index
  1849. if TlkJSONobject(FParent).GetNameOf(PlkHashItem(a_x[j].Items[k])^.index) = ws then
  1850. begin
  1851. PlkHashItem(a_x[j].Items[k])^.index := idx;
  1852. find := true;
  1853. end;
  1854. end;
  1855. if find = false then
  1856. begin
  1857. GetMem(p,sizeof(TlkHashItem));
  1858. k := a_x[j].Add(p);
  1859. p^.hash := i;
  1860. p^.index := idx;
  1861. while (k>0) and (PlkHashItem(a_x[j].Items[k])^.hash < PlkHashItem(a_x[j].Items[k-1])^.hash) do
  1862. begin
  1863. a_x[j].Exchange(k,k-1);
  1864. dec(k);
  1865. end;
  1866. end;
  1867. end;
  1868. function TlkHashTable.counters: string;
  1869. var
  1870. i, j: Integer;
  1871. ws: string;
  1872. begin
  1873. ws := '';
  1874. for i := 0 to 15 do
  1875. begin
  1876. for j := 0 to 15 do
  1877. // ws := ws + format('%.3d ', [length(a_h[i * 16 + j])]);
  1878. ws := ws + format('%.3d ', [a_x[i * 16 + j].Count]);
  1879. ws := ws + #13#10;
  1880. end;
  1881. result := ws;
  1882. end;
  1883. procedure TlkHashTable.Delete(const ws: WideString);
  1884. var
  1885. i, j, k: cardinal;
  1886. begin
  1887. if InTable(ws, i, j, k) then
  1888. begin
  1889. // while k < high(a_h[j]) do
  1890. // begin
  1891. // hswap(j, k, k + 1);
  1892. // inc(k);
  1893. // end;
  1894. // SetLength(a_h[j], k);
  1895. FreeMem(a_x[j].Items[k]);
  1896. a_x[j].Delete(k);
  1897. end;
  1898. end;
  1899. {$IFDEF THREADSAFE}
  1900. const
  1901. rnd_table: array[0..255] of byte =
  1902. (216, 191, 234, 201, 12, 163, 190, 205, 128, 199, 210, 17, 52, 43,
  1903. 38, 149, 40, 207, 186, 89, 92, 179, 142, 93, 208, 215, 162,
  1904. 161, 132, 59, 246, 37, 120, 223, 138, 233, 172, 195, 94, 237, 32,
  1905. 231, 114, 49, 212, 75, 198, 181, 200, 239, 90, 121, 252, 211,
  1906. 46, 125, 112, 247, 66, 193, 36, 91, 150, 69, 24, 255, 42, 9, 76,
  1907. 227, 254, 13, 192, 7, 18, 81, 116, 107, 102, 213, 104, 15, 250,
  1908. 153, 156, 243, 206, 157, 16, 23, 226, 225, 196, 123, 54, 101,
  1909. 184, 31, 202, 41, 236, 3, 158, 45, 96, 39, 178, 113, 20, 139, 6,
  1910. 245, 8, 47, 154, 185, 60, 19, 110, 189, 176, 55, 130, 1, 100,
  1911. 155, 214, 133, 88, 63, 106, 73, 140, 35, 62, 77, 0, 71, 82, 145,
  1912. 180,
  1913. 171, 166, 21, 168, 79, 58, 217, 220, 51, 14, 221, 80, 87, 34, 33,
  1914. 4, 187, 118, 165, 248, 95, 10, 105, 44, 67, 222, 109, 160, 103,
  1915. 242, 177, 84, 203, 70, 53, 72, 111, 218, 249, 124, 83, 174, 253,
  1916. 240, 119, 194, 65, 164, 219, 22, 197, 152, 127, 170, 137, 204,
  1917. 99, 126, 141, 64, 135, 146, 209, 244, 235, 230, 85, 232, 143,
  1918. 122, 25, 28, 115, 78, 29, 144, 151, 98, 97, 68, 251, 182, 229,
  1919. 56,
  1920. 159, 74, 169, 108, 131, 30, 173, 224, 167, 50, 241, 148, 11, 134,
  1921. 117, 136, 175, 26, 57, 188, 147, 238, 61, 48, 183, 2, 129,
  1922. 228, 27, 86, 5);
  1923. {$ELSE}
  1924. var
  1925. rnd_table: array[0..255] of byte;
  1926. {$ENDIF}
  1927. function TlkHashTable.DefaultHashOf(const ws: WideString): cardinal;
  1928. {$IFDEF DOTNET}
  1929. var
  1930. i, j: Integer;
  1931. x1, x2, x3, x4: byte;
  1932. begin
  1933. result := 0;
  1934. // result := 0;
  1935. x1 := 0;
  1936. x2 := 1;
  1937. for i := 1 to length(ws) do
  1938. begin
  1939. j := ord(ws[i]);
  1940. // first version of hashing
  1941. x1 := (x1 + j) {and $FF};
  1942. x2 := (x2 + 1 + (j shr 8)) {and $FF};
  1943. x3 := rnd_table[x1];
  1944. x4 := rnd_table[x3];
  1945. result := ((x1 * x4) + (x2 * x3)) xor result;
  1946. end;
  1947. end;
  1948. {$ELSE}
  1949. var
  1950. x1, x2, x3, x4: byte;
  1951. p: PWideChar;
  1952. begin
  1953. result := 0;
  1954. x1 := 0;
  1955. x2 := 1;
  1956. p := PWideChar(ws);
  1957. while p^ <> #0 do
  1958. begin
  1959. inc(x1, ord(p^)) {and $FF};
  1960. inc(x2, 1 + (ord(p^) shr 8)) {and $FF};
  1961. x3 := rnd_table[x1];
  1962. x4 := rnd_table[x3];
  1963. result := ((x1 * x4) + (x2 * x3)) xor result;
  1964. inc(p);
  1965. end;
  1966. end;
  1967. {$ENDIF}
  1968. procedure TlkHashTable.hswap(j, k, l: Integer);
  1969. //var
  1970. // h: TlkHashItem;
  1971. begin
  1972. // h := a_h[j, k];
  1973. // a_h[j, k] := a_h[j, l];
  1974. // a_h[j, l] := h;
  1975. a_x[j].Exchange(k, l);
  1976. end;
  1977. function TlkHashTable.IndexOf(const ws: WideString): Integer;
  1978. var
  1979. i, j, k: Cardinal;
  1980. begin
  1981. if not InTable(ws, i, j, k) then
  1982. begin
  1983. result := -1;
  1984. end
  1985. else
  1986. begin
  1987. // result := a_h[j, k].index;
  1988. result := PlkHashItem(a_x[j].Items[k])^.index;
  1989. end;
  1990. end;
  1991. function TlkHashTable.InTable(const ws: WideString; var i, j, k:
  1992. cardinal):
  1993. Boolean;
  1994. var
  1995. l, wu, wl: Integer;
  1996. x: Cardinal;
  1997. fin: Boolean;
  1998. begin
  1999. i := HashOf(ws);
  2000. j := i and $FF;
  2001. result := false;
  2002. {using "binary" search always, because array is sorted}
  2003. if a_x[j].Count-1 >= 0 then
  2004. begin
  2005. wl := 0;
  2006. wu := a_x[j].Count-1;
  2007. repeat
  2008. fin := true;
  2009. if PlkHashItem(a_x[j].Items[wl])^.hash = i then
  2010. begin
  2011. k := wl;
  2012. result := true;
  2013. end
  2014. else if PlkHashItem(a_x[j].Items[wu])^.hash = i then
  2015. begin
  2016. k := wu;
  2017. result := true;
  2018. end
  2019. else if (wu - wl) > 1 then
  2020. begin
  2021. fin := false;
  2022. x := (wl + wu) shr 1;
  2023. if PlkHashItem(a_x[j].Items[x])^.hash > i then
  2024. begin
  2025. wu := x;
  2026. end
  2027. else
  2028. begin
  2029. wl := x;
  2030. end;
  2031. end;
  2032. until fin;
  2033. end;
  2034. // verify k index in chain
  2035. if result = true then
  2036. begin
  2037. while (k > 0) and (PlkHashItem(a_x[j].Items[k])^.hash = PlkHashItem(a_x[j].Items[k-1])^.hash) do dec(k);
  2038. repeat
  2039. fin := true;
  2040. if TlkJSONobject(FParent).GetNameOf(PlkHashItem(a_x[j].Items[k])^.index) <> ws then
  2041. begin
  2042. if k < a_x[j].Count-1 then
  2043. begin
  2044. inc(k);
  2045. fin := false;
  2046. end
  2047. else
  2048. begin
  2049. result := false;
  2050. end;
  2051. end
  2052. else
  2053. begin
  2054. result := true;
  2055. end;
  2056. until fin;
  2057. end;
  2058. end;
  2059. {$IFNDEF THREADSAFE}
  2060. procedure init_rnd;
  2061. var
  2062. x0: Integer;
  2063. i: Integer;
  2064. begin
  2065. x0 := 5;
  2066. for i := 0 to 255 do
  2067. begin
  2068. x0 := (x0 * 29 + 71) and $FF;
  2069. rnd_table[i] := x0;
  2070. end;
  2071. end;
  2072. {$ENDIF}
  2073. procedure TlkHashTable.SetHashFunction(const AValue:
  2074. TlkHashFunction);
  2075. begin
  2076. FHashFunction := AValue;
  2077. end;
  2078. constructor TlkHashTable.Create;
  2079. var
  2080. i: Integer;
  2081. begin
  2082. inherited;
  2083. // for i := 0 to 255 do SetLength(a_h[i], 0);
  2084. for i := 0 to 255 do a_x[i] := TList.Create;
  2085. HashOf := {$IFDEF FPC}@{$ENDIF}DefaultHashOf;
  2086. end;
  2087. destructor TlkHashTable.Destroy;
  2088. var
  2089. i, j: Integer;
  2090. begin
  2091. // for i := 0 to 255 do SetLength(a_h[i], 0);
  2092. for i := 0 to 255 do
  2093. begin
  2094. for j := 0 to a_x[i].Count - 1 do Freemem(a_x[i].Items[j]);
  2095. a_x[i].Free;
  2096. end;
  2097. inherited;
  2098. end;
  2099. function TlkHashTable.SimpleHashOf(const ws: WideString): cardinal;
  2100. var
  2101. i: Integer;
  2102. begin
  2103. result := length(ws);
  2104. for i := 1 to length(ws) do result := result + ord(ws[i]);
  2105. end;
  2106. {$ENDIF USE_HASH}
  2107. { TlkJSONstreamed }
  2108. {$IFNDEF KOL}
  2109. class function TlkJSONstreamed.LoadFromFile(srcname: string):
  2110. TlkJSONbase;
  2111. var
  2112. fs: TFileStream;
  2113. begin
  2114. result := nil;
  2115. if not FileExists(srcname) then exit;
  2116. try
  2117. fs := TFileStream.Create(srcname, fmOpenRead);
  2118. result := LoadFromStream(fs);
  2119. finally
  2120. if Assigned(fs) then FreeAndNil(fs);
  2121. end;
  2122. end;
  2123. class function TlkJSONstreamed.LoadFromStream(src: TStream):
  2124. TlkJSONbase;
  2125. var
  2126. ws: string;
  2127. len: int64;
  2128. begin
  2129. result := nil;
  2130. if not assigned(src) then exit;
  2131. len := src.Size - src.Position;
  2132. SetLength(ws, len);
  2133. src.Read(pchar(ws)^, len);
  2134. result := ParseText(ws);
  2135. end;
  2136. class procedure TlkJSONstreamed.SaveToFile(obj: TlkJSONbase;
  2137. dstname: string);
  2138. var
  2139. fs: TFileStream;
  2140. begin
  2141. if not assigned(obj) then exit;
  2142. try
  2143. fs := TFileStream.Create(dstname, fmCreate);
  2144. SaveToStream(obj, fs);
  2145. finally
  2146. if Assigned(fs) then FreeAndNil(fs);
  2147. end;
  2148. end;
  2149. class procedure TlkJSONstreamed.SaveToStream(obj: TlkJSONbase;
  2150. dst: TStream);
  2151. var
  2152. ws: string;
  2153. begin
  2154. if not assigned(obj) then exit;
  2155. if not assigned(dst) then exit;
  2156. ws := GenerateText(obj);
  2157. dst.Write(pchar(ws)^, length(ws));
  2158. end;
  2159. {$ENDIF}
  2160. { TlkJSONdotnetclass }
  2161. {$IFDEF DOTNET}
  2162. procedure TlkJSONdotnetclass.AfterConstruction;
  2163. begin
  2164. end;
  2165. procedure TlkJSONdotnetclass.BeforeDestruction;
  2166. begin
  2167. end;
  2168. constructor TlkJSONdotnetclass.Create;
  2169. begin
  2170. inherited;
  2171. AfterConstruction;
  2172. end;
  2173. destructor TlkJSONdotnetclass.Destroy;
  2174. begin
  2175. BeforeDestruction;
  2176. inherited;
  2177. end;
  2178. {$ENDIF DOTNET}
  2179. { TlkBalTree }
  2180. {$IFNDEF USE_HASH}
  2181. procedure TlkBalTree.Clear;
  2182. procedure rec(t: PlkBalNode);
  2183. begin
  2184. if t.left<>fbottom then rec(t.left);
  2185. if t.right<>fbottom then rec(t.right);
  2186. t.nm := '';
  2187. dispose(t);
  2188. end;
  2189. begin
  2190. if froot<>fbottom then rec(froot);
  2191. froot := fbottom;
  2192. fdeleted := fbottom;
  2193. end;
  2194. function TlkBalTree.counters: string;
  2195. begin
  2196. result := format('Balanced tree root node level is %d',[froot.level]);
  2197. end;
  2198. constructor TlkBalTree.Create;
  2199. begin
  2200. inherited Create;
  2201. new(fbottom);
  2202. fbottom.left := fbottom;
  2203. fbottom.right := fbottom;
  2204. fbottom.level := 0;
  2205. fdeleted := fbottom;
  2206. froot := fbottom;
  2207. end;
  2208. function TlkBalTree.Delete(const ws: WideString): Boolean;
  2209. procedure UpdateKeys(t: PlkBalNode; idx: integer);
  2210. begin
  2211. if t <> fbottom then begin
  2212. if t.key > idx then
  2213. t.key := t.key - 1;
  2214. UpdateKeys(t.left, idx);
  2215. UpdateKeys(t.right, idx);
  2216. end;
  2217. end;
  2218. function del(var t: PlkBalNode): Boolean;
  2219. begin
  2220. result := false;
  2221. if t<>fbottom then begin
  2222. flast := t;
  2223. if ws<t.nm then
  2224. result := del(t.left)
  2225. else begin
  2226. fdeleted := t;
  2227. result := del(t.right);
  2228. end;
  2229. if (t = flast) and (fdeleted <> fbottom) and (ws = fdeleted.nm) then begin
  2230. UpdateKeys(froot, fdeleted.key);
  2231. fdeleted.key := t.key;
  2232. fdeleted.nm := t.nm;
  2233. t := t.right;
  2234. flast.nm := '';
  2235. dispose(flast);
  2236. result := true;
  2237. end
  2238. else if (t.left.level < (t.level - 1)) or (t.right.level < (t.level - 1)) then begin
  2239. t.level := t.level - 1;
  2240. if t.right.level > t.level then
  2241. t.right.level := t.level;
  2242. skew(t);
  2243. skew(t.right);
  2244. skew(t.right.right);
  2245. split(t);
  2246. split(t.right);
  2247. end;
  2248. end;
  2249. end;
  2250. {
  2251. // mine version, buggy, see tracker message
  2252. // [ 2229135 ] Value deletion is broken by "Nobody/Anonymous - nobody"
  2253. function del(var t: PlkBalNode): Boolean;
  2254. begin
  2255. result := false;
  2256. if t<>fbottom then
  2257. begin
  2258. flast := t;
  2259. if ws<t.nm then
  2260. result := del(t.left)
  2261. else
  2262. begin
  2263. fdeleted := t;
  2264. result := del(t.right);
  2265. end;
  2266. if (t = flast) and (fdeleted<>fbottom) and (ws = t.nm) then
  2267. begin
  2268. fdeleted.key := t.key;
  2269. fdeleted.nm := t.nm;
  2270. t := t.right;
  2271. flast.nm := '';
  2272. dispose(flast);
  2273. result := true;
  2274. end
  2275. else if (t.left.level<(t.level-1)) or (t.right.level<(t.level-1)) then
  2276. begin
  2277. t.level := t.level-1;
  2278. if t.right.level>t.level then t.right.level := t.level;
  2279. skew(t);
  2280. skew(t.right);
  2281. skew(t.right.right);
  2282. split(t);
  2283. split(t.right);
  2284. end;
  2285. end;
  2286. end;
  2287. }
  2288. begin
  2289. result := del(froot);
  2290. end;
  2291. destructor TlkBalTree.Destroy;
  2292. begin
  2293. Clear;
  2294. dispose(fbottom);
  2295. inherited;
  2296. end;
  2297. function TlkBalTree.IndexOf(const ws: WideString): Integer;
  2298. var
  2299. tk: PlkBalNode;
  2300. begin
  2301. result := -1;
  2302. tk := froot;
  2303. while (result=-1) and (tk<>fbottom) do
  2304. begin
  2305. if tk.nm = ws then result := tk.key
  2306. else if ws<tk.nm then tk := tk.left
  2307. else tk := tk.right;
  2308. end;
  2309. end;
  2310. function TlkBalTree.Insert(const ws: WideString; x: Integer): Boolean;
  2311. function ins(var t: PlkBalNode): Boolean;
  2312. begin
  2313. if t = fbottom then
  2314. begin
  2315. new(t);
  2316. t.key := x;
  2317. t.nm := ws;
  2318. t.left := fbottom;
  2319. t.right := fbottom;
  2320. t.level := 1;
  2321. result := true;
  2322. end
  2323. else
  2324. begin
  2325. if ws < t.nm then
  2326. result := ins(t.left)
  2327. else if ws > t.nm then
  2328. result := ins(t.right)
  2329. else result := false;
  2330. skew(t);
  2331. split(t);
  2332. end;
  2333. end;
  2334. begin
  2335. result := ins(froot);
  2336. end;
  2337. procedure TlkBalTree.skew(var t: PlkBalNode);
  2338. var
  2339. temp: PlkBalNode;
  2340. begin
  2341. if t.left.level = t.level then
  2342. begin
  2343. temp := t;
  2344. t := t.left;
  2345. temp.left := t.right;
  2346. t.right := temp;
  2347. end;
  2348. end;
  2349. procedure TlkBalTree.split(var t: PlkBalNode);
  2350. var
  2351. temp: PlkBalNode;
  2352. begin
  2353. if t.right.right.level = t.level then
  2354. begin
  2355. temp := t;
  2356. t := t.right;
  2357. temp.right := t.left;
  2358. t.left := temp;
  2359. t.level := t.level+1;
  2360. end;
  2361. end;
  2362. {$ENDIF USE_HASH}
  2363. initialization
  2364. {$IFNDEF THREADSAFE}
  2365. {$IFDEF USE_HASH}
  2366. init_rnd;
  2367. {$ENDIF USE_HASH}
  2368. {$ENDIF THREADSAFE}
  2369. end.