stringbuilder.bmx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. ' Copyright (c) 2018 Bruce A Henderson
  2. '
  3. ' This software is provided 'as-is', without any express or implied
  4. ' warranty. In no event will the authors be held liable for any damages
  5. ' arising from the use of this software.
  6. '
  7. ' Permission is granted to anyone to use this software for any purpose,
  8. ' including commercial applications, and to alter it and redistribute it
  9. ' freely, subject to the following restrictions:
  10. '
  11. ' 1. The origin of this software must not be misrepresented; you must not
  12. ' claim that you wrote the original software. If you use this software
  13. ' in a product, an acknowledgment in the product documentation would be
  14. ' appreciated but is not required.
  15. ' 2. Altered source versions must be plainly marked as such, and must not be
  16. ' misrepresented as being the original software.
  17. ' 3. This notice may not be removed or altered from any source distribution.
  18. '
  19. SuperStrict
  20. Rem
  21. bbdoc: A string builder.
  22. End Rem
  23. Module BRL.StringBuilder
  24. ModuleInfo "Version: 1.04"
  25. ModuleInfo "License: zlib/libpng"
  26. ModuleInfo "Copyright: 2018 Bruce A Henderson"
  27. ModuleInfo "History: 1.04"
  28. ModuleInfo "History: Added shorts appender."
  29. ModuleInfo "History: 1.03"
  30. ModuleInfo "History: Added overloaded constructor for providing instance specific initial capacity."
  31. ModuleInfo "History: 1.02"
  32. ModuleInfo "History: Added AppendCString() and AppendUTF8String() methods."
  33. ModuleInfo "History: 1.01"
  34. ModuleInfo "History: Added CharAt(), SetCharAt() and RemoveCharAt() methods."
  35. ModuleInfo "History: 1.00 Initial Release"
  36. Import "common.bmx"
  37. Rem
  38. bbdoc: A modifiable String.
  39. about: A string builder provides functionality to efficiently insert, replace, remove, append and reverse.
  40. It is an order of magnitude faster to append Strings to a TStringBuilder than it is to append Strings to Strings.
  41. End Rem
  42. Type TStringBuilder
  43. ?bmxng
  44. Private
  45. ?
  46. ' the char buffer
  47. Field buffer:Byte Ptr
  48. Field newLine:String
  49. Field nullText:String
  50. Global initialCapacity:Int = 16
  51. ?win32
  52. Const NEW_LINE:String = "~r~n"
  53. ?Not win32
  54. Const NEW_LINE:String = "~n"
  55. ?
  56. ?bmxng
  57. Public
  58. ?
  59. Method New()
  60. buffer = bmx_stringbuilder_new(initialCapacity)
  61. End Method
  62. ?bmxng
  63. Method New(initialCapacity:Int)
  64. buffer = bmx_stringbuilder_new(initialCapacity)
  65. End Method
  66. ?
  67. Rem
  68. bbdoc: Constructs a string builder initialized to the contents of the specified string.
  69. End Rem
  70. Function Create:TStringBuilder(Text:String)
  71. ?Not bmxng
  72. Local this:TStringBuilder = New TStringBuilder
  73. ?bmxng
  74. Local this:TStringBuilder
  75. If Text.length > initialCapacity Then
  76. this = New TStringBuilder(Text.length)
  77. Else
  78. this = New TStringBuilder
  79. End If
  80. ?
  81. Return this.Append(Text)
  82. End Function
  83. Rem
  84. bbdoc: Returns the length of the string the string builder would create.
  85. End Rem
  86. Method Length:Int()
  87. Return bmx_stringbuilder_count(buffer)
  88. End Method
  89. Rem
  90. bbdoc: Returns the total number of characters that the string builder can accommodate before needing to grow.
  91. End Rem
  92. Method Capacity:Int()
  93. Return bmx_stringbuilder_capacity(buffer)
  94. End Method
  95. Rem
  96. bbdoc: Sets the length of the string builder.
  97. about: If the length is less than the current length, the current text will be truncated. Otherwise,
  98. the capacity will be increased as necessary, although the actual length of text will remain the same.
  99. End Rem
  100. Method SetLength(length:Int)
  101. bmx_stringbuilder_setlength(buffer, length)
  102. End Method
  103. Rem
  104. bbdoc: Appends the text onto the string builder.
  105. End Rem
  106. Method Append:TStringBuilder(value:String)
  107. bmx_stringbuilder_append_string(buffer, value)
  108. Return Self
  109. End Method
  110. Rem
  111. bbdoc: Appends a byte value to the string builder.
  112. End Rem
  113. Method AppendByte:TStringBuilder(value:Byte)
  114. bmx_stringbuilder_append_byte(buffer, value)
  115. Return Self
  116. End Method
  117. Rem
  118. bbdoc: Appends an object onto the string builder.
  119. about: This generally calls the object's ToString() method.
  120. TStringBuilder objects are simply mem-copied.
  121. End Rem
  122. Method AppendObject:TStringBuilder(obj:Object)
  123. If TStringBuilder(obj) Then
  124. bmx_stringbuilder_append_stringbuffer(buffer, TStringBuilder(obj).buffer)
  125. Else
  126. If obj Then
  127. bmx_stringbuilder_append_string(buffer, obj.ToString())
  128. Else
  129. Return AppendNull()
  130. End If
  131. End If
  132. Return Self
  133. End Method
  134. Rem
  135. bbdoc: Appends a null-terminated C string onto the string builder.
  136. End Rem
  137. Method AppendCString:TStringBuilder(chars:Byte Ptr)
  138. bmx_stringbuilder_append_cstring(buffer, chars)
  139. Return Self
  140. End Method
  141. Rem
  142. bbdoc: Appends a double value to the string builder.
  143. End Rem
  144. Method AppendDouble:TStringBuilder(value:Double)
  145. bmx_stringbuilder_append_double(buffer, value)
  146. Return Self
  147. End Method
  148. Rem
  149. bbdoc: Appends a float value to the string builder.
  150. End Rem
  151. Method AppendFloat:TStringBuilder(value:Float)
  152. bmx_stringbuilder_append_float(buffer, value)
  153. Return Self
  154. End Method
  155. Rem
  156. bbdoc: Appends a int value to the string builder.
  157. End Rem
  158. Method AppendInt:TStringBuilder(value:Int)
  159. bmx_stringbuilder_append_int(buffer, value)
  160. Return Self
  161. End Method
  162. Rem
  163. bbdoc: Appends a Long value to the string builder.
  164. End Rem
  165. Method AppendLong:TStringBuilder(value:Long)
  166. bmx_stringbuilder_append_long(buffer, value)
  167. Return Self
  168. End Method
  169. Rem
  170. bbdoc: Appends the new line string to the string builder.
  171. about: The new line string can be altered using #SetNewLineText. This might be used to force the output to always use Unix line endings even when on Windows.
  172. End Rem
  173. Method AppendNewLine:TStringBuilder()
  174. If newLine Then
  175. bmx_stringbuilder_append_string(buffer, newLine)
  176. Else
  177. bmx_stringbuilder_append_string(buffer, NEW_LINE)
  178. End If
  179. Return Self
  180. End Method
  181. Rem
  182. bbdoc: Appends the text representing null to the string builder.
  183. End Rem
  184. Method AppendNull:TStringBuilder()
  185. If nullText Then
  186. bmx_stringbuilder_append_string(buffer, nullText)
  187. End If
  188. Return Self
  189. End Method
  190. Rem
  191. bbdoc: Appends a Short value to the string builder.
  192. End Rem
  193. Method AppendShort:TStringBuilder(value:Short)
  194. bmx_stringbuilder_append_short(buffer, value)
  195. Return Self
  196. End Method
  197. ?bmxng
  198. Rem
  199. bbdoc: Appends a UInt value to the string builder.
  200. End Rem
  201. Method AppendUInt:TStringBuilder(value:UInt)
  202. bmx_stringbuilder_append_uint(buffer, value)
  203. Return Self
  204. End Method
  205. Rem
  206. bbdoc: Appends a Ulong value to the string builder.
  207. End Rem
  208. Method AppendULong:TStringBuilder(value:ULong)
  209. bmx_stringbuilder_append_ulong(buffer, value)
  210. Return Self
  211. End Method
  212. Rem
  213. bbdoc: Appends a Size_T value to the string builder.
  214. End Rem
  215. Method AppendSizet:TStringBuilder(value:Size_T)
  216. bmx_stringbuilder_append_sizet(buffer, value)
  217. Return Self
  218. End Method
  219. ?
  220. Rem
  221. bbdoc: Appends a null-terminated UTF-8 string onto the string builder.
  222. End Rem
  223. Method AppendUTF8String:TStringBuilder(chars:Byte Ptr)
  224. bmx_stringbuilder_append_utf8string(buffer, chars)
  225. Return Self
  226. End Method
  227. Rem
  228. bbdoc: Appends an array of shorts onto the string builder.
  229. End Rem
  230. Method AppendShorts:TStringBuilder(shorts:Short Ptr, length:Int)
  231. bmx_stringbuilder_append_shorts(buffer, shorts, length)
  232. Return Self
  233. End Method
  234. Rem
  235. bbdoc: Finds first occurance of a sub string.
  236. returns: -1 if @subString not found.
  237. End Rem
  238. Method Find:Int(subString:String, startIndex:Int = 0)
  239. Return bmx_stringbuilder_find(buffer, subString, startIndex)
  240. End Method
  241. Rem
  242. bbdoc: Finds last occurance of a sub string.
  243. returns: -1 if @subString not found.
  244. End Rem
  245. Method FindLast:Int(subString:String, startIndex:Int = 0)
  246. Return bmx_stringbuilder_findlast(buffer, subString, startIndex)
  247. End Method
  248. Rem
  249. bbdoc: Extracts the leftmost characters from the string builder.
  250. about: This method extracts the left @length characters from the builder. If this many characters are not available, the whole builder is returned.
  251. Thus the returned string may be shorter than the length requested.
  252. End Rem
  253. Method Left:String(length:Int)
  254. Return bmx_stringbuilder_left(buffer, length)
  255. End Method
  256. Rem
  257. bbdoc: Removes leading and trailing non-printable characters from the string builder.
  258. End Rem
  259. Method Trim:TStringBuilder()
  260. bmx_stringbuilder_trim(buffer)
  261. Return Self
  262. End Method
  263. Rem
  264. bbdoc: Replaces all occurances of @subString with @withString.
  265. End Rem
  266. Method Replace:TStringBuilder(subString:String, withString:String)
  267. bmx_stringbuilder_replace(buffer, subString, withString)
  268. Return Self
  269. End Method
  270. Rem
  271. bbdoc: Returns true if string starts with @subString.
  272. End Rem
  273. Method StartsWith:Int(subString:String)
  274. Return bmx_stringbuilder_startswith(buffer, subString)
  275. End Method
  276. Rem
  277. bbdoc: Returns true if string ends with @subString.
  278. End Rem
  279. Method EndsWith:Int(subString:String)
  280. Return bmx_stringbuilder_endswith(buffer, subString)
  281. End Method
  282. Rem
  283. bbdoc: Returns the char value in the buffer at the specified index.
  284. about: The first char value is at index 0, the next at index 1, and so on, as in array indexing.
  285. @index must be greater than or equal to 0, and less than the length of the buffer.
  286. End Rem
  287. Method CharAt:Int(index:Int)
  288. Return bmx_stringbuilder_charat(buffer, index)
  289. End Method
  290. Rem
  291. bbdoc: Returns true if string contains @subString.
  292. End Rem
  293. Method Contains:Int(subString:String)
  294. Return Find(subString) >= 0
  295. End Method
  296. Rem
  297. bbdoc: Joins @bits together by inserting this string builder between each bit.
  298. returns: A new TStringBuilder object.
  299. End Rem
  300. Method Join:TStringBuilder(bits:String[])
  301. Local buf:TStringBuilder = New TStringBuilder
  302. bmx_stringbuilder_join(buffer, bits, buf.buffer)
  303. Return buf
  304. End Method
  305. Rem
  306. bbdoc: Converts all of the characters in the buffer to lower case.
  307. End Rem
  308. Method ToLower:TStringBuilder()
  309. bmx_stringbuilder_tolower(buffer)
  310. Return Self
  311. End Method
  312. Rem
  313. bbdoc: Converts all of the characters in the buffer to upper case.
  314. End Rem
  315. Method ToUpper:TStringBuilder()
  316. bmx_stringbuilder_toupper(buffer)
  317. Return Self
  318. End Method
  319. Rem
  320. bbdoc: Removes a range of characters from the string builder.
  321. about: @startIndex is the first character to remove. @endIndex is the index after the last character to remove.
  322. End Rem
  323. Method Remove:TStringBuilder(startIndex:Int, endIndex:Int)
  324. bmx_stringbuilder_remove(buffer, startIndex, endIndex)
  325. Return Self
  326. End Method
  327. Rem
  328. bbdoc: Removes the character at the specified position in the buffer.
  329. about: The buffer is shortened by one character.
  330. End Rem
  331. Method RemoveCharAt:TStringBuilder(index:Int)
  332. bmx_stringbuilder_removecharat(buffer, index)
  333. Return Self
  334. End Method
  335. Rem
  336. bbdoc: Inserts text into the string builder at the specified offset.
  337. End Rem
  338. Method Insert:TStringBuilder(offset:Int, value:String)
  339. bmx_stringbuilder_insert(buffer, offset, value)
  340. Return Self
  341. End Method
  342. Rem
  343. bbdoc: Reverses the characters of the string builder.
  344. End Rem
  345. Method Reverse:TStringBuilder()
  346. bmx_stringbuilder_reverse(buffer)
  347. Return Self
  348. End Method
  349. Rem
  350. bbdoc: Extracts the rightmost characters from the string builder.
  351. about: This method extracts the right @length characters from the builder. If this many characters are not available, the whole builder is returned.
  352. Thus the returned string may be shorter than the length requested.
  353. End Rem
  354. Method Right:String(length:Int)
  355. Return bmx_stringbuilder_right(buffer, length)
  356. End Method
  357. Rem
  358. bbdoc: The character at the specified index is set to @char.
  359. about: @index must be greater than or equal to 0, and less than the length of the buffer.
  360. End Rem
  361. Method SetCharAt(index:Int, char:Int)
  362. bmx_stringbuilder_setcharat(buffer, index, char)
  363. End Method
  364. Rem
  365. bbdoc: Sets the text to be appended when a new line is added.
  366. End Rem
  367. Method SetNewLineText:TStringBuilder(newLine:String)
  368. Self.newLine = newLine
  369. Return Self
  370. End Method
  371. Rem
  372. bbdoc: Sets the text to be appended when null is added.
  373. End Rem
  374. Method SetNullText:TStringBuilder(nullText:String)
  375. Self.nullText = nullText
  376. Return Self
  377. End Method
  378. Rem
  379. bbdoc: Returns a substring of the string builder given the specified indexes.
  380. about: @beginIndex is the first character of the substring.
  381. @endIndex is the index after the last character of the substring. If @endIndex is zero,
  382. will return everything from @beginIndex until the end of the string builder.
  383. End Rem
  384. Method Substring:String(beginIndex:Int, endIndex:Int = 0)
  385. Return bmx_stringbuilder_substring(buffer, beginIndex, endIndex)
  386. End Method
  387. Rem
  388. bbdoc:
  389. End Rem
  390. Method Split:TSplitBuffer(separator:String)
  391. Local buf:TSplitBuffer = New TSplitBuffer
  392. buf.buffer = Self
  393. buf.splitPtr = bmx_stringbuilder_split(buffer, separator)
  394. Return buf
  395. End Method
  396. Rem
  397. bbdoc: Converts the string builder to a String.
  398. End Rem
  399. Method ToString:String() Override
  400. Return bmx_stringbuilder_tostring(buffer)
  401. End Method
  402. Method Delete()
  403. If buffer Then
  404. bmx_stringbuilder_free(buffer)
  405. buffer = Null
  406. End If
  407. End Method
  408. End Type
  409. Rem
  410. bbdoc: An array of split text from a TStringBuilder.
  411. about: Note that the TSplitBuffer is only valid while its parent TStringBuilder is unchanged.
  412. Once you modify the TStringBuffer you should call Split() again.
  413. End Rem
  414. Type TSplitBuffer
  415. Field buffer:TStringBuilder
  416. Field splitPtr:Byte Ptr
  417. Rem
  418. bbdoc: The number of split elements.
  419. End Rem
  420. Method Length:Int()
  421. Return bmx_stringbuilder_splitbuffer_length(splitPtr)
  422. End Method
  423. Rem
  424. bbdoc: Returns the text for the given index in the split buffer.
  425. End Rem
  426. Method Text:String(index:Int)
  427. Return bmx_stringbuilder_splitbuffer_text(splitPtr, index)
  428. End Method
  429. Rem
  430. bbdoc: Creates a new string array of all the split elements.
  431. End Rem
  432. Method ToArray:String[]()
  433. Return bmx_stringbuilder_splitbuffer_toarray(splitPtr)
  434. End Method
  435. Method ObjectEnumerator:TSplitBufferEnum()
  436. Local enum:TSplitBufferEnum = New TSplitBufferEnum
  437. enum.buffer = Self
  438. enum.length = Length()
  439. Return enum
  440. End Method
  441. Method Delete()
  442. If splitPtr Then
  443. buffer = Null
  444. bmx_stringbuilder_splitbuffer_free(splitPtr)
  445. splitPtr = Null
  446. End If
  447. End Method
  448. End Type
  449. Type TSplitBufferEnum
  450. Field index:Int
  451. Field length:Int
  452. Field buffer:TSplitBuffer
  453. Method HasNext:Int()
  454. Return index < length
  455. End Method
  456. Method NextObject:Object()
  457. Local s:String = buffer.Text(index)
  458. index :+ 1
  459. Return s
  460. End Method
  461. End Type