2
0

stringbuilder.bmx 14 KB

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