ustrings.inc 68 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 1999-2005 by Florian Klaempfl,
  4. member of the Free Pascal development team.
  5. This file implements support routines for UTF-8 strings with FPC
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. {$i wustrings.inc}
  13. {
  14. This file contains the implementation of the UnicodeString type,
  15. and all things that are needed for it.
  16. UnicodeString is defined as a 'silent' punicodechar :
  17. a punicodechar that points to :
  18. @-8 : SizeInt for reference count;
  19. @-4 : SizeInt for size; size=number of bytes, not the number of chars. Divide or multiply
  20. with sizeof(UnicodeChar) to convert. This is needed to be compatible with Delphi and
  21. Windows COM BSTR.
  22. @ : String + Terminating #0;
  23. Punicodechar(Unicodestring) is a valid typecast.
  24. So WS[i] is converted to the address @WS+i-1.
  25. Constants should be assigned a reference count of -1
  26. Meaning that they can't be disposed of.
  27. }
  28. Type
  29. PUnicodeRec = ^TUnicodeRec;
  30. TUnicodeRec = Packed Record
  31. Ref : SizeInt;
  32. Len : SizeInt;
  33. First : UnicodeChar;
  34. end;
  35. Const
  36. UnicodeRecLen = SizeOf(TUnicodeRec);
  37. UnicodeFirstOff = SizeOf(TUnicodeRec)-sizeof(UnicodeChar);
  38. {
  39. Default UnicodeChar <-> Char conversion is to only convert the
  40. lower 127 chars, all others are translated to '?'.
  41. These routines can be overwritten for the Current Locale
  42. }
  43. procedure DefaultUnicode2AnsiMove(source:punicodechar;var dest:ansistring;len:SizeInt);
  44. var
  45. i : SizeInt;
  46. p : PAnsiChar;
  47. begin
  48. setlength(dest,len);
  49. p:=pointer(dest); {SetLength guarantees that dest is unique}
  50. for i:=1 to len do
  51. begin
  52. if word(source^)<256 then
  53. p^:=char(word(source^))
  54. else
  55. p^:='?';
  56. inc(source);
  57. inc(p);
  58. end;
  59. end;
  60. procedure DefaultAnsi2UnicodeMove(source:pchar;var dest:unicodestring;len:SizeInt);
  61. var
  62. i : SizeInt;
  63. p : PUnicodeChar;
  64. begin
  65. setlength(dest,len);
  66. p:=pointer(dest); {SetLength guarantees that dest is unique}
  67. for i:=1 to len do
  68. begin
  69. p^:=unicodechar(byte(source^));
  70. inc(source);
  71. inc(p);
  72. end;
  73. end;
  74. Procedure GetUnicodeStringManager (Var Manager : TUnicodeStringManager);
  75. begin
  76. manager:=widestringmanager;
  77. end;
  78. Procedure SetUnicodeStringManager (Const New : TUnicodeStringManager; Var Old: TUnicodeStringManager);
  79. begin
  80. Old:=widestringmanager;
  81. widestringmanager:=New;
  82. end;
  83. Procedure SetUnicodeStringManager (Const New : TUnicodeStringManager);
  84. begin
  85. widestringmanager:=New;
  86. end;
  87. Procedure GetWideStringManager (Var Manager : TUnicodeStringManager);
  88. begin
  89. manager:=widestringmanager;
  90. end;
  91. Procedure SetWideStringManager (Const New : TUnicodeStringManager; Var Old: TUnicodeStringManager);
  92. begin
  93. Old:=widestringmanager;
  94. widestringmanager:=New;
  95. end;
  96. Procedure SetWideStringManager (Const New : TUnicodeStringManager);
  97. begin
  98. widestringmanager:=New;
  99. end;
  100. {****************************************************************************
  101. Internal functions, not in interface.
  102. ****************************************************************************}
  103. procedure UnicodeStringError;
  104. begin
  105. HandleErrorFrame(204,get_frame);
  106. end;
  107. {$ifdef UnicodeStrDebug}
  108. Procedure DumpUnicodeRec(S : Pointer);
  109. begin
  110. If S=Nil then
  111. Writeln ('String is nil')
  112. Else
  113. Begin
  114. With PUnicodeRec(S-UnicodeFirstOff)^ do
  115. begin
  116. Write ('(Len:',len);
  117. Writeln (' Ref: ',ref,')');
  118. end;
  119. end;
  120. end;
  121. {$endif}
  122. Function NewUnicodeString(Len : SizeInt) : Pointer;
  123. {
  124. Allocate a new UnicodeString on the heap.
  125. initialize it to zero length and reference count 1.
  126. }
  127. Var
  128. P : Pointer;
  129. begin
  130. GetMem(P,Len*sizeof(UnicodeChar)+UnicodeRecLen);
  131. If P<>Nil then
  132. begin
  133. PUnicodeRec(P)^.Len:=Len*2; { Initial length }
  134. PUnicodeRec(P)^.Ref:=1; { Initial Refcount }
  135. PUnicodeRec(P)^.First:=#0; { Terminating #0 }
  136. inc(p,UnicodeFirstOff); { Points to string now }
  137. end
  138. else
  139. UnicodeStringError;
  140. NewUnicodeString:=P;
  141. end;
  142. Procedure DisposeUnicodeString(Var S : Pointer);
  143. {
  144. Deallocates a UnicodeString From the heap.
  145. }
  146. begin
  147. If S=Nil then
  148. exit;
  149. Dec (S,UnicodeFirstOff);
  150. Freemem(S);
  151. S:=Nil;
  152. end;
  153. Procedure fpc_UnicodeStr_Decr_Ref (Var S : Pointer);[Public,Alias:'FPC_UNICODESTR_DECR_REF']; compilerproc;
  154. {
  155. Decreases the ReferenceCount of a non constant unicodestring;
  156. If the reference count is zero, deallocate the string;
  157. }
  158. Type
  159. pSizeInt = ^SizeInt;
  160. Var
  161. l : pSizeInt;
  162. Begin
  163. { Zero string }
  164. if S=Nil then
  165. exit;
  166. { check for constant strings ...}
  167. l:=@PUnicodeRec(S-UnicodeFirstOff)^.Ref;
  168. if l^<0 then
  169. exit;
  170. { declocked does a MT safe dec and returns true, if the counter is 0 }
  171. if declocked(l^) then
  172. { Ref count dropped to zero ...
  173. ... remove }
  174. DisposeUnicodeString(S);
  175. end;
  176. { alias for internal use }
  177. Procedure fpc_UnicodeStr_Decr_Ref (Var S : Pointer);[external name 'FPC_UNICODESTR_DECR_REF'];
  178. Procedure fpc_UnicodeStr_Incr_Ref(S : Pointer);[Public,Alias:'FPC_UNICODESTR_INCR_REF']; compilerproc;
  179. Begin
  180. If S=Nil then
  181. exit;
  182. { constant string ? }
  183. If PUnicodeRec(S-UnicodeFirstOff)^.Ref<0 then
  184. exit;
  185. inclocked(PUnicodeRec(S-UnicodeFirstOff)^.Ref);
  186. end;
  187. { alias for internal use }
  188. Procedure fpc_UnicodeStr_Incr_Ref (S : Pointer);[external name 'FPC_UNICODESTR_INCR_REF'];
  189. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  190. function fpc_UnicodeStr_To_ShortStr (high_of_res: SizeInt;const S2 : UnicodeString): shortstring;[Public, alias: 'FPC_UNICODESTR_TO_SHORTSTR']; compilerproc;
  191. {
  192. Converts a UnicodeString to a ShortString;
  193. }
  194. Var
  195. Size : SizeInt;
  196. temp : ansistring;
  197. begin
  198. result:='';
  199. Size:=Length(S2);
  200. if Size>0 then
  201. begin
  202. If Size>high_of_res then
  203. Size:=high_of_res;
  204. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(S2),temp,Size);
  205. result:=temp;
  206. end;
  207. end;
  208. {$else FPC_STRTOSHORTSTRINGPROC}
  209. procedure fpc_UnicodeStr_To_ShortStr (out res: ShortString;const S2 : UnicodeString); [Public, alias: 'FPC_UNICODESTR_TO_SHORTSTR'];compilerproc;
  210. {
  211. Converts a UnicodeString to a ShortString;
  212. }
  213. Var
  214. Size : SizeInt;
  215. temp : ansistring;
  216. begin
  217. res:='';
  218. Size:=Length(S2);
  219. if Size>0 then
  220. begin
  221. If Size>high(res) then
  222. Size:=high(res);
  223. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(S2),temp,Size);
  224. res:=temp;
  225. end;
  226. end;
  227. {$endif FPC_STRTOSHORTSTRINGPROC}
  228. Function fpc_ShortStr_To_UnicodeStr (Const S2 : ShortString): UnicodeString;compilerproc;
  229. {
  230. Converts a ShortString to a UnicodeString;
  231. }
  232. Var
  233. Size : SizeInt;
  234. begin
  235. result:='';
  236. Size:=Length(S2);
  237. if Size>0 then
  238. begin
  239. widestringmanager.Ansi2UnicodeMoveProc(PChar(@S2[1]),result,Size);
  240. { Terminating Zero }
  241. PUnicodeChar(Pointer(fpc_ShortStr_To_UnicodeStr)+Size*sizeof(UnicodeChar))^:=#0;
  242. end;
  243. end;
  244. Function fpc_UnicodeStr_To_AnsiStr (const S2 : UnicodeString): AnsiString; compilerproc;
  245. {
  246. Converts a UnicodeString to an AnsiString
  247. }
  248. Var
  249. Size : SizeInt;
  250. begin
  251. result:='';
  252. Size:=Length(S2);
  253. if Size>0 then
  254. widestringmanager.Unicode2AnsiMoveProc(PUnicodeChar(Pointer(S2)),result,Size);
  255. end;
  256. Function fpc_AnsiStr_To_UnicodeStr (Const S2 : AnsiString): UnicodeString; compilerproc;
  257. {
  258. Converts an AnsiString to a UnicodeString;
  259. }
  260. Var
  261. Size : SizeInt;
  262. begin
  263. result:='';
  264. Size:=Length(S2);
  265. if Size>0 then
  266. widestringmanager.Ansi2UnicodeMoveProc(PChar(S2),result,Size);
  267. end;
  268. Function fpc_UnicodeStr_To_WideStr (const S2 : UnicodeString): WideString; compilerproc;
  269. begin
  270. SetLength(Result,Length(S2));
  271. Move(pointer(S2)^,Pointer(Result)^,Length(S2)*sizeof(WideChar));
  272. end;
  273. Function fpc_WideStr_To_UnicodeStr (Const S2 : WideString): UnicodeString; compilerproc;
  274. begin
  275. SetLength(Result,Length(S2));
  276. Move(pointer(S2)^,Pointer(Result)^,Length(S2)*sizeof(WideChar));
  277. end;
  278. Function fpc_PUnicodeChar_To_AnsiStr(const p : punicodechar): ansistring; compilerproc;
  279. var
  280. Size : SizeInt;
  281. begin
  282. result:='';
  283. if p=nil then
  284. exit;
  285. Size := IndexWord(p^, -1, 0);
  286. if Size>0 then
  287. widestringmanager.Unicode2AnsiMoveProc(P,result,Size);
  288. end;
  289. Function fpc_PUnicodeChar_To_UnicodeStr(const p : punicodechar): unicodestring; compilerproc;
  290. var
  291. Size : SizeInt;
  292. begin
  293. result:='';
  294. if p=nil then
  295. exit;
  296. Size := IndexWord(p^, -1, 0);
  297. Setlength(result,Size);
  298. if Size>0 then
  299. begin
  300. Move(p^,PUnicodeChar(Pointer(result))^,Size*sizeof(UnicodeChar));
  301. { Terminating Zero }
  302. PUnicodeChar(Pointer(result)+Size*sizeof(UnicodeChar))^:=#0;
  303. end;
  304. end;
  305. Function fpc_PWideChar_To_UnicodeStr(const p : pwidechar): unicodestring; compilerproc;
  306. var
  307. Size : SizeInt;
  308. begin
  309. result:='';
  310. if p=nil then
  311. exit;
  312. Size := IndexWord(p^, -1, 0);
  313. Setlength(result,Size);
  314. if Size>0 then
  315. begin
  316. Move(p^,PUnicodeChar(Pointer(result))^,Size*sizeof(UnicodeChar));
  317. { Terminating Zero }
  318. PUnicodeChar(Pointer(result)+Size*sizeof(UnicodeChar))^:=#0;
  319. end;
  320. end;
  321. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  322. Function fpc_PUnicodeChar_To_ShortStr(const p : punicodechar): shortstring; compilerproc;
  323. var
  324. Size : SizeInt;
  325. temp: ansistring;
  326. begin
  327. result:='';
  328. if p=nil then
  329. exit;
  330. Size := IndexWord(p^, $7fffffff, 0);
  331. if Size>0 then
  332. begin
  333. widestringmanager.Unicode2AnsiMoveProc(p,temp,Size);
  334. result:=temp;
  335. end;
  336. end;
  337. {$else FPC_STRTOSHORTSTRINGPROC}
  338. procedure fpc_PUnicodeChar_To_ShortStr(out res : shortstring;const p : punicodechar); compilerproc;
  339. var
  340. Size : SizeInt;
  341. temp: ansistring;
  342. begin
  343. res:='';
  344. if p=nil then
  345. exit;
  346. Size:=IndexWord(p^, high(PtrInt), 0);
  347. if Size>0 then
  348. begin
  349. widestringmanager.Unicode2AnsiMoveProc(p,temp,Size);
  350. res:=temp;
  351. end;
  352. end;
  353. {$endif FPC_STRTOSHORTSTRINGPROC}
  354. Function fpc_PWideChar_To_AnsiStr(const p : pwidechar): ansistring; compilerproc;
  355. var
  356. Size : SizeInt;
  357. begin
  358. result:='';
  359. if p=nil then
  360. exit;
  361. Size := IndexWord(p^, -1, 0);
  362. if Size>0 then
  363. widestringmanager.Wide2AnsiMoveProc(P,result,Size);
  364. end;
  365. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  366. Function fpc_PWideChar_To_ShortStr(const p : pwidechar): shortstring; compilerproc;
  367. var
  368. Size : SizeInt;
  369. temp: ansistring;
  370. begin
  371. result:='';
  372. if p=nil then
  373. exit;
  374. Size := IndexWord(p^, $7fffffff, 0);
  375. if Size>0 then
  376. begin
  377. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  378. result:=temp;
  379. end;
  380. end;
  381. {$else FPC_STRTOSHORTSTRINGPROC}
  382. procedure fpc_PWideChar_To_ShortStr(out res : shortstring;const p : pwidechar); compilerproc;
  383. var
  384. Size : SizeInt;
  385. temp: ansistring;
  386. begin
  387. res:='';
  388. if p=nil then
  389. exit;
  390. Size:=IndexWord(p^, high(PtrInt), 0);
  391. if Size>0 then
  392. begin
  393. widestringmanager.Wide2AnsiMoveProc(p,temp,Size);
  394. res:=temp;
  395. end;
  396. end;
  397. {$endif FPC_STRTOSHORTSTRINGPROC}
  398. { checked against the ansistring routine, 2001-05-27 (FK) }
  399. Procedure fpc_UnicodeStr_Assign (Var S1 : Pointer;S2 : Pointer);[Public,Alias:'FPC_UNICODESTR_ASSIGN']; compilerproc;
  400. {
  401. Assigns S2 to S1 (S1:=S2), taking in account reference counts.
  402. }
  403. begin
  404. If S2<>nil then
  405. If PUnicodeRec(S2-UnicodeFirstOff)^.Ref>0 then
  406. inclocked(PUnicodeRec(S2-UnicodeFirstOff)^.ref);
  407. { Decrease the reference count on the old S1 }
  408. fpc_unicodestr_decr_ref (S1);
  409. s1:=s2;
  410. end;
  411. { alias for internal use }
  412. Procedure fpc_UnicodeStr_Assign (Var S1 : Pointer;S2 : Pointer);[external name 'FPC_UNICODESTR_ASSIGN'];
  413. {$ifndef STR_CONCAT_PROCS}
  414. function fpc_UnicodeStr_Concat (const S1,S2 : UnicodeString): UnicodeString; compilerproc;
  415. Var
  416. Size,Location : SizeInt;
  417. pc : punicodechar;
  418. begin
  419. { only assign if s1 or s2 is empty }
  420. if (S1='') then
  421. begin
  422. result:=s2;
  423. exit;
  424. end;
  425. if (S2='') then
  426. begin
  427. result:=s1;
  428. exit;
  429. end;
  430. Location:=Length(S1);
  431. Size:=length(S2);
  432. SetLength(result,Size+Location);
  433. pc:=punicodechar(result);
  434. Move(S1[1],pc^,Location*sizeof(UnicodeChar));
  435. inc(pc,location);
  436. Move(S2[1],pc^,(Size+1)*sizeof(UnicodeChar));
  437. end;
  438. function fpc_UnicodeStr_Concat_multi (const sarr:array of Unicodestring): unicodestring; compilerproc;
  439. Var
  440. i : Longint;
  441. p : pointer;
  442. pc : punicodechar;
  443. Size,NewSize : SizeInt;
  444. begin
  445. { First calculate size of the result so we can do
  446. a single call to SetLength() }
  447. NewSize:=0;
  448. for i:=low(sarr) to high(sarr) do
  449. inc(Newsize,length(sarr[i]));
  450. SetLength(result,NewSize);
  451. pc:=punicodechar(result);
  452. for i:=low(sarr) to high(sarr) do
  453. begin
  454. p:=pointer(sarr[i]);
  455. if assigned(p) then
  456. begin
  457. Size:=length(unicodestring(p));
  458. Move(punicodechar(p)^,pc^,(Size+1)*sizeof(UnicodeChar));
  459. inc(pc,size);
  460. end;
  461. end;
  462. end;
  463. {$else STR_CONCAT_PROCS}
  464. procedure fpc_UnicodeStr_Concat (var DestS:Unicodestring;const S1,S2 : UnicodeString); compilerproc;
  465. Var
  466. Size,Location : SizeInt;
  467. same : boolean;
  468. begin
  469. { only assign if s1 or s2 is empty }
  470. if (S1='') then
  471. begin
  472. DestS:=s2;
  473. exit;
  474. end;
  475. if (S2='') then
  476. begin
  477. DestS:=s1;
  478. exit;
  479. end;
  480. Location:=Length(S1);
  481. Size:=length(S2);
  482. { Use Pointer() typecasts to prevent extra conversion code }
  483. if Pointer(DestS)=Pointer(S1) then
  484. begin
  485. same:=Pointer(S1)=Pointer(S2);
  486. SetLength(DestS,Size+Location);
  487. if same then
  488. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(UnicodeChar))^,(Size)*sizeof(UnicodeChar))
  489. else
  490. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(UnicodeChar))^,(Size+1)*sizeof(UnicodeChar));
  491. end
  492. else if Pointer(DestS)=Pointer(S2) then
  493. begin
  494. SetLength(DestS,Size+Location);
  495. Move(Pointer(DestS)^,(Pointer(DestS)+Location*sizeof(UnicodeChar))^,(Size+1)*sizeof(UnicodeChar));
  496. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(UnicodeChar));
  497. end
  498. else
  499. begin
  500. DestS:='';
  501. SetLength(DestS,Size+Location);
  502. Move(Pointer(S1)^,Pointer(DestS)^,Location*sizeof(UnicodeChar));
  503. Move(Pointer(S2)^,(Pointer(DestS)+Location*sizeof(UnicodeChar))^,(Size+1)*sizeof(UnicodeChar));
  504. end;
  505. end;
  506. procedure fpc_UnicodeStr_Concat_multi (var DestS:Unicodestring;const sarr:array of Unicodestring); compilerproc;
  507. Var
  508. i : Longint;
  509. p,pc : pointer;
  510. Size,NewLen : SizeInt;
  511. lowstart : longint;
  512. destcopy : pointer;
  513. OldDestLen : SizeInt;
  514. begin
  515. if high(sarr)=0 then
  516. begin
  517. DestS:='';
  518. exit;
  519. end;
  520. destcopy:=nil;
  521. lowstart:=low(sarr);
  522. if Pointer(DestS)=Pointer(sarr[lowstart]) then
  523. inc(lowstart);
  524. { Check for another reuse, then we can't use
  525. the append optimization }
  526. for i:=lowstart to high(sarr) do
  527. begin
  528. if Pointer(DestS)=Pointer(sarr[i]) then
  529. begin
  530. { if DestS is used somewhere in the middle of the expression,
  531. we need to make sure the original string still exists after
  532. we empty/modify DestS.
  533. This trick only works with reference counted strings. Therefor
  534. this optimization is disabled for WINLIKEUNICODESTRING }
  535. destcopy:=pointer(dests);
  536. fpc_UnicodeStr_Incr_Ref(destcopy);
  537. lowstart:=low(sarr);
  538. break;
  539. end;
  540. end;
  541. { Start with empty DestS if we start with concatting
  542. the first array element }
  543. if lowstart=low(sarr) then
  544. DestS:='';
  545. OldDestLen:=length(DestS);
  546. { Calculate size of the result so we can do
  547. a single call to SetLength() }
  548. NewLen:=0;
  549. for i:=low(sarr) to high(sarr) do
  550. inc(NewLen,length(sarr[i]));
  551. SetLength(DestS,NewLen);
  552. { Concat all strings, except the string we already
  553. copied in DestS }
  554. pc:=Pointer(DestS)+OldDestLen*sizeof(UnicodeChar);
  555. for i:=lowstart to high(sarr) do
  556. begin
  557. p:=pointer(sarr[i]);
  558. if assigned(p) then
  559. begin
  560. Size:=length(unicodestring(p));
  561. Move(p^,pc^,(Size+1)*sizeof(UnicodeChar));
  562. inc(pc,size*sizeof(UnicodeChar));
  563. end;
  564. end;
  565. fpc_UnicodeStr_Decr_Ref(destcopy);
  566. end;
  567. {$endif STR_CONCAT_PROCS}
  568. Function fpc_Char_To_UChar(const c : Char): UnicodeChar; compilerproc;
  569. var
  570. w: unicodestring;
  571. begin
  572. widestringmanager.Ansi2UnicodeMoveProc(@c, w, 1);
  573. fpc_Char_To_UChar:= w[1];
  574. end;
  575. Function fpc_Char_To_UnicodeStr(const c : Char): UnicodeString; compilerproc;
  576. {
  577. Converts a Char to a UnicodeString;
  578. }
  579. begin
  580. Setlength(fpc_Char_To_UnicodeStr,1);
  581. fpc_Char_To_UnicodeStr[1]:=c;
  582. { Terminating Zero }
  583. PUnicodeChar(Pointer(fpc_Char_To_UnicodeStr)+sizeof(UnicodeChar))^:=#0;
  584. end;
  585. Function fpc_UChar_To_Char(const c : UnicodeChar): Char; compilerproc;
  586. {
  587. Converts a UnicodeChar to a Char;
  588. }
  589. var
  590. s: ansistring;
  591. begin
  592. widestringmanager.Unicode2AnsiMoveProc(@c, s, 1);
  593. if length(s)=1 then
  594. fpc_UChar_To_Char:= s[1]
  595. else
  596. fpc_UChar_To_Char:='?';
  597. end;
  598. Function fpc_WChar_To_UnicodeStr(const c : WideChar): UnicodeString; compilerproc;
  599. {
  600. Converts a WideChar to a UnicodeString;
  601. }
  602. begin
  603. Setlength (Result,1);
  604. Result[1]:= c;
  605. end;
  606. Function fpc_Char_To_WChar(const c : Char): WideChar; compilerproc;
  607. var
  608. w: widestring;
  609. begin
  610. widestringmanager.Ansi2WideMoveProc(@c, w, 1);
  611. fpc_Char_To_WChar:= w[1];
  612. end;
  613. Function fpc_WChar_To_Char(const c : WideChar): Char; compilerproc;
  614. {
  615. Converts a WideChar to a Char;
  616. }
  617. var
  618. s: ansistring;
  619. begin
  620. widestringmanager.Wide2AnsiMoveProc(@c, s, 1);
  621. if length(s)=1 then
  622. fpc_WChar_To_Char:= s[1]
  623. else
  624. fpc_WChar_To_Char:='?';
  625. end;
  626. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  627. Function fpc_WChar_To_ShortStr(const c : WideChar): ShortString; compilerproc;
  628. {
  629. Converts a WideChar to a ShortString;
  630. }
  631. var
  632. s: ansistring;
  633. begin
  634. widestringmanager.Wide2AnsiMoveProc(@c, s, 1);
  635. fpc_WChar_To_ShortStr:= s;
  636. end;
  637. {$else FPC_STRTOSHORTSTRINGPROC}
  638. procedure fpc_WChar_To_ShortStr(out res : shortstring;const c : WideChar) compilerproc;
  639. {
  640. Converts a WideChar to a ShortString;
  641. }
  642. var
  643. s: ansistring;
  644. begin
  645. widestringmanager.Wide2AnsiMoveProc(@c,s,1);
  646. res:=s;
  647. end;
  648. {$endif FPC_STRTOSHORTSTRINGPROC}
  649. Function fpc_UChar_To_UnicodeStr(const c : UnicodeChar): UnicodeString; compilerproc;
  650. {
  651. Converts a UnicodeChar to a UnicodeString;
  652. }
  653. begin
  654. Setlength (fpc_UChar_To_UnicodeStr,1);
  655. fpc_UChar_To_UnicodeStr[1]:= c;
  656. end;
  657. Function fpc_UChar_To_AnsiStr(const c : UnicodeChar): AnsiString; compilerproc;
  658. {
  659. Converts a UnicodeChar to a AnsiString;
  660. }
  661. begin
  662. widestringmanager.Unicode2AnsiMoveProc(@c, fpc_UChar_To_AnsiStr, 1);
  663. end;
  664. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  665. Function fpc_UChar_To_ShortStr(const c : UnicodeChar): ShortString; compilerproc;
  666. {
  667. Converts a UnicodeChar to a ShortString;
  668. }
  669. var
  670. s: ansistring;
  671. begin
  672. widestringmanager.Unicode2AnsiMoveProc(@c, s, 1);
  673. fpc_UChar_To_ShortStr:= s;
  674. end;
  675. {$else FPC_STRTOSHORTSTRINGPROC}
  676. procedure fpc_UChar_To_ShortStr(out res : shortstring;const c : UnicodeChar) compilerproc;
  677. {
  678. Converts a UnicodeChar to a ShortString;
  679. }
  680. var
  681. s: ansistring;
  682. begin
  683. widestringmanager.Unicode2AnsiMoveProc(@c,s,1);
  684. res:=s;
  685. end;
  686. {$endif FPC_STRTOSHORTSTRINGPROC}
  687. Function fpc_PChar_To_UnicodeStr(const p : pchar): UnicodeString; compilerproc;
  688. Var
  689. L : SizeInt;
  690. begin
  691. if (not assigned(p)) or (p[0]=#0) Then
  692. begin
  693. fpc_pchar_to_unicodestr := '';
  694. exit;
  695. end;
  696. l:=IndexChar(p^,-1,#0);
  697. widestringmanager.Ansi2UnicodeMoveProc(P,fpc_PChar_To_UnicodeStr,l);
  698. end;
  699. Function fpc_CharArray_To_UnicodeStr(const arr: array of char; zerobased: boolean = true): UnicodeString; compilerproc;
  700. var
  701. i : SizeInt;
  702. begin
  703. if (zerobased) then
  704. begin
  705. if (arr[0]=#0) Then
  706. begin
  707. fpc_chararray_to_unicodestr := '';
  708. exit;
  709. end;
  710. i:=IndexChar(arr,high(arr)+1,#0);
  711. if i = -1 then
  712. i := high(arr)+1;
  713. end
  714. else
  715. i := high(arr)+1;
  716. SetLength(fpc_CharArray_To_UnicodeStr,i);
  717. widestringmanager.Ansi2UnicodeMoveProc (pchar(@arr),fpc_CharArray_To_UnicodeStr,i);
  718. end;
  719. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  720. function fpc_UnicodeCharArray_To_ShortStr(const arr: array of unicodechar; zerobased: boolean = true): shortstring;[public,alias:'FPC_UNICODECHARARRAY_TO_SHORTSTR']; compilerproc;
  721. var
  722. l: longint;
  723. index: longint;
  724. len: byte;
  725. temp: ansistring;
  726. begin
  727. l := high(arr)+1;
  728. if l>=256 then
  729. l:=255
  730. else if l<0 then
  731. l:=0;
  732. if zerobased then
  733. begin
  734. index:=IndexWord(arr[0],l,0);
  735. if (index < 0) then
  736. len := l
  737. else
  738. len := index;
  739. end
  740. else
  741. len := l;
  742. widestringmanager.Unicode2AnsiMoveProc (punicodechar(@arr),temp,len);
  743. fpc_UnicodeCharArray_To_ShortStr := temp;
  744. end;
  745. {$else FPC_STRTOSHORTSTRINGPROC}
  746. procedure fpc_UnicodeCharArray_To_ShortStr(out res : shortstring;const arr: array of unicodechar; zerobased: boolean = true);[public,alias:'FPC_UNICODECHARARRAY_TO_SHORTSTR']; compilerproc;
  747. var
  748. l: longint;
  749. index: ptrint;
  750. len: byte;
  751. temp: ansistring;
  752. begin
  753. l := high(arr)+1;
  754. if l>=high(res)+1 then
  755. l:=high(res)
  756. else if l<0 then
  757. l:=0;
  758. if zerobased then
  759. begin
  760. index:=IndexWord(arr[0],l,0);
  761. if index<0 then
  762. len:=l
  763. else
  764. len:=index;
  765. end
  766. else
  767. len:=l;
  768. widestringmanager.Unicode2AnsiMoveProc (punicodechar(@arr),temp,len);
  769. res:=temp;
  770. end;
  771. {$endif FPC_STRTOSHORTSTRINGPROC}
  772. Function fpc_UnicodeCharArray_To_AnsiStr(const arr: array of unicodechar; zerobased: boolean = true): AnsiString; compilerproc;
  773. var
  774. i : SizeInt;
  775. begin
  776. if (zerobased) then
  777. begin
  778. i:=IndexWord(arr,high(arr)+1,0);
  779. if i = -1 then
  780. i := high(arr)+1;
  781. end
  782. else
  783. i := high(arr)+1;
  784. SetLength(fpc_UnicodeCharArray_To_AnsiStr,i);
  785. widestringmanager.Unicode2AnsiMoveProc (punicodechar(@arr),fpc_UnicodeCharArray_To_AnsiStr,i);
  786. end;
  787. Function fpc_UnicodeCharArray_To_UnicodeStr(const arr: array of unicodechar; zerobased: boolean = true): UnicodeString; compilerproc;
  788. var
  789. i : SizeInt;
  790. begin
  791. if (zerobased) then
  792. begin
  793. i:=IndexWord(arr,high(arr)+1,0);
  794. if i = -1 then
  795. i := high(arr)+1;
  796. end
  797. else
  798. i := high(arr)+1;
  799. SetLength(fpc_UnicodeCharArray_To_UnicodeStr,i);
  800. Move(arr[0], Pointer(fpc_UnicodeCharArray_To_UnicodeStr)^,i*sizeof(UnicodeChar));
  801. end;
  802. Function fpc_WideCharArray_To_UnicodeStr(const arr: array of widechar; zerobased: boolean = true): UnicodeString; compilerproc;
  803. var
  804. i : SizeInt;
  805. begin
  806. if (zerobased) then
  807. begin
  808. i:=IndexWord(arr,high(arr)+1,0);
  809. if i = -1 then
  810. i := high(arr)+1;
  811. end
  812. else
  813. i := high(arr)+1;
  814. SetLength(fpc_WideCharArray_To_UnicodeStr,i);
  815. Move(arr[0], Pointer(fpc_WideCharArray_To_UnicodeStr)^,i*sizeof(WideChar));
  816. end;
  817. { due to their names, the following procedures should be in wstrings.inc,
  818. however, the compiler generates code using this functions on all platforms }
  819. {$ifndef FPC_STRTOSHORTSTRINGPROC}
  820. function fpc_WideCharArray_To_ShortStr(const arr: array of widechar; zerobased: boolean = true): shortstring;[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  821. var
  822. l: longint;
  823. index: longint;
  824. len: byte;
  825. temp: ansistring;
  826. begin
  827. l := high(arr)+1;
  828. if l>=256 then
  829. l:=255
  830. else if l<0 then
  831. l:=0;
  832. if zerobased then
  833. begin
  834. index:=IndexWord(arr[0],l,0);
  835. if (index < 0) then
  836. len := l
  837. else
  838. len := index;
  839. end
  840. else
  841. len := l;
  842. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  843. fpc_WideCharArray_To_ShortStr := temp;
  844. end;
  845. {$else FPC_STRTOSHORTSTRINGPROC}
  846. procedure fpc_WideCharArray_To_ShortStr(out res : shortstring;const arr: array of widechar; zerobased: boolean = true);[public,alias:'FPC_WIDECHARARRAY_TO_SHORTSTR']; compilerproc;
  847. var
  848. l: longint;
  849. index: ptrint;
  850. len: byte;
  851. temp: ansistring;
  852. begin
  853. l := high(arr)+1;
  854. if l>=high(res)+1 then
  855. l:=high(res)
  856. else if l<0 then
  857. l:=0;
  858. if zerobased then
  859. begin
  860. index:=IndexWord(arr[0],l,0);
  861. if index<0 then
  862. len:=l
  863. else
  864. len:=index;
  865. end
  866. else
  867. len:=l;
  868. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),temp,len);
  869. res:=temp;
  870. end;
  871. {$endif FPC_STRTOSHORTSTRINGPROC}
  872. Function fpc_WideCharArray_To_AnsiStr(const arr: array of widechar; zerobased: boolean = true): AnsiString; compilerproc;
  873. var
  874. i : SizeInt;
  875. begin
  876. if (zerobased) then
  877. begin
  878. i:=IndexWord(arr,high(arr)+1,0);
  879. if i = -1 then
  880. i := high(arr)+1;
  881. end
  882. else
  883. i := high(arr)+1;
  884. SetLength(fpc_WideCharArray_To_AnsiStr,i);
  885. widestringmanager.Wide2AnsiMoveProc (pwidechar(@arr),fpc_WideCharArray_To_AnsiStr,i);
  886. end;
  887. Function fpc_WideCharArray_To_WideStr(const arr: array of widechar; zerobased: boolean = true): WideString; compilerproc;
  888. var
  889. i : SizeInt;
  890. begin
  891. if (zerobased) then
  892. begin
  893. i:=IndexWord(arr,high(arr)+1,0);
  894. if i = -1 then
  895. i := high(arr)+1;
  896. end
  897. else
  898. i := high(arr)+1;
  899. SetLength(fpc_WideCharArray_To_WideStr,i);
  900. Move(arr[0], Pointer(fpc_WideCharArray_To_WideStr)^,i*sizeof(WideChar));
  901. end;
  902. {$ifndef FPC_STRTOCHARARRAYPROC}
  903. { inside the compiler, the resulttype is modified to that of the actual }
  904. { chararray we're converting to (JM) }
  905. function fpc_unicodestr_to_chararray(arraysize: SizeInt; const src: UnicodeString): fpc_big_chararray;[public,alias: 'FPC_UNICODESTR_TO_CHARARRAY']; compilerproc;
  906. var
  907. len: SizeInt;
  908. temp: ansistring;
  909. begin
  910. len := length(src);
  911. { make sure we don't dereference src if it can be nil (JM) }
  912. if len > 0 then
  913. widestringmanager.unicode2ansimoveproc(punicodechar(@src[1]),temp,len);
  914. len := length(temp);
  915. if len > arraysize then
  916. len := arraysize;
  917. {$r-}
  918. move(temp[1],fpc_unicodestr_to_chararray[0],len);
  919. fillchar(fpc_unicodestr_to_chararray[len],arraysize-len,0);
  920. {$ifdef RangeCheckWasOn}
  921. {$r+}
  922. {$endif}
  923. end;
  924. { inside the compiler, the resulttype is modified to that of the actual }
  925. { unicodechararray we're converting to (JM) }
  926. function fpc_unicodestr_to_unicodechararray(arraysize: SizeInt; const src: UnicodeString): fpc_big_unicodechararray;[public,alias: 'FPC_UNICODESTR_TO_UNICODECHARARRAY']; compilerproc;
  927. var
  928. len: SizeInt;
  929. begin
  930. len := length(src);
  931. if len > arraysize then
  932. len := arraysize;
  933. {$r-}
  934. { make sure we don't try to access element 1 of the ansistring if it's nil }
  935. if len > 0 then
  936. move(src[1],fpc_unicodestr_to_unicodechararray[0],len*SizeOf(UnicodeChar));
  937. fillchar(fpc_unicodestr_to_unicodechararray[len],(arraysize-len)*SizeOf(UnicodeChar),0);
  938. {$ifdef RangeCheckWasOn}
  939. {$r+}
  940. {$endif}
  941. end;
  942. { inside the compiler, the resulttype is modified to that of the actual }
  943. { chararray we're converting to (JM) }
  944. function fpc_ansistr_to_unicodechararray(arraysize: SizeInt; const src: AnsiString): fpc_big_unicodechararray;[public,alias: 'FPC_ANSISTR_TO_UNICODECHARARRAY']; compilerproc;
  945. var
  946. len: SizeInt;
  947. temp: unicodestring;
  948. begin
  949. len := length(src);
  950. { make sure we don't dereference src if it can be nil (JM) }
  951. if len > 0 then
  952. widestringmanager.ansi2unicodemoveproc(pchar(@src[1]),temp,len);
  953. len := length(temp);
  954. if len > arraysize then
  955. len := arraysize;
  956. {$r-}
  957. move(temp[1],fpc_ansistr_to_unicodechararray[0],len*sizeof(unicodechar));
  958. fillchar(fpc_ansistr_to_unicodechararray[len],(arraysize-len)*SizeOf(UnicodeChar),0);
  959. {$ifdef RangeCheckWasOn}
  960. {$r+}
  961. {$endif}
  962. end;
  963. function fpc_shortstr_to_unicodechararray(arraysize: SizeInt; const src: ShortString): fpc_big_unicodechararray;[public,alias: 'FPC_SHORTSTR_TO_UNICODECHARARRAY']; compilerproc;
  964. var
  965. len: longint;
  966. temp : unicodestring;
  967. begin
  968. len := length(src);
  969. { make sure we don't access char 1 if length is 0 (JM) }
  970. if len > 0 then
  971. widestringmanager.ansi2unicodemoveproc(pchar(@src[1]),temp,len);
  972. len := length(temp);
  973. if len > arraysize then
  974. len := arraysize;
  975. {$r-}
  976. move(temp[1],fpc_shortstr_to_unicodechararray[0],len*sizeof(unicodechar));
  977. fillchar(fpc_shortstr_to_unicodechararray[len],(arraysize-len)*SizeOf(UnicodeChar),0);
  978. {$ifdef RangeCheckWasOn}
  979. {$r+}
  980. {$endif}
  981. end;
  982. {$else ndef FPC_STRTOCHARARRAYPROC}
  983. procedure fpc_unicodestr_to_chararray(out res: array of char; const src: UnicodeString); compilerproc;
  984. var
  985. len: SizeInt;
  986. temp: ansistring;
  987. begin
  988. len := length(src);
  989. { make sure we don't dereference src if it can be nil (JM) }
  990. if len > 0 then
  991. widestringmanager.unicode2ansimoveproc(punicodechar(@src[1]),temp,len);
  992. len := length(temp);
  993. if len > length(res) then
  994. len := length(res);
  995. {$r-}
  996. move(temp[1],res[0],len);
  997. fillchar(res[len],length(res)-len,0);
  998. {$ifdef RangeCheckWasOn}
  999. {$r+}
  1000. {$endif}
  1001. end;
  1002. procedure fpc_unicodestr_to_unicodechararray(out res: array of unicodechar; const src: UnicodeString); compilerproc;
  1003. var
  1004. len: SizeInt;
  1005. begin
  1006. len := length(src);
  1007. if len > length(res) then
  1008. len := length(res);
  1009. {$r-}
  1010. { make sure we don't try to access element 1 of the ansistring if it's nil }
  1011. if len > 0 then
  1012. move(src[1],res[0],len*SizeOf(UnicodeChar));
  1013. fillchar(res[len],(length(res)-len)*SizeOf(UnicodeChar),0);
  1014. {$ifdef RangeCheckWasOn}
  1015. {$r+}
  1016. {$endif}
  1017. end;
  1018. procedure fpc_ansistr_to_unicodechararray(out res: array of unicodechar; const src: AnsiString); compilerproc;
  1019. var
  1020. len: SizeInt;
  1021. temp: unicodestring;
  1022. begin
  1023. len := length(src);
  1024. { make sure we don't dereference src if it can be nil (JM) }
  1025. if len > 0 then
  1026. widestringmanager.ansi2unicodemoveproc(pchar(@src[1]),temp,len);
  1027. len := length(temp);
  1028. if len > length(res) then
  1029. len := length(res);
  1030. {$r-}
  1031. move(temp[1],res[0],len*sizeof(unicodechar));
  1032. fillchar(res[len],(length(res)-len)*SizeOf(UnicodeChar),0);
  1033. {$ifdef RangeCheckWasOn}
  1034. {$r+}
  1035. {$endif}
  1036. end;
  1037. procedure fpc_shortstr_to_unicodechararray(out res: array of unicodechar; const src: ShortString); compilerproc;
  1038. var
  1039. len: longint;
  1040. temp : unicodestring;
  1041. begin
  1042. len := length(src);
  1043. { make sure we don't access char 1 if length is 0 (JM) }
  1044. if len > 0 then
  1045. widestringmanager.ansi2unicodemoveproc(pchar(@src[1]),temp,len);
  1046. len := length(temp);
  1047. if len > length(res) then
  1048. len := length(res);
  1049. {$r-}
  1050. move(temp[1],res[0],len*sizeof(unicodechar));
  1051. fillchar(res[len],(length(res)-len)*SizeOf(UnicodeChar),0);
  1052. {$ifdef RangeCheckWasOn}
  1053. {$r+}
  1054. {$endif}
  1055. end;
  1056. procedure fpc_ansistr_to_widechararray(out res: array of widechar; const src: AnsiString); compilerproc;
  1057. var
  1058. len: SizeInt;
  1059. temp: widestring;
  1060. begin
  1061. len := length(src);
  1062. { make sure we don't dereference src if it can be nil (JM) }
  1063. if len > 0 then
  1064. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  1065. len := length(temp);
  1066. if len > length(res) then
  1067. len := length(res);
  1068. {$r-}
  1069. move(temp[1],res[0],len*sizeof(widechar));
  1070. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  1071. {$ifdef RangeCheckWasOn}
  1072. {$r+}
  1073. {$endif}
  1074. end;
  1075. procedure fpc_shortstr_to_widechararray(out res: array of widechar; const src: ShortString); compilerproc;
  1076. var
  1077. len: longint;
  1078. temp : widestring;
  1079. begin
  1080. len := length(src);
  1081. { make sure we don't access char 1 if length is 0 (JM) }
  1082. if len > 0 then
  1083. widestringmanager.ansi2widemoveproc(pchar(@src[1]),temp,len);
  1084. len := length(temp);
  1085. if len > length(res) then
  1086. len := length(res);
  1087. {$r-}
  1088. move(temp[1],res[0],len*sizeof(widechar));
  1089. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  1090. {$ifdef RangeCheckWasOn}
  1091. {$r+}
  1092. {$endif}
  1093. end;
  1094. procedure fpc_unicodestr_to_widechararray(out res: array of widechar; const src: UnicodeString); compilerproc;
  1095. var
  1096. len: SizeInt;
  1097. begin
  1098. len := length(src);
  1099. if len > length(res) then
  1100. len := length(res);
  1101. {$r-}
  1102. { make sure we don't try to access element 1 of the widestring if it's nil }
  1103. if len > 0 then
  1104. move(src[1],res[0],len*SizeOf(WideChar));
  1105. fillchar(res[len],(length(res)-len)*SizeOf(WideChar),0);
  1106. {$ifdef RangeCheckWasOn}
  1107. {$r+}
  1108. {$endif}
  1109. end;
  1110. {$endif ndef FPC_STRTOCHARARRAYPROC}
  1111. Function fpc_UnicodeStr_Compare(const S1,S2 : UnicodeString): SizeInt;[Public,Alias : 'FPC_UNICODESTR_COMPARE']; compilerproc;
  1112. {
  1113. Compares 2 UnicodeStrings;
  1114. The result is
  1115. <0 if S1<S2
  1116. 0 if S1=S2
  1117. >0 if S1>S2
  1118. }
  1119. Var
  1120. MaxI,Temp : SizeInt;
  1121. begin
  1122. if pointer(S1)=pointer(S2) then
  1123. begin
  1124. fpc_UnicodeStr_Compare:=0;
  1125. exit;
  1126. end;
  1127. Maxi:=Length(S1);
  1128. temp:=Length(S2);
  1129. If MaxI>Temp then
  1130. MaxI:=Temp;
  1131. Temp:=CompareWord(S1[1],S2[1],MaxI);
  1132. if temp=0 then
  1133. temp:=Length(S1)-Length(S2);
  1134. fpc_UnicodeStr_Compare:=Temp;
  1135. end;
  1136. Function fpc_UnicodeStr_Compare_Equal(const S1,S2 : UnicodeString): SizeInt;[Public,Alias : 'FPC_UNICODESTR_COMPARE_EQUAL']; compilerproc;
  1137. {
  1138. Compares 2 UnicodeStrings for equality only;
  1139. The result is
  1140. 0 if S1=S2
  1141. <>0 if S1<>S2
  1142. }
  1143. Var
  1144. MaxI : SizeInt;
  1145. begin
  1146. if pointer(S1)=pointer(S2) then
  1147. exit(0);
  1148. Maxi:=Length(S1);
  1149. If MaxI<>Length(S2) then
  1150. exit(-1)
  1151. else
  1152. exit(CompareWord(S1[1],S2[1],MaxI));
  1153. end;
  1154. Procedure fpc_UnicodeStr_CheckZero(p : pointer);[Public,Alias : 'FPC_UNICODESTR_CHECKZERO']; compilerproc;
  1155. begin
  1156. if p=nil then
  1157. HandleErrorFrame(201,get_frame);
  1158. end;
  1159. Procedure fpc_UnicodeStr_CheckRange(len,index : SizeInt);[Public,Alias : 'FPC_UNICODESTR_RANGECHECK']; compilerproc;
  1160. begin
  1161. if (index>len div 2) or (Index<1) then
  1162. HandleErrorFrame(201,get_frame);
  1163. end;
  1164. Procedure fpc_UnicodeStr_SetLength(Var S : UnicodeString; l : SizeInt);[Public,Alias : 'FPC_UNICODESTR_SETLENGTH']; compilerproc;
  1165. {
  1166. Sets The length of string S to L.
  1167. Makes sure S is unique, and contains enough room.
  1168. }
  1169. Var
  1170. Temp : Pointer;
  1171. movelen: SizeInt;
  1172. begin
  1173. if (l>0) then
  1174. begin
  1175. if Pointer(S)=nil then
  1176. begin
  1177. { Need a complete new string...}
  1178. Pointer(s):=NewUnicodeString(l);
  1179. end
  1180. { windows doesn't support reallocing unicodestrings, this code
  1181. is anyways subject to be removed because unicodestrings shouldn't be
  1182. ref. counted anymore (FK) }
  1183. else
  1184. if (PUnicodeRec(Pointer(S)-UnicodeFirstOff)^.Ref = 1) then
  1185. begin
  1186. Dec(Pointer(S),UnicodeFirstOff);
  1187. if SizeUInt(L*sizeof(UnicodeChar)+UnicodeRecLen)>MemSize(Pointer(S)) then
  1188. reallocmem(pointer(S), L*sizeof(UnicodeChar)+UnicodeRecLen);
  1189. Inc(Pointer(S), UnicodeFirstOff);
  1190. end
  1191. else
  1192. begin
  1193. { Reallocation is needed... }
  1194. Temp:=Pointer(NewUnicodeString(L));
  1195. if Length(S)>0 then
  1196. begin
  1197. if l < succ(length(s)) then
  1198. movelen := l
  1199. { also move terminating null }
  1200. else
  1201. movelen := succ(length(s));
  1202. Move(Pointer(S)^,Temp^,movelen * Sizeof(UnicodeChar));
  1203. end;
  1204. fpc_unicodestr_decr_ref(Pointer(S));
  1205. Pointer(S):=Temp;
  1206. end;
  1207. { Force nil termination in case it gets shorter }
  1208. PWord(Pointer(S)+l*sizeof(UnicodeChar))^:=0;
  1209. PUnicodeRec(Pointer(S)-UnicodeFirstOff)^.Len:=l*sizeof(UnicodeChar);
  1210. end
  1211. else
  1212. begin
  1213. { Length=0 }
  1214. if Pointer(S)<>nil then
  1215. fpc_unicodestr_decr_ref (Pointer(S));
  1216. Pointer(S):=Nil;
  1217. end;
  1218. end;
  1219. {*****************************************************************************
  1220. Public functions, In interface.
  1221. *****************************************************************************}
  1222. function UnicodeCharToString(S : PUnicodeChar) : AnsiString;
  1223. begin
  1224. result:=UnicodeCharLenToString(s,Length(UnicodeString(s)));
  1225. end;
  1226. function StringToUnicodeChar(const Src : AnsiString;Dest : PUnicodeChar;DestSize : SizeInt) : PUnicodeChar;
  1227. var
  1228. temp:unicodestring;
  1229. begin
  1230. widestringmanager.Ansi2UnicodeMoveProc(PChar(Src),temp,Length(Src));
  1231. if Length(temp)<DestSize then
  1232. move(temp[1],Dest^,Length(temp)*SizeOf(UnicodeChar))
  1233. else
  1234. move(temp[1],Dest^,(DestSize-1)*SizeOf(UnicodeChar));
  1235. Dest[DestSize-1]:=#0;
  1236. result:=Dest;
  1237. end;
  1238. function WideCharToString(S : PWideChar) : AnsiString;
  1239. begin
  1240. result:=WideCharLenToString(s,Length(WideString(s)));
  1241. end;
  1242. function StringToWideChar(const Src : AnsiString;Dest : PWideChar;DestSize : SizeInt) : PWideChar;
  1243. var
  1244. temp:widestring;
  1245. begin
  1246. widestringmanager.Ansi2WideMoveProc(PChar(Src),temp,Length(Src));
  1247. if Length(temp)<DestSize then
  1248. move(temp[1],Dest^,Length(temp)*SizeOf(WideChar))
  1249. else
  1250. move(temp[1],Dest^,(DestSize-1)*SizeOf(WideChar));
  1251. Dest[DestSize-1]:=#0;
  1252. result:=Dest;
  1253. end;
  1254. function UnicodeCharLenToString(S : PUnicodeChar;Len : SizeInt) : AnsiString;
  1255. begin
  1256. //SetLength(result,Len);
  1257. widestringmanager.Unicode2AnsiMoveproc(S,result,Len);
  1258. end;
  1259. procedure UnicodeCharLenToStrVar(Src : PUnicodeChar;Len : SizeInt;out Dest : AnsiString);
  1260. begin
  1261. Dest:=UnicodeCharLenToString(Src,Len);
  1262. end;
  1263. procedure UnicodeCharToStrVar(S : PUnicodeChar;out Dest : AnsiString);
  1264. begin
  1265. Dest:=UnicodeCharToString(S);
  1266. end;
  1267. function WideCharLenToString(S : PWideChar;Len : SizeInt) : AnsiString;
  1268. begin
  1269. //SetLength(result,Len);
  1270. widestringmanager.Wide2AnsiMoveproc(S,result,Len);
  1271. end;
  1272. procedure WideCharLenToStrVar(Src : PWideChar;Len : SizeInt;out Dest : AnsiString);
  1273. begin
  1274. Dest:=WideCharLenToString(Src,Len);
  1275. end;
  1276. procedure WideCharToStrVar(S : PWideChar;out Dest : AnsiString);
  1277. begin
  1278. Dest:=WideCharToString(S);
  1279. end;
  1280. Function fpc_unicodestr_Unique(Var S : Pointer): Pointer; [Public,Alias : 'FPC_UNICODESTR_UNIQUE']; compilerproc;
  1281. {
  1282. Make sure reference count of S is 1,
  1283. using copy-on-write semantics.
  1284. }
  1285. Var
  1286. SNew : Pointer;
  1287. L : SizeInt;
  1288. begin
  1289. pointer(result) := pointer(s);
  1290. If Pointer(S)=Nil then
  1291. exit;
  1292. if PUnicodeRec(Pointer(S)-UnicodeFirstOff)^.Ref<>1 then
  1293. begin
  1294. L:=PUnicodeRec(Pointer(S)-UnicodeFirstOff)^.len div sizeof(UnicodeChar);
  1295. SNew:=NewUnicodeString (L);
  1296. Move (PUnicodeChar(S)^,SNew^,(L+1)*sizeof(UnicodeChar));
  1297. PUnicodeRec(SNew-UnicodeFirstOff)^.len:=L * sizeof(UnicodeChar);
  1298. fpc_unicodestr_decr_ref (Pointer(S)); { Thread safe }
  1299. pointer(S):=SNew;
  1300. pointer(result):=SNew;
  1301. end;
  1302. end;
  1303. Function Fpc_UnicodeStr_Copy (Const S : UnicodeString; Index,Size : SizeInt) : UnicodeString;compilerproc;
  1304. var
  1305. ResultAddress : Pointer;
  1306. begin
  1307. ResultAddress:=Nil;
  1308. dec(index);
  1309. if Index < 0 then
  1310. Index := 0;
  1311. { Check Size. Accounts for Zero-length S, the double check is needed because
  1312. Size can be maxint and will get <0 when adding index }
  1313. if (Size>Length(S)) or
  1314. (Index+Size>Length(S)) then
  1315. Size:=Length(S)-Index;
  1316. If Size>0 then
  1317. begin
  1318. If Index<0 Then
  1319. Index:=0;
  1320. ResultAddress:=Pointer(NewUnicodeString (Size));
  1321. if ResultAddress<>Nil then
  1322. begin
  1323. Move (PUnicodeChar(S)[Index],ResultAddress^,Size*sizeof(UnicodeChar));
  1324. PUnicodeRec(ResultAddress-UnicodeFirstOff)^.Len:=Size*sizeof(UnicodeChar);
  1325. PUnicodeChar(ResultAddress+Size*sizeof(UnicodeChar))^:=#0;
  1326. end;
  1327. end;
  1328. fpc_unicodestr_decr_ref(Pointer(fpc_unicodestr_copy));
  1329. Pointer(fpc_unicodestr_Copy):=ResultAddress;
  1330. end;
  1331. Function Pos (Const Substr : UnicodeString; Const Source : UnicodeString) : SizeInt;
  1332. var
  1333. i,MaxLen : SizeInt;
  1334. pc : punicodechar;
  1335. begin
  1336. Pos:=0;
  1337. if Length(SubStr)>0 then
  1338. begin
  1339. MaxLen:=Length(source)-Length(SubStr);
  1340. i:=0;
  1341. pc:=@source[1];
  1342. while (i<=MaxLen) do
  1343. begin
  1344. inc(i);
  1345. if (SubStr[1]=pc^) and
  1346. (CompareWord(Substr[1],pc^,Length(SubStr))=0) then
  1347. begin
  1348. Pos:=i;
  1349. exit;
  1350. end;
  1351. inc(pc);
  1352. end;
  1353. end;
  1354. end;
  1355. { Faster version for a unicodechar alone }
  1356. Function Pos (c : UnicodeChar; Const s : UnicodeString) : SizeInt;
  1357. var
  1358. i: SizeInt;
  1359. pc : punicodechar;
  1360. begin
  1361. pc:=@s[1];
  1362. for i:=1 to length(s) do
  1363. begin
  1364. if pc^=c then
  1365. begin
  1366. pos:=i;
  1367. exit;
  1368. end;
  1369. inc(pc);
  1370. end;
  1371. pos:=0;
  1372. end;
  1373. Function Pos (c : AnsiString; Const s : UnicodeString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1374. begin
  1375. result:=Pos(UnicodeString(c),s);
  1376. end;
  1377. Function Pos (c : ShortString; Const s : UnicodeString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1378. begin
  1379. result:=Pos(UnicodeString(c),s);
  1380. end;
  1381. Function Pos (c : UnicodeString; Const s : AnsiString) : SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1382. begin
  1383. result:=Pos(c,UnicodeString(s));
  1384. end;
  1385. { Faster version for a char alone. Must be implemented because }
  1386. { pos(c: char; const s: shortstring) also exists, so otherwise }
  1387. { using pos(char,pchar) will always call the shortstring version }
  1388. { (exact match for first argument), also with $h+ (JM) }
  1389. Function Pos (c : Char; Const s : UnicodeString) : SizeInt;
  1390. var
  1391. i: SizeInt;
  1392. wc : unicodechar;
  1393. pc : punicodechar;
  1394. begin
  1395. wc:=c;
  1396. pc:=@s[1];
  1397. for i:=1 to length(s) do
  1398. begin
  1399. if pc^=wc then
  1400. begin
  1401. pos:=i;
  1402. exit;
  1403. end;
  1404. inc(pc);
  1405. end;
  1406. pos:=0;
  1407. end;
  1408. Procedure Delete (Var S : UnicodeString; Index,Size: SizeInt);
  1409. Var
  1410. LS : SizeInt;
  1411. begin
  1412. LS:=Length(S);
  1413. if (Index>LS) or (Index<=0) or (Size<=0) then
  1414. exit;
  1415. UniqueString (S);
  1416. { (Size+Index) will overflow if Size=MaxInt. }
  1417. if Size>LS-Index then
  1418. Size:=LS-Index+1;
  1419. if Size<=LS-Index then
  1420. begin
  1421. Dec(Index);
  1422. Move(PUnicodeChar(S)[Index+Size],PUnicodeChar(S)[Index],(LS-Index-Size+1)*sizeof(UnicodeChar));
  1423. end;
  1424. Setlength(s,LS-Size);
  1425. end;
  1426. Procedure Insert (Const Source : UnicodeString; Var S : UnicodeString; Index : SizeInt);
  1427. var
  1428. Temp : UnicodeString;
  1429. LS : SizeInt;
  1430. begin
  1431. If Length(Source)=0 then
  1432. exit;
  1433. if index <= 0 then
  1434. index := 1;
  1435. Ls:=Length(S);
  1436. if index > LS then
  1437. index := LS+1;
  1438. Dec(Index);
  1439. Pointer(Temp) := NewUnicodeString(Length(Source)+LS);
  1440. SetLength(Temp,Length(Source)+LS);
  1441. If Index>0 then
  1442. move (PUnicodeChar(S)^,PUnicodeChar(Temp)^,Index*sizeof(UnicodeChar));
  1443. Move (PUnicodeChar(Source)^,PUnicodeChar(Temp)[Index],Length(Source)*sizeof(UnicodeChar));
  1444. If (LS-Index)>0 then
  1445. Move(PUnicodeChar(S)[Index],PUnicodeChar(temp)[Length(Source)+index],(LS-Index)*sizeof(UnicodeChar));
  1446. S:=Temp;
  1447. end;
  1448. Function UpCase(c:UnicodeChar):UnicodeChar;
  1449. var
  1450. s : UnicodeString;
  1451. begin
  1452. s:=c;
  1453. result:=widestringmanager.UpperUnicodeStringProc(s)[1];
  1454. end;
  1455. function UpCase(const s : UnicodeString) : UnicodeString;
  1456. begin
  1457. result:=widestringmanager.UpperUnicodeStringProc(s);
  1458. end;
  1459. Procedure SetString (Out S : UnicodeString; Buf : PUnicodeChar; Len : SizeInt);
  1460. begin
  1461. SetLength(S,Len);
  1462. If (Buf<>Nil) and (Len>0) then
  1463. Move (Buf[0],S[1],Len*sizeof(UnicodeChar));
  1464. end;
  1465. Procedure SetString (Out S : UnicodeString; Buf : PChar; Len : SizeInt);
  1466. var
  1467. BufLen: SizeInt;
  1468. begin
  1469. SetLength(S,Len);
  1470. If (Buf<>Nil) and (Len>0) then
  1471. widestringmanager.Ansi2UnicodeMoveProc(Buf,S,Len);
  1472. end;
  1473. {$ifndef FPUNONE}
  1474. Function fpc_Val_Real_UnicodeStr(Const S : UnicodeString; out Code : ValSInt): ValReal; [public, alias:'FPC_VAL_REAL_UNICODESTR']; compilerproc;
  1475. Var
  1476. SS : String;
  1477. begin
  1478. fpc_Val_Real_UnicodeStr := 0;
  1479. if length(S) > 255 then
  1480. code := 256
  1481. else
  1482. begin
  1483. SS := S;
  1484. Val(SS,fpc_Val_Real_UnicodeStr,code);
  1485. end;
  1486. end;
  1487. {$endif}
  1488. function fpc_val_enum_unicodestr(str2ordindex:pointer;const s:unicodestring;out code:valsint):longint;compilerproc;
  1489. var ss:shortstring;
  1490. begin
  1491. if length(s)>255 then
  1492. code:=256
  1493. else
  1494. begin
  1495. ss:=s;
  1496. val(ss,fpc_val_enum_unicodestr,code);
  1497. end;
  1498. end;
  1499. Function fpc_Val_Currency_UnicodeStr(Const S : UnicodeString; out Code : ValSInt): Currency; [public, alias:'FPC_VAL_CURRENCY_UNICODESTR']; compilerproc;
  1500. Var
  1501. SS : String;
  1502. begin
  1503. if length(S) > 255 then
  1504. begin
  1505. fpc_Val_Currency_UnicodeStr:=0;
  1506. code := 256;
  1507. end
  1508. else
  1509. begin
  1510. SS := S;
  1511. Val(SS,fpc_Val_Currency_UnicodeStr,code);
  1512. end;
  1513. end;
  1514. Function fpc_Val_UInt_UnicodeStr (Const S : UnicodeString; out Code : ValSInt): ValUInt; [public, alias:'FPC_VAL_UINT_UNICODESTR']; compilerproc;
  1515. Var
  1516. SS : ShortString;
  1517. begin
  1518. fpc_Val_UInt_UnicodeStr := 0;
  1519. if length(S) > 255 then
  1520. code := 256
  1521. else
  1522. begin
  1523. SS := S;
  1524. Val(SS,fpc_Val_UInt_UnicodeStr,code);
  1525. end;
  1526. end;
  1527. Function fpc_Val_SInt_UnicodeStr (DestSize: SizeInt; Const S : UnicodeString; out Code : ValSInt): ValSInt; [public, alias:'FPC_VAL_SINT_UNICODESTR']; compilerproc;
  1528. Var
  1529. SS : ShortString;
  1530. begin
  1531. fpc_Val_SInt_UnicodeStr:=0;
  1532. if length(S)>255 then
  1533. code:=256
  1534. else
  1535. begin
  1536. SS := S;
  1537. fpc_Val_SInt_UnicodeStr := int_Val_SInt_ShortStr(DestSize,SS,Code);
  1538. end;
  1539. end;
  1540. {$ifndef CPU64}
  1541. Function fpc_Val_qword_UnicodeStr (Const S : UnicodeString; out Code : ValSInt): qword; [public, alias:'FPC_VAL_QWORD_UNICODESTR']; compilerproc;
  1542. Var
  1543. SS : ShortString;
  1544. begin
  1545. fpc_Val_qword_UnicodeStr:=0;
  1546. if length(S)>255 then
  1547. code:=256
  1548. else
  1549. begin
  1550. SS := S;
  1551. Val(SS,fpc_Val_qword_UnicodeStr,Code);
  1552. end;
  1553. end;
  1554. Function fpc_Val_int64_UnicodeStr (Const S : UnicodeString; out Code : ValSInt): Int64; [public, alias:'FPC_VAL_INT64_UNICODESTR']; compilerproc;
  1555. Var
  1556. SS : ShortString;
  1557. begin
  1558. fpc_Val_int64_UnicodeStr:=0;
  1559. if length(S)>255 then
  1560. code:=256
  1561. else
  1562. begin
  1563. SS := S;
  1564. Val(SS,fpc_Val_int64_UnicodeStr,Code);
  1565. end;
  1566. end;
  1567. {$endif CPU64}
  1568. {$ifndef FPUNONE}
  1569. procedure fpc_UnicodeStr_Float(d : ValReal;len,fr,rt : SizeInt;out s : UnicodeString);compilerproc;
  1570. var
  1571. ss : shortstring;
  1572. begin
  1573. str_real(len,fr,d,treal_type(rt),ss);
  1574. s:=ss;
  1575. end;
  1576. {$endif}
  1577. procedure fpc_unicodestr_enum(ordinal,len:sizeint;typinfo,ord2strindex:pointer;out s:unicodestring);compilerproc;
  1578. var ss:shortstring;
  1579. begin
  1580. fpc_shortstr_enum(ordinal,len,typinfo,ord2strindex,ss);
  1581. s:=ss;
  1582. end;
  1583. {$ifdef FPC_HAS_STR_CURRENCY}
  1584. procedure fpc_UnicodeStr_Currency(c : Currency;len,fr : SizeInt;out s : UnicodeString);compilerproc;
  1585. var
  1586. ss : shortstring;
  1587. begin
  1588. str(c:len:fr,ss);
  1589. s:=ss;
  1590. end;
  1591. {$endif FPC_HAS_STR_CURRENCY}
  1592. Procedure fpc_UnicodeStr_SInt(v : ValSint; Len : SizeInt; out S : UnicodeString);compilerproc;
  1593. Var
  1594. SS : ShortString;
  1595. begin
  1596. Str (v:Len,SS);
  1597. S:=SS;
  1598. end;
  1599. Procedure fpc_UnicodeStr_UInt(v : ValUInt;Len : SizeInt; out S : UnicodeString);compilerproc;
  1600. Var
  1601. SS : ShortString;
  1602. begin
  1603. str(v:Len,SS);
  1604. S:=SS;
  1605. end;
  1606. {$ifndef CPU64}
  1607. Procedure fpc_UnicodeStr_Int64(v : Int64; Len : SizeInt; out S : UnicodeString);compilerproc;
  1608. Var
  1609. SS : ShortString;
  1610. begin
  1611. Str (v:Len,SS);
  1612. S:=SS;
  1613. end;
  1614. Procedure fpc_UnicodeStr_Qword(v : Qword;Len : SizeInt; out S : UnicodeString);compilerproc;
  1615. Var
  1616. SS : ShortString;
  1617. begin
  1618. str(v:Len,SS);
  1619. S:=SS;
  1620. end;
  1621. {$endif CPU64}
  1622. { converts an utf-16 code point or surrogate pair to utf-32 }
  1623. function utf16toutf32(const S: UnicodeString; const index: SizeInt; out len: longint): UCS4Char; [public, alias: 'FPC_UTF16TOUTF32'];
  1624. var
  1625. w: unicodechar;
  1626. begin
  1627. { UTF-16 points in the range #$0-#$D7FF and #$E000-#$FFFF }
  1628. { are the same in UTF-32 }
  1629. w:=s[index];
  1630. if (w<=#$d7ff) or
  1631. (w>=#$e000) then
  1632. begin
  1633. result:=UCS4Char(w);
  1634. len:=1;
  1635. end
  1636. { valid surrogate pair? }
  1637. else if (w<=#$dbff) and
  1638. { w>=#$d7ff check not needed, checked above }
  1639. (index<length(s)) and
  1640. (s[index+1]>=#$dc00) and
  1641. (s[index+1]<=#$dfff) then
  1642. { convert the surrogate pair to UTF-32 }
  1643. begin
  1644. result:=(UCS4Char(w)-$d800) shl 10 + (UCS4Char(s[index+1])-$dc00) + $10000;
  1645. len:=2;
  1646. end
  1647. else
  1648. { invalid surrogate -> do nothing }
  1649. begin
  1650. result:=UCS4Char(w);
  1651. len:=1;
  1652. end;
  1653. end;
  1654. function UnicodeToUtf8(Dest: PChar; Source: PUnicodeChar; MaxBytes: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1655. begin
  1656. if assigned(Source) then
  1657. Result:=UnicodeToUtf8(Dest,MaxBytes,Source,IndexWord(Source^,-1,0))
  1658. else
  1659. Result:=0;
  1660. end;
  1661. function UnicodeToUtf8(Dest: PChar; MaxDestBytes: SizeUInt; Source: PUnicodeChar; SourceChars: SizeUInt): SizeUInt;
  1662. var
  1663. i,j : SizeUInt;
  1664. w : word;
  1665. lw : longword;
  1666. len : longint;
  1667. begin
  1668. result:=0;
  1669. if source=nil then
  1670. exit;
  1671. i:=0;
  1672. j:=0;
  1673. if assigned(Dest) then
  1674. begin
  1675. while (i<SourceChars) and (j<MaxDestBytes) do
  1676. begin
  1677. w:=word(Source[i]);
  1678. case w of
  1679. 0..$7f:
  1680. begin
  1681. Dest[j]:=char(w);
  1682. inc(j);
  1683. end;
  1684. $80..$7ff:
  1685. begin
  1686. if j+1>=MaxDestBytes then
  1687. break;
  1688. Dest[j]:=char($c0 or (w shr 6));
  1689. Dest[j+1]:=char($80 or (w and $3f));
  1690. inc(j,2);
  1691. end;
  1692. $800..$d7ff,$e000..$ffff:
  1693. begin
  1694. if j+2>=MaxDestBytes then
  1695. break;
  1696. Dest[j]:=char($e0 or (w shr 12));
  1697. Dest[j+1]:=char($80 or ((w shr 6) and $3f));
  1698. Dest[j+2]:=char($80 or (w and $3f));
  1699. inc(j,3);
  1700. end;
  1701. $d800..$dbff:
  1702. {High Surrogates}
  1703. begin
  1704. if j+3>=MaxDestBytes then
  1705. break;
  1706. if (i<sourcechars-1) and
  1707. (word(Source[i+1]) >= $dc00) and
  1708. (word(Source[i+1]) <= $dfff) then
  1709. begin
  1710. lw:=longword(utf16toutf32(Source[i] + Source[i+1], 1, len));
  1711. Dest[j]:=char($f0 or (lw shr 18));
  1712. Dest[j+1]:=char($80 or ((lw shr 12) and $3f));
  1713. Dest[j+2]:=char($80 or ((lw shr 6) and $3f));
  1714. Dest[j+3]:=char($80 or (lw and $3f));
  1715. inc(j,4);
  1716. inc(i);
  1717. end;
  1718. end;
  1719. end;
  1720. inc(i);
  1721. end;
  1722. if j>SizeUInt(MaxDestBytes-1) then
  1723. j:=MaxDestBytes-1;
  1724. Dest[j]:=#0;
  1725. end
  1726. else
  1727. begin
  1728. while i<SourceChars do
  1729. begin
  1730. case word(Source[i]) of
  1731. $0..$7f:
  1732. inc(j);
  1733. $80..$7ff:
  1734. inc(j,2);
  1735. $800..$d7ff,$e000..$ffff:
  1736. inc(j,3);
  1737. $d800..$dbff:
  1738. begin
  1739. if (i<sourcechars-1) and
  1740. (word(Source[i+1]) >= $dc00) and
  1741. (word(Source[i+1]) <= $dfff) then
  1742. begin
  1743. inc(j,4);
  1744. inc(i);
  1745. end;
  1746. end;
  1747. end;
  1748. inc(i);
  1749. end;
  1750. end;
  1751. result:=j+1;
  1752. end;
  1753. function Utf8ToUnicode(Dest: PUnicodeChar; Source: PChar; MaxChars: SizeInt): SizeInt;{$ifdef SYSTEMINLINE}inline;{$endif}
  1754. begin
  1755. if assigned(Source) then
  1756. Result:=Utf8ToUnicode(Dest,MaxChars,Source,strlen(Source))
  1757. else
  1758. Result:=0;
  1759. end;
  1760. function UTF8ToUnicode(Dest: PUnicodeChar; MaxDestChars: SizeUInt; Source: PChar; SourceBytes: SizeUInt): SizeUInt;
  1761. const
  1762. UNICODE_INVALID=63;
  1763. var
  1764. InputUTF8: SizeUInt;
  1765. IBYTE: BYTE;
  1766. OutputUnicode: SizeUInt;
  1767. PRECHAR: SizeUInt;
  1768. TempBYTE: BYTE;
  1769. CharLen: SizeUint;
  1770. LookAhead: SizeUInt;
  1771. UC: SizeUInt;
  1772. begin
  1773. if not assigned(Source) then
  1774. begin
  1775. result:=0;
  1776. exit;
  1777. end;
  1778. result:=SizeUInt(-1);
  1779. InputUTF8:=0;
  1780. OutputUnicode:=0;
  1781. PreChar:=0;
  1782. if Assigned(Dest) Then
  1783. begin
  1784. while (OutputUnicode<MaxDestChars) and (InputUTF8<SourceBytes) do
  1785. begin
  1786. IBYTE:=byte(Source[InputUTF8]);
  1787. if (IBYTE and $80) = 0 then
  1788. begin
  1789. //One character US-ASCII, convert it to unicode
  1790. if IBYTE = 10 then
  1791. begin
  1792. If (PreChar<>13) and FALSE then
  1793. begin
  1794. //Expand to crlf, conform UTF-8.
  1795. //This procedure will break the memory alocation by
  1796. //FPC for the widestring, so never use it. Condition never true due the "and FALSE".
  1797. if OutputUnicode+1<MaxDestChars then
  1798. begin
  1799. Dest[OutputUnicode]:=WideChar(13);
  1800. inc(OutputUnicode);
  1801. Dest[OutputUnicode]:=WideChar(10);
  1802. inc(OutputUnicode);
  1803. PreChar:=10;
  1804. end
  1805. else
  1806. begin
  1807. Dest[OutputUnicode]:=WideChar(13);
  1808. inc(OutputUnicode);
  1809. end;
  1810. end
  1811. else
  1812. begin
  1813. Dest[OutputUnicode]:=WideChar(IBYTE);
  1814. inc(OutputUnicode);
  1815. PreChar:=IBYTE;
  1816. end;
  1817. end
  1818. else
  1819. begin
  1820. Dest[OutputUnicode]:=WideChar(IBYTE);
  1821. inc(OutputUnicode);
  1822. PreChar:=IBYTE;
  1823. end;
  1824. inc(InputUTF8);
  1825. end
  1826. else
  1827. begin
  1828. TempByte:=IBYTE;
  1829. CharLen:=0;
  1830. while (TempBYTE and $80)<>0 do
  1831. begin
  1832. TempBYTE:=(TempBYTE shl 1) and $FE;
  1833. inc(CharLen);
  1834. end;
  1835. //Test for the "CharLen" conforms UTF-8 string
  1836. //This means the 10xxxxxx pattern.
  1837. if SizeUInt(InputUTF8+CharLen-1)>SourceBytes then
  1838. begin
  1839. //Insuficient chars in string to decode
  1840. //UTF-8 array. Fallback to single char.
  1841. CharLen:= 1;
  1842. end;
  1843. for LookAhead := 1 to CharLen-1 do
  1844. begin
  1845. if ((byte(Source[InputUTF8+LookAhead]) and $80)<>$80) or
  1846. ((byte(Source[InputUTF8+LookAhead]) and $40)<>$00) then
  1847. begin
  1848. //Invalid UTF-8 sequence, fallback.
  1849. CharLen:= LookAhead;
  1850. break;
  1851. end;
  1852. end;
  1853. UC:=$FFFF;
  1854. case CharLen of
  1855. 1: begin
  1856. //Not valid UTF-8 sequence
  1857. UC:=UNICODE_INVALID;
  1858. end;
  1859. 2: begin
  1860. //Two bytes UTF, convert it
  1861. UC:=(byte(Source[InputUTF8]) and $1F) shl 6;
  1862. UC:=UC or (byte(Source[InputUTF8+1]) and $3F);
  1863. if UC <= $7F then
  1864. begin
  1865. //Invalid UTF sequence.
  1866. UC:=UNICODE_INVALID;
  1867. end;
  1868. end;
  1869. 3: begin
  1870. //Three bytes, convert it to unicode
  1871. UC:= (byte(Source[InputUTF8]) and $0F) shl 12;
  1872. UC:= UC or ((byte(Source[InputUTF8+1]) and $3F) shl 6);
  1873. UC:= UC or ((byte(Source[InputUTF8+2]) and $3F));
  1874. if (UC <= $7FF) or (UC >= $FFFE) or ((UC >= $D800) and (UC <= $DFFF)) then
  1875. begin
  1876. //Invalid UTF-8 sequence
  1877. UC:= UNICODE_INVALID;
  1878. End;
  1879. end;
  1880. 4: begin
  1881. //Four bytes, convert it to two unicode characters
  1882. UC:= (byte(Source[InputUTF8]) and $07) shl 18;
  1883. UC:= UC or ((byte(Source[InputUTF8+1]) and $3F) shl 12);
  1884. UC:= UC or ((byte(Source[InputUTF8+2]) and $3F) shl 6);
  1885. UC:= UC or ((byte(Source[InputUTF8+3]) and $3F));
  1886. if (UC < $10000) or (UC > $10FFFF) then
  1887. begin
  1888. UC:= UNICODE_INVALID;
  1889. end
  1890. else
  1891. begin
  1892. { only store pair if room }
  1893. dec(UC,$10000);
  1894. if (OutputUnicode<MaxDestChars-1) then
  1895. begin
  1896. Dest[OutputUnicode]:=WideChar(UC shr 10 + $D800);
  1897. inc(OutputUnicode);
  1898. UC:=(UC and $3ff) + $DC00;
  1899. end
  1900. else
  1901. begin
  1902. InputUTF8:= InputUTF8 + CharLen;
  1903. { don't store anything }
  1904. CharLen:=0;
  1905. end;
  1906. end;
  1907. end;
  1908. 5,6,7: begin
  1909. //Invalid UTF8 to unicode conversion,
  1910. //mask it as invalid UNICODE too.
  1911. UC:=UNICODE_INVALID;
  1912. end;
  1913. end;
  1914. if CharLen > 0 then
  1915. begin
  1916. PreChar:=UC;
  1917. Dest[OutputUnicode]:=WideChar(UC);
  1918. inc(OutputUnicode);
  1919. end;
  1920. InputUTF8:= InputUTF8 + CharLen;
  1921. end;
  1922. end;
  1923. Result:=OutputUnicode+1;
  1924. end
  1925. else
  1926. begin
  1927. while (InputUTF8<SourceBytes) do
  1928. begin
  1929. IBYTE:=byte(Source[InputUTF8]);
  1930. if (IBYTE and $80) = 0 then
  1931. begin
  1932. //One character US-ASCII, convert it to unicode
  1933. if IBYTE = 10 then
  1934. begin
  1935. if (PreChar<>13) and FALSE then
  1936. begin
  1937. //Expand to crlf, conform UTF-8.
  1938. //This procedure will break the memory alocation by
  1939. //FPC for the widestring, so never use it. Condition never true due the "and FALSE".
  1940. inc(OutputUnicode,2);
  1941. PreChar:=10;
  1942. end
  1943. else
  1944. begin
  1945. inc(OutputUnicode);
  1946. PreChar:=IBYTE;
  1947. end;
  1948. end
  1949. else
  1950. begin
  1951. inc(OutputUnicode);
  1952. PreChar:=IBYTE;
  1953. end;
  1954. inc(InputUTF8);
  1955. end
  1956. else
  1957. begin
  1958. TempByte:=IBYTE;
  1959. CharLen:=0;
  1960. while (TempBYTE and $80)<>0 do
  1961. begin
  1962. TempBYTE:=(TempBYTE shl 1) and $FE;
  1963. inc(CharLen);
  1964. end;
  1965. //Test for the "CharLen" conforms UTF-8 string
  1966. //This means the 10xxxxxx pattern.
  1967. if SizeUInt(InputUTF8+CharLen-1)>SourceBytes then
  1968. begin
  1969. //Insuficient chars in string to decode
  1970. //UTF-8 array. Fallback to single char.
  1971. CharLen:= 1;
  1972. end;
  1973. for LookAhead := 1 to CharLen-1 do
  1974. begin
  1975. if ((byte(Source[InputUTF8+LookAhead]) and $80)<>$80) or
  1976. ((byte(Source[InputUTF8+LookAhead]) and $40)<>$00) then
  1977. begin
  1978. //Invalid UTF-8 sequence, fallback.
  1979. CharLen:= LookAhead;
  1980. break;
  1981. end;
  1982. end;
  1983. UC:=$FFFF;
  1984. case CharLen of
  1985. 1: begin
  1986. //Not valid UTF-8 sequence
  1987. UC:=UNICODE_INVALID;
  1988. end;
  1989. 2: begin
  1990. //Two bytes UTF, convert it
  1991. UC:=(byte(Source[InputUTF8]) and $1F) shl 6;
  1992. UC:=UC or (byte(Source[InputUTF8+1]) and $3F);
  1993. if UC <= $7F then
  1994. begin
  1995. //Invalid UTF sequence.
  1996. UC:=UNICODE_INVALID;
  1997. end;
  1998. end;
  1999. 3: begin
  2000. //Three bytes, convert it to unicode
  2001. UC:= (byte(Source[InputUTF8]) and $0F) shl 12;
  2002. UC:= UC or ((byte(Source[InputUTF8+1]) and $3F) shl 6);
  2003. UC:= UC or ((byte(Source[InputUTF8+2]) and $3F));
  2004. If (UC <= $7FF) or (UC >= $FFFE) or ((UC >= $D800) and (UC <= $DFFF)) then
  2005. begin
  2006. //Invalid UTF-8 sequence
  2007. UC:= UNICODE_INVALID;
  2008. end;
  2009. end;
  2010. 4: begin
  2011. //Four bytes, convert it to two unicode characters
  2012. UC:= (byte(Source[InputUTF8]) and $07) shl 18;
  2013. UC:= UC or ((byte(Source[InputUTF8+1]) and $3F) shl 12);
  2014. UC:= UC or ((byte(Source[InputUTF8+2]) and $3F) shl 6);
  2015. UC:= UC or ((byte(Source[InputUTF8+3]) and $3F));
  2016. if (UC < $10000) or (UC > $10FFFF) then
  2017. UC:= UNICODE_INVALID
  2018. else
  2019. { extra character character }
  2020. inc(OutputUnicode);
  2021. end;
  2022. 5,6,7: begin
  2023. //Invalid UTF8 to unicode conversion,
  2024. //mask it as invalid UNICODE too.
  2025. UC:=UNICODE_INVALID;
  2026. end;
  2027. end;
  2028. if CharLen > 0 then
  2029. begin
  2030. PreChar:=UC;
  2031. inc(OutputUnicode);
  2032. end;
  2033. InputUTF8:= InputUTF8 + CharLen;
  2034. end;
  2035. end;
  2036. Result:=OutputUnicode+1;
  2037. end;
  2038. end;
  2039. function UTF8Encode(const s : Ansistring) : UTF8String; inline;
  2040. begin
  2041. Result:=UTF8Encode(UnicodeString(s));
  2042. end;
  2043. function UTF8Encode(const s : UnicodeString) : UTF8String;
  2044. var
  2045. i : SizeInt;
  2046. hs : UTF8String;
  2047. begin
  2048. result:='';
  2049. if s='' then
  2050. exit;
  2051. SetLength(hs,length(s)*3);
  2052. i:=UnicodeToUtf8(pchar(hs),length(hs)+1,PUnicodeChar(s),length(s));
  2053. if i>0 then
  2054. begin
  2055. SetLength(hs,i-1);
  2056. result:=hs;
  2057. end;
  2058. end;
  2059. function UTF8Decode(const s : UTF8String): UnicodeString;
  2060. var
  2061. i : SizeInt;
  2062. hs : UnicodeString;
  2063. begin
  2064. result:='';
  2065. if s='' then
  2066. exit;
  2067. SetLength(hs,length(s));
  2068. i:=Utf8ToUnicode(PUnicodeChar(hs),length(hs)+1,pchar(s),length(s));
  2069. if i>0 then
  2070. begin
  2071. SetLength(hs,i-1);
  2072. result:=hs;
  2073. end;
  2074. end;
  2075. function AnsiToUtf8(const s : ansistring): UTF8String;{$ifdef SYSTEMINLINE}inline;{$endif}
  2076. begin
  2077. Result:=Utf8Encode(s);
  2078. end;
  2079. function Utf8ToAnsi(const s : UTF8String) : ansistring;{$ifdef SYSTEMINLINE}inline;{$endif}
  2080. begin
  2081. Result:=Utf8Decode(s);
  2082. end;
  2083. function UnicodeStringToUCS4String(const s : UnicodeString) : UCS4String;
  2084. var
  2085. i, slen,
  2086. destindex : SizeInt;
  2087. len : longint;
  2088. begin
  2089. slen:=length(s);
  2090. setlength(result,slen+1);
  2091. i:=1;
  2092. destindex:=0;
  2093. while (i<=slen) do
  2094. begin
  2095. result[destindex]:=utf16toutf32(s,i,len);
  2096. inc(destindex);
  2097. inc(i,len);
  2098. end;
  2099. { destindex <= slen (surrogate pairs may have been merged) }
  2100. { destindex+1 for terminating #0 (dynamic arrays are }
  2101. { implicitely filled with zero) }
  2102. setlength(result,destindex+1);
  2103. end;
  2104. { concatenates an utf-32 char to a unicodestring. S *must* be unique when entering. }
  2105. procedure ConcatUTF32ToUnicodeStr(const nc: UCS4Char; var S: UnicodeString; var index: SizeInt);
  2106. var
  2107. p : PUnicodeChar;
  2108. begin
  2109. { if nc > $ffff, we need two places }
  2110. if (index+ord(nc > $ffff)>length(s)) then
  2111. if (length(s) < 10*256) then
  2112. setlength(s,length(s)+10)
  2113. else
  2114. setlength(s,length(s)+length(s) shr 8);
  2115. { we know that s is unique -> avoid uniquestring calls}
  2116. p:=@s[index];
  2117. if (nc<$ffff) then
  2118. begin
  2119. p^:=unicodechar(nc);
  2120. inc(index);
  2121. end
  2122. else if (dword(nc)<=$10ffff) then
  2123. begin
  2124. p^:=unicodechar((nc - $10000) shr 10 + $d800);
  2125. (p+1)^:=unicodechar((nc - $10000) and $3ff + $dc00);
  2126. inc(index,2);
  2127. end
  2128. else
  2129. { invalid code point }
  2130. begin
  2131. p^:='?';
  2132. inc(index);
  2133. end;
  2134. end;
  2135. function UCS4StringToUnicodeString(const s : UCS4String) : UnicodeString;
  2136. var
  2137. i : SizeInt;
  2138. resindex : SizeInt;
  2139. begin
  2140. { skip terminating #0 }
  2141. SetLength(result,length(s)-1);
  2142. resindex:=1;
  2143. for i:=0 to high(s)-1 do
  2144. ConcatUTF32ToUnicodeStr(s[i],result,resindex);
  2145. { adjust result length (may be too big due to growing }
  2146. { for surrogate pairs) }
  2147. setlength(result,resindex-1);
  2148. end;
  2149. function WideStringToUCS4String(const s : WideString) : UCS4String;
  2150. var
  2151. i, slen,
  2152. destindex : SizeInt;
  2153. len : longint;
  2154. begin
  2155. slen:=length(s);
  2156. setlength(result,slen+1);
  2157. i:=1;
  2158. destindex:=0;
  2159. while (i<=slen) do
  2160. begin
  2161. result[destindex]:=utf16toutf32(s,i,len);
  2162. inc(destindex);
  2163. inc(i,len);
  2164. end;
  2165. { destindex <= slen (surrogate pairs may have been merged) }
  2166. { destindex+1 for terminating #0 (dynamic arrays are }
  2167. { implicitely filled with zero) }
  2168. setlength(result,destindex+1);
  2169. end;
  2170. { concatenates an utf-32 char to a widestring. S *must* be unique when entering. }
  2171. procedure ConcatUTF32ToWideStr(const nc: UCS4Char; var S: WideString; var index: SizeInt);
  2172. var
  2173. p : PWideChar;
  2174. begin
  2175. { if nc > $ffff, we need two places }
  2176. if (index+ord(nc > $ffff)>length(s)) then
  2177. if (length(s) < 10*256) then
  2178. setlength(s,length(s)+10)
  2179. else
  2180. setlength(s,length(s)+length(s) shr 8);
  2181. { we know that s is unique -> avoid uniquestring calls}
  2182. p:=@s[index];
  2183. if (nc<$ffff) then
  2184. begin
  2185. p^:=widechar(nc);
  2186. inc(index);
  2187. end
  2188. else if (dword(nc)<=$10ffff) then
  2189. begin
  2190. p^:=widechar((nc - $10000) shr 10 + $d800);
  2191. (p+1)^:=widechar((nc - $10000) and $3ff + $dc00);
  2192. inc(index,2);
  2193. end
  2194. else
  2195. { invalid code point }
  2196. begin
  2197. p^:='?';
  2198. inc(index);
  2199. end;
  2200. end;
  2201. function UCS4StringToWideString(const s : UCS4String) : WideString;
  2202. var
  2203. i : SizeInt;
  2204. resindex : SizeInt;
  2205. begin
  2206. { skip terminating #0 }
  2207. SetLength(result,length(s)-1);
  2208. resindex:=1;
  2209. for i:=0 to high(s)-1 do
  2210. ConcatUTF32ToWideStr(s[i],result,resindex);
  2211. { adjust result length (may be too big due to growing }
  2212. { for surrogate pairs) }
  2213. setlength(result,resindex-1);
  2214. end;
  2215. const
  2216. SNoUnicodestrings = 'This binary has no unicodestrings support compiled in.';
  2217. SRecompileWithUnicodestrings = 'Recompile the application with a unicodestrings-manager in the program uses clause.';
  2218. procedure unimplementedunicodestring;
  2219. begin
  2220. {$ifdef FPC_HAS_FEATURE_CONSOLEIO}
  2221. If IsConsole then
  2222. begin
  2223. Writeln(StdErr,SNoUnicodestrings);
  2224. Writeln(StdErr,SRecompileWithUnicodestrings);
  2225. end;
  2226. {$endif FPC_HAS_FEATURE_CONSOLEIO}
  2227. HandleErrorFrame(233,get_frame);
  2228. end;
  2229. {$warnings off}
  2230. function GenericUnicodeCase(const s : UnicodeString) : UnicodeString;
  2231. begin
  2232. unimplementedunicodestring;
  2233. end;
  2234. function CompareUnicodeString(const s1, s2 : UnicodeString) : PtrInt;
  2235. begin
  2236. unimplementedunicodestring;
  2237. end;
  2238. function CompareTextUnicodeString(const s1, s2 : UnicodeString): PtrInt;
  2239. begin
  2240. unimplementedunicodestring;
  2241. end;
  2242. function CharLengthPChar(const Str: PChar): PtrInt;
  2243. begin
  2244. unimplementedunicodestring;
  2245. end;
  2246. {$warnings on}
  2247. procedure initunicodestringmanager;
  2248. begin
  2249. {$ifndef HAS_WIDESTRINGMANAGER}
  2250. widestringmanager.Unicode2AnsiMoveProc:=@defaultUnicode2AnsiMove;
  2251. widestringmanager.Ansi2UnicodeMoveProc:=@defaultAnsi2UnicodeMove;
  2252. widestringmanager.UpperUnicodeStringProc:=@GenericUnicodeCase;
  2253. widestringmanager.LowerUnicodeStringProc:=@GenericUnicodeCase;
  2254. {$endif HAS_WIDESTRINGMANAGER}
  2255. widestringmanager.CompareUnicodeStringProc:=@CompareUnicodeString;
  2256. widestringmanager.CompareTextUnicodeStringProc:=@CompareTextUnicodeString;
  2257. {$ifdef FPC_WIDESTRING_EQUAL_UNICODESTRING}
  2258. {$ifndef HAS_WIDESTRINGMANAGER}
  2259. widestringmanager.Wide2AnsiMoveProc:=@defaultUnicode2AnsiMove;
  2260. widestringmanager.Ansi2WideMoveProc:=@defaultAnsi2UnicodeMove;
  2261. widestringmanager.UpperWideStringProc:=@GenericUnicodeCase;
  2262. widestringmanager.LowerWideStringProc:=@GenericUnicodeCase;
  2263. {$endif HAS_WIDESTRINGMANAGER}
  2264. widestringmanager.CompareWideStringProc:=@CompareUnicodeString;
  2265. widestringmanager.CompareTextWideStringProc:=@CompareTextUnicodeString;
  2266. widestringmanager.CharLengthPCharProc:=@CharLengthPChar;
  2267. {$endif FPC_WIDESTRING_EQUAL_UNICODESTRING}
  2268. end;