strings.odin 47 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948
  1. // simple procedures to manipulate UTF-8 encoded strings
  2. package strings
  3. import "core:io"
  4. import "core:mem"
  5. import "core:slice"
  6. import "core:unicode"
  7. import "core:unicode/utf8"
  8. // returns a clone of the string `s` allocated using the `allocator`
  9. clone :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> string {
  10. c := make([]byte, len(s), allocator, loc)
  11. copy(c, s)
  12. return string(c[:len(s)])
  13. }
  14. // returns a clone of the string `s` allocated using the `allocator`
  15. clone_safe :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (str: string, err: mem.Allocator_Error) {
  16. c := make([]byte, len(s), allocator, loc) or_return
  17. copy(c, s)
  18. return string(c[:len(s)]), nil
  19. }
  20. // returns a clone of the string `s` allocated using the `allocator` as a cstring
  21. // a nul byte is appended to the clone, to make the cstring safe
  22. clone_to_cstring :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> cstring {
  23. c := make([]byte, len(s)+1, allocator, loc)
  24. copy(c, s)
  25. c[len(s)] = 0
  26. return cstring(&c[0])
  27. }
  28. // returns a string from a byte pointer `ptr` and byte length `len`
  29. // the string is valid as long as the parameters stay alive
  30. string_from_ptr :: proc(ptr: ^byte, len: int) -> string {
  31. return transmute(string)mem.Raw_String{ptr, len}
  32. }
  33. // returns a string from a byte pointer `ptr and byte length `len`
  34. // searches for a nul byte from 0..<len, otherwhise `len` will be the end size
  35. string_from_nul_terminated_ptr :: proc(ptr: ^byte, len: int) -> string {
  36. s := transmute(string)mem.Raw_String{ptr, len}
  37. s = truncate_to_byte(s, 0)
  38. return s
  39. }
  40. // returns the raw ^byte start of the string `str`
  41. ptr_from_string :: proc(str: string) -> ^byte {
  42. d := transmute(mem.Raw_String)str
  43. return d.data
  44. }
  45. // returns the transmute of string `str` to a cstring
  46. // not safe since the origin string may not contain a nul byte
  47. unsafe_string_to_cstring :: proc(str: string) -> cstring {
  48. d := transmute(mem.Raw_String)str
  49. return cstring(d.data)
  50. }
  51. // returns a string truncated to the first time it finds the byte `b`
  52. // uses the `len` of the string `str` when it couldn't find the input
  53. truncate_to_byte :: proc(str: string, b: byte) -> string {
  54. n := index_byte(str, b)
  55. if n < 0 {
  56. n = len(str)
  57. }
  58. return str[:n]
  59. }
  60. // returns a string truncated to the first time it finds the rune `r`
  61. // uses the `len` of the string `str` when it couldn't find the input
  62. truncate_to_rune :: proc(str: string, r: rune) -> string {
  63. n := index_rune(str, r)
  64. if n < 0 {
  65. n = len(str)
  66. }
  67. return str[:n]
  68. }
  69. // returns a cloned string of the byte array `s` using the `allocator`
  70. // appends a leading nul byte
  71. clone_from_bytes :: proc(s: []byte, allocator := context.allocator, loc := #caller_location) -> string {
  72. c := make([]byte, len(s)+1, allocator, loc)
  73. copy(c, s)
  74. c[len(s)] = 0
  75. return string(c[:len(s)])
  76. }
  77. // returns a clone of the cstring `s` using the `allocator` as a string
  78. clone_from_cstring :: proc(s: cstring, allocator := context.allocator, loc := #caller_location) -> string {
  79. return clone(string(s), allocator, loc)
  80. }
  81. // returns a cloned string from the pointer `ptr` and a byte length `len` using the `allocator`
  82. // same to `string_from_ptr` but allocates
  83. clone_from_ptr :: proc(ptr: ^byte, len: int, allocator := context.allocator, loc := #caller_location) -> string {
  84. s := string_from_ptr(ptr, len)
  85. return clone(s, allocator, loc)
  86. }
  87. // overload to clone from a `string`, `[]byte`, `cstring` or a `^byte + length` to a string
  88. clone_from :: proc{
  89. clone,
  90. clone_from_bytes,
  91. clone_from_cstring,
  92. clone_from_ptr,
  93. }
  94. // returns a cloned string from the cstring `ptr` and a byte length `len` using the `allocator`
  95. // truncates till the first nul byte it finds or the byte len
  96. clone_from_cstring_bounded :: proc(ptr: cstring, len: int, allocator := context.allocator, loc := #caller_location) -> string {
  97. s := string_from_ptr((^u8)(ptr), len)
  98. s = truncate_to_byte(s, 0)
  99. return clone(s, allocator, loc)
  100. }
  101. // Compares two strings, returning a value representing which one comes first lexiographically.
  102. // -1 for `lhs`; 1 for `rhs`, or 0 if they are equal.
  103. compare :: proc(lhs, rhs: string) -> int {
  104. return mem.compare(transmute([]byte)lhs, transmute([]byte)rhs)
  105. }
  106. // returns the byte offset of the rune `r` in the string `s`, -1 when not found
  107. contains_rune :: proc(s: string, r: rune) -> int {
  108. for c, offset in s {
  109. if c == r {
  110. return offset
  111. }
  112. }
  113. return -1
  114. }
  115. /*
  116. returns true when the string `substr` is contained inside the string `s`
  117. strings.contains("testing", "test") -> true
  118. strings.contains("testing", "ing") -> true
  119. strings.contains("testing", "text") -> false
  120. */
  121. contains :: proc(s, substr: string) -> bool {
  122. return index(s, substr) >= 0
  123. }
  124. /*
  125. returns true when the string `s` contains any of the characters inside the string `chars`
  126. strings.contains_any("test", "test") -> true
  127. strings.contains_any("test", "ts") -> true
  128. strings.contains_any("test", "et") -> true
  129. strings.contains_any("test", "a") -> false
  130. */
  131. contains_any :: proc(s, chars: string) -> bool {
  132. return index_any(s, chars) >= 0
  133. }
  134. /*
  135. returns the utf8 rune count of the string `s`
  136. strings.rune_count("test") -> 4
  137. strings.rune_count("testö") -> 5, where len("testö") -> 6
  138. */
  139. rune_count :: proc(s: string) -> int {
  140. return utf8.rune_count_in_string(s)
  141. }
  142. /*
  143. returns wether the strings `u` and `v` are the same alpha characters
  144. works with utf8 string content and ignores different casings
  145. strings.equal_fold("test", "test") -> true
  146. strings.equal_fold("Test", "test") -> true
  147. strings.equal_fold("Test", "tEsT") -> true
  148. strings.equal_fold("test", "tes") -> false
  149. */
  150. equal_fold :: proc(u, v: string) -> bool {
  151. s, t := u, v
  152. loop: for s != "" && t != "" {
  153. sr, tr: rune
  154. if s[0] < utf8.RUNE_SELF {
  155. sr, s = rune(s[0]), s[1:]
  156. } else {
  157. r, size := utf8.decode_rune_in_string(s)
  158. sr, s = r, s[size:]
  159. }
  160. if t[0] < utf8.RUNE_SELF {
  161. tr, t = rune(t[0]), t[1:]
  162. } else {
  163. r, size := utf8.decode_rune_in_string(t)
  164. tr, t = r, t[size:]
  165. }
  166. if tr == sr { // easy case
  167. continue loop
  168. }
  169. if tr < sr {
  170. tr, sr = sr, tr
  171. }
  172. if tr < utf8.RUNE_SELF {
  173. switch sr {
  174. case 'A'..='Z':
  175. if tr == (sr+'a')-'A' {
  176. continue loop
  177. }
  178. }
  179. return false
  180. }
  181. // TODO(bill): Unicode folding
  182. return false
  183. }
  184. return s == t
  185. }
  186. /*
  187. return the prefix length common between strings `a` and `b`.
  188. strings.prefix_length("testing", "test") -> 4
  189. strings.prefix_length("testing", "te") -> 2
  190. strings.prefix_length("telephone", "te") -> 2
  191. strings.prefix_length("testing", "est") -> 0
  192. */
  193. prefix_length :: proc(a, b: string) -> (n: int) {
  194. _len := min(len(a), len(b))
  195. // Scan for matches including partial codepoints.
  196. #no_bounds_check for n < _len && a[n] == b[n] {
  197. n += 1
  198. }
  199. // Now scan to ignore partial codepoints.
  200. if n > 0 {
  201. s := a[:n]
  202. n = 0
  203. for {
  204. r0, w := utf8.decode_rune(s[n:])
  205. if r0 != utf8.RUNE_ERROR {
  206. n += w
  207. } else {
  208. break
  209. }
  210. }
  211. }
  212. return
  213. }
  214. /*
  215. return true when the string `prefix` is contained at the start of the string `s`
  216. strings.has_prefix("testing", "test") -> true
  217. strings.has_prefix("testing", "te") -> true
  218. strings.has_prefix("telephone", "te") -> true
  219. strings.has_prefix("testing", "est") -> false
  220. */
  221. has_prefix :: proc(s, prefix: string) -> bool {
  222. return len(s) >= len(prefix) && s[0:len(prefix)] == prefix
  223. }
  224. /*
  225. returns true when the string `suffix` is contained at the end of the string `s`
  226. good example to use this is for file extensions
  227. strings.has_suffix("todo.txt", ".txt") -> true
  228. strings.has_suffix("todo.doc", ".txt") -> false
  229. strings.has_suffix("todo.doc.txt", ".txt") -> true
  230. */
  231. has_suffix :: proc(s, suffix: string) -> bool {
  232. return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix
  233. }
  234. /*
  235. returns a combined string from the slice of strings `a` seperated with the `sep` string
  236. allocates the string using the `allocator`
  237. a := [?]string { "a", "b", "c" }
  238. b := strings.join(a[:], " ") -> "a b c"
  239. c := strings.join(a[:], "-") -> "a-b-c"
  240. d := strings.join(a[:], "...") -> "a...b...c"
  241. */
  242. join :: proc(a: []string, sep: string, allocator := context.allocator) -> string {
  243. if len(a) == 0 {
  244. return ""
  245. }
  246. n := len(sep) * (len(a) - 1)
  247. for s in a {
  248. n += len(s)
  249. }
  250. b := make([]byte, n, allocator)
  251. i := copy(b, a[0])
  252. for s in a[1:] {
  253. i += copy(b[i:], sep)
  254. i += copy(b[i:], s)
  255. }
  256. return string(b)
  257. }
  258. join_safe :: proc(a: []string, sep: string, allocator := context.allocator) -> (str: string, err: mem.Allocator_Error) {
  259. if len(a) == 0 {
  260. return "", nil
  261. }
  262. n := len(sep) * (len(a) - 1)
  263. for s in a {
  264. n += len(s)
  265. }
  266. b := make([]byte, n, allocator) or_return
  267. i := copy(b, a[0])
  268. for s in a[1:] {
  269. i += copy(b[i:], sep)
  270. i += copy(b[i:], s)
  271. }
  272. return string(b), nil
  273. }
  274. /*
  275. returns a combined string from the slice of strings `a` without a seperator
  276. allocates the string using the `allocator`
  277. a := [?]string { "a", "b", "c" }
  278. b := strings.concatenate(a[:]) -> "abc"
  279. */
  280. concatenate :: proc(a: []string, allocator := context.allocator) -> string {
  281. if len(a) == 0 {
  282. return ""
  283. }
  284. n := 0
  285. for s in a {
  286. n += len(s)
  287. }
  288. b := make([]byte, n, allocator)
  289. i := 0
  290. for s in a {
  291. i += copy(b[i:], s)
  292. }
  293. return string(b)
  294. }
  295. concatenate_safe :: proc(a: []string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) {
  296. if len(a) == 0 {
  297. return "", nil
  298. }
  299. n := 0
  300. for s in a {
  301. n += len(s)
  302. }
  303. b := make([]byte, n, allocator) or_return
  304. i := 0
  305. for s in a {
  306. i += copy(b[i:], s)
  307. }
  308. return string(b), nil
  309. }
  310. /*
  311. `rune_offset` and `rune_length` are in runes, not bytes.
  312. If `rune_length` <= 0, then it'll return the remainder of the string starting at `rune_offset`.
  313. strings.cut("some example text", 0, 4) -> "some"
  314. strings.cut("some example text", 2, 2) -> "me"
  315. strings.cut("some example text", 5, 7) -> "example"
  316. */
  317. cut :: proc(s: string, rune_offset := int(0), rune_length := int(0), allocator := context.allocator) -> (res: string) {
  318. s := s; rune_length := rune_length
  319. context.allocator = allocator
  320. // If we signal that we want the entire remainder (length <= 0) *and*
  321. // the offset is zero, then we can early out by cloning the input
  322. if rune_offset == 0 && rune_length <= 0 {
  323. return clone(s)
  324. }
  325. // We need to know if we have enough runes to cover offset + length.
  326. rune_count := utf8.rune_count_in_string(s)
  327. // We're asking for a substring starting after the end of the input string.
  328. // That's just an empty string.
  329. if rune_offset >= rune_count {
  330. return ""
  331. }
  332. // If we don't specify the length of the substring, use the remainder.
  333. if rune_length <= 0 {
  334. rune_length = rune_count - rune_offset
  335. }
  336. // We don't yet know how many bytes we need exactly.
  337. // But we do know it's bounded by the number of runes * 4 bytes,
  338. // and can be no more than the size of the input string.
  339. bytes_needed := min(rune_length * 4, len(s))
  340. buf := make([]u8, bytes_needed)
  341. byte_offset := 0
  342. for i := 0; i < rune_count; i += 1 {
  343. _, w := utf8.decode_rune_in_string(s)
  344. // If the rune is part of the substring, copy it to the output buffer.
  345. if i >= rune_offset {
  346. for j := 0; j < w; j += 1 {
  347. buf[byte_offset+j] = s[j]
  348. }
  349. byte_offset += w
  350. }
  351. // We're done if we reach the end of the input string, *or*
  352. // if we've reached a specified length in runes.
  353. if rune_length > 0 {
  354. if i == rune_offset + rune_length - 1 { break }
  355. }
  356. s = s[w:]
  357. }
  358. return string(buf[:byte_offset])
  359. }
  360. @private
  361. _split :: proc(s_, sep: string, sep_save, n_: int, allocator := context.allocator) -> []string {
  362. s, n := s_, n_
  363. if n == 0 {
  364. return nil
  365. }
  366. if sep == "" {
  367. l := utf8.rune_count_in_string(s)
  368. if n < 0 || n > l {
  369. n = l
  370. }
  371. res := make([dynamic]string, n, allocator)
  372. for i := 0; i < n-1; i += 1 {
  373. _, w := utf8.decode_rune_in_string(s)
  374. res[i] = s[:w]
  375. s = s[w:]
  376. }
  377. if n > 0 {
  378. res[n-1] = s
  379. }
  380. return res[:]
  381. }
  382. if n < 0 {
  383. n = count(s, sep) + 1
  384. }
  385. res := make([dynamic]string, n, allocator)
  386. n -= 1
  387. i := 0
  388. for ; i < n; i += 1 {
  389. m := index(s, sep)
  390. if m < 0 {
  391. break
  392. }
  393. res[i] = s[:m+sep_save]
  394. s = s[m+len(sep):]
  395. }
  396. res[i] = s
  397. return res[:i+1]
  398. }
  399. /*
  400. Splits a string into parts, based on a separator.
  401. Returned strings are substrings of 's'.
  402. ```
  403. s := "aaa.bbb.ccc.ddd.eee" // 5 parts
  404. ss := split(s, ".")
  405. fmt.println(ss) // [aaa, bbb, ccc, ddd, eee]
  406. ```
  407. */
  408. split :: proc(s, sep: string, allocator := context.allocator) -> []string {
  409. return _split(s, sep, 0, -1, allocator)
  410. }
  411. /*
  412. Splits a string into a total of 'n' parts, based on a separator.
  413. Returns fewer parts if there wasn't enough occurrences of the separator.
  414. Returned strings are substrings of 's'.
  415. ```
  416. s := "aaa.bbb.ccc.ddd.eee" // 5 parts present
  417. ss := split_n(s, ".", 3) // total of 3 wanted
  418. fmt.println(ss) // [aaa, bbb, ccc.ddd.eee]
  419. ```
  420. */
  421. split_n :: proc(s, sep: string, n: int, allocator := context.allocator) -> []string {
  422. return _split(s, sep, 0, n, allocator)
  423. }
  424. /*
  425. splits the string `s` after the seperator string `sep` appears
  426. returns the slice of split strings allocated using `allocator`
  427. a := "aaa.bbb.ccc.ddd.eee"
  428. aa := strings.split_after(a, ".")
  429. fmt.eprintln(aa) // [aaa., bbb., ccc., ddd., eee]
  430. */
  431. split_after :: proc(s, sep: string, allocator := context.allocator) -> []string {
  432. return _split(s, sep, len(sep), -1, allocator)
  433. }
  434. /*
  435. splits the string `s` after the seperator string `sep` appears into a total of `n` parts
  436. returns the slice of split strings allocated using `allocator`
  437. a := "aaa.bbb.ccc.ddd.eee"
  438. aa := strings.split_after(a, ".")
  439. fmt.eprintln(aa) // [aaa., bbb., ccc., ddd., eee]
  440. */
  441. split_after_n :: proc(s, sep: string, n: int, allocator := context.allocator) -> []string {
  442. return _split(s, sep, len(sep), n, allocator)
  443. }
  444. @private
  445. _split_iterator :: proc(s: ^string, sep: string, sep_save: int) -> (res: string, ok: bool) {
  446. // stop once the string is empty or nil
  447. if s == nil || len(s^) == 0 {
  448. return
  449. }
  450. if sep == "" {
  451. res = s[:]
  452. ok = true
  453. s^ = s[len(s):]
  454. return
  455. }
  456. m := index(s^, sep)
  457. if m < 0 {
  458. // not found
  459. res = s[:]
  460. ok = res != ""
  461. s^ = s[len(s):]
  462. } else {
  463. res = s[:m+sep_save]
  464. ok = true
  465. s^ = s[m+len(sep):]
  466. }
  467. return
  468. }
  469. /*
  470. split the ^string `s` by the byte seperator `sep` in an iterator fashion
  471. consumes the original string till the end, leaving the string `s` with len == 0
  472. text := "a.b.c.d.e"
  473. for str in strings.split_by_byte_iterator(&text, '.') {
  474. fmt.eprintln(str) // every loop -> a b c d e
  475. }
  476. */
  477. split_by_byte_iterator :: proc(s: ^string, sep: u8) -> (res: string, ok: bool) {
  478. m := index_byte(s^, sep)
  479. if m < 0 {
  480. // not found
  481. res = s[:]
  482. ok = res != ""
  483. s^ = {}
  484. } else {
  485. res = s[:m]
  486. ok = true
  487. s^ = s[m+1:]
  488. }
  489. return
  490. }
  491. /*
  492. split the ^string `s` by the seperator string `sep` in an iterator fashion
  493. consumes the original string till the end
  494. text := "a.b.c.d.e"
  495. for str in strings.split_iterator(&text, ".") {
  496. fmt.eprintln(str) // every loop -> a b c d e
  497. }
  498. */
  499. split_iterator :: proc(s: ^string, sep: string) -> (string, bool) {
  500. return _split_iterator(s, sep, 0)
  501. }
  502. /*
  503. split the ^string `s` after every seperator string `sep` in an iterator fashion
  504. consumes the original string till the end
  505. text := "a.b.c.d.e"
  506. for str in strings.split_after_iterator(&text, ".") {
  507. fmt.eprintln(str) // every loop -> a. b. c. d. e
  508. }
  509. */
  510. split_after_iterator :: proc(s: ^string, sep: string) -> (string, bool) {
  511. return _split_iterator(s, sep, len(sep))
  512. }
  513. @(private)
  514. _trim_cr :: proc(s: string) -> string {
  515. n := len(s)
  516. if n > 0 {
  517. if s[n-1] == '\r' {
  518. return s[:n-1]
  519. }
  520. }
  521. return s
  522. }
  523. /*
  524. split the string `s` at every line break '\n'
  525. return an allocated slice of strings
  526. a := "a\nb\nc\nd\ne"
  527. b := strings.split_lines(a)
  528. fmt.eprintln(b) // [a, b, c, d, e]
  529. */
  530. split_lines :: proc(s: string, allocator := context.allocator) -> []string {
  531. sep :: "\n"
  532. lines := _split(s, sep, 0, -1, allocator)
  533. for line in &lines {
  534. line = _trim_cr(line)
  535. }
  536. return lines
  537. }
  538. /*
  539. split the string `s` at every line break '\n' for `n` parts
  540. return an allocated slice of strings
  541. a := "a\nb\nc\nd\ne"
  542. b := strings.split_lines_n(a, 3)
  543. fmt.eprintln(b) // [a, b, c, d\ne\n]
  544. */
  545. split_lines_n :: proc(s: string, n: int, allocator := context.allocator) -> []string {
  546. sep :: "\n"
  547. lines := _split(s, sep, 0, n, allocator)
  548. for line in &lines {
  549. line = _trim_cr(line)
  550. }
  551. return lines
  552. }
  553. /*
  554. split the string `s` at every line break '\n' leaving the '\n' in the resulting strings
  555. return an allocated slice of strings
  556. a := "a\nb\nc\nd\ne"
  557. b := strings.split_lines_after(a)
  558. fmt.eprintln(b) // [a\n, b\n, c\n, d\n, e\n]
  559. */
  560. split_lines_after :: proc(s: string, allocator := context.allocator) -> []string {
  561. sep :: "\n"
  562. lines := _split(s, sep, len(sep), -1, allocator)
  563. for line in &lines {
  564. line = _trim_cr(line)
  565. }
  566. return lines
  567. }
  568. /*
  569. split the string `s` at every line break '\n' leaving the '\n' in the resulting strings
  570. only runs for `n` parts
  571. return an allocated slice of strings
  572. a := "a\nb\nc\nd\ne"
  573. b := strings.split_lines_after_n(a, 3)
  574. fmt.eprintln(b) // [a\n, b\n, c\n, d\ne\n]
  575. */
  576. split_lines_after_n :: proc(s: string, n: int, allocator := context.allocator) -> []string {
  577. sep :: "\n"
  578. lines := _split(s, sep, len(sep), n, allocator)
  579. for line in &lines {
  580. line = _trim_cr(line)
  581. }
  582. return lines
  583. }
  584. /*
  585. split the string `s` at every line break '\n'
  586. returns the current split string every iteration till the string is consumed
  587. text := "a\nb\nc\nd\ne"
  588. for str in strings.split_lines_iterator(&text) {
  589. fmt.eprintln(text) // every loop -> a b c d e
  590. }
  591. */
  592. split_lines_iterator :: proc(s: ^string) -> (line: string, ok: bool) {
  593. sep :: "\n"
  594. line = _split_iterator(s, sep, 0) or_return
  595. return _trim_cr(line), true
  596. }
  597. /*
  598. split the string `s` at every line break '\n'
  599. returns the current split string every iteration till the string is consumed
  600. text := "a\nb\nc\nd\ne"
  601. for str in strings.split_lines_after_iterator(&text) {
  602. fmt.eprintln(text) // every loop -> a\n b\n c\n d\n e\n
  603. }
  604. */
  605. split_lines_after_iterator :: proc(s: ^string) -> (line: string, ok: bool) {
  606. sep :: "\n"
  607. line = _split_iterator(s, sep, len(sep)) or_return
  608. return _trim_cr(line), true
  609. }
  610. /*
  611. returns the byte offset of the first byte `c` in the string `s` it finds, -1 when not found
  612. can't find utf8 based runes
  613. strings.index_byte("test", 't') -> 0
  614. strings.index_byte("test", 'e') -> 1
  615. strings.index_byte("test", 'x') -> -1
  616. strings.index_byte("teäst", 'ä') -> -1
  617. */
  618. index_byte :: proc(s: string, c: byte) -> int {
  619. for i := 0; i < len(s); i += 1 {
  620. if s[i] == c {
  621. return i
  622. }
  623. }
  624. return -1
  625. }
  626. /*
  627. returns the byte offset of the last byte `c` in the string `s` it finds, -1 when not found
  628. can't find utf8 based runes
  629. strings.index_byte("test", 't') -> 3
  630. strings.index_byte("test", 'e') -> 1
  631. strings.index_byte("test", 'x') -> -1
  632. strings.index_byte("teäst", 'ä') -> -1
  633. */
  634. last_index_byte :: proc(s: string, c: byte) -> int {
  635. for i := len(s)-1; i >= 0; i -= 1 {
  636. if s[i] == c {
  637. return i
  638. }
  639. }
  640. return -1
  641. }
  642. /*
  643. returns the byte offset of the first rune `r` in the string `s` it finds, -1 when not found
  644. avoids invalid runes
  645. strings.index_rune("abcädef", 'x') -> -1
  646. strings.index_rune("abcädef", 'a') -> 0
  647. strings.index_rune("abcädef", 'b') -> 1
  648. strings.index_rune("abcädef", 'c') -> 2
  649. strings.index_rune("abcädef", 'ä') -> 3
  650. strings.index_rune("abcädef", 'd') -> 5
  651. strings.index_rune("abcädef", 'e') -> 6
  652. strings.index_rune("abcädef", 'f') -> 7
  653. */
  654. index_rune :: proc(s: string, r: rune) -> int {
  655. switch {
  656. case u32(r) < utf8.RUNE_SELF:
  657. return index_byte(s, byte(r))
  658. case r == utf8.RUNE_ERROR:
  659. for c, i in s {
  660. if c == utf8.RUNE_ERROR {
  661. return i
  662. }
  663. }
  664. return -1
  665. case !utf8.valid_rune(r):
  666. return -1
  667. }
  668. b, w := utf8.encode_rune(r)
  669. return index(s, string(b[:w]))
  670. }
  671. @private PRIME_RABIN_KARP :: 16777619
  672. /*
  673. returns the byte offset of the string `substr` in the string `s`, -1 when not found
  674. strings.index("test", "t") -> 0
  675. strings.index("test", "te") -> 0
  676. strings.index("test", "st") -> 2
  677. strings.index("test", "tt") -> -1
  678. */
  679. index :: proc(s, substr: string) -> int {
  680. hash_str_rabin_karp :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) {
  681. for i := 0; i < len(s); i += 1 {
  682. hash = hash*PRIME_RABIN_KARP + u32(s[i])
  683. }
  684. sq := u32(PRIME_RABIN_KARP)
  685. for i := len(s); i > 0; i >>= 1 {
  686. if (i & 1) != 0 {
  687. pow *= sq
  688. }
  689. sq *= sq
  690. }
  691. return
  692. }
  693. n := len(substr)
  694. switch {
  695. case n == 0:
  696. return 0
  697. case n == 1:
  698. return index_byte(s, substr[0])
  699. case n == len(s):
  700. if s == substr {
  701. return 0
  702. }
  703. return -1
  704. case n > len(s):
  705. return -1
  706. }
  707. hash, pow := hash_str_rabin_karp(substr)
  708. h: u32
  709. for i := 0; i < n; i += 1 {
  710. h = h*PRIME_RABIN_KARP + u32(s[i])
  711. }
  712. if h == hash && s[:n] == substr {
  713. return 0
  714. }
  715. for i := n; i < len(s); /**/ {
  716. h *= PRIME_RABIN_KARP
  717. h += u32(s[i])
  718. h -= pow * u32(s[i-n])
  719. i += 1
  720. if h == hash && s[i-n:i] == substr {
  721. return i - n
  722. }
  723. }
  724. return -1
  725. }
  726. /*
  727. returns the last byte offset of the string `substr` in the string `s`, -1 when not found
  728. strings.index("test", "t") -> 3
  729. strings.index("test", "te") -> 0
  730. strings.index("test", "st") -> 2
  731. strings.index("test", "tt") -> -1
  732. */
  733. last_index :: proc(s, substr: string) -> int {
  734. hash_str_rabin_karp_reverse :: proc(s: string) -> (hash: u32 = 0, pow: u32 = 1) {
  735. for i := len(s) - 1; i >= 0; i -= 1 {
  736. hash = hash*PRIME_RABIN_KARP + u32(s[i])
  737. }
  738. sq := u32(PRIME_RABIN_KARP)
  739. for i := len(s); i > 0; i >>= 1 {
  740. if (i & 1) != 0 {
  741. pow *= sq
  742. }
  743. sq *= sq
  744. }
  745. return
  746. }
  747. n := len(substr)
  748. switch {
  749. case n == 0:
  750. return len(s)
  751. case n == 1:
  752. return last_index_byte(s, substr[0])
  753. case n == len(s):
  754. return 0 if substr == s else -1
  755. case n > len(s):
  756. return -1
  757. }
  758. hash, pow := hash_str_rabin_karp_reverse(substr)
  759. last := len(s) - n
  760. h: u32
  761. for i := len(s)-1; i >= last; i -= 1 {
  762. h = h*PRIME_RABIN_KARP + u32(s[i])
  763. }
  764. if h == hash && s[last:] == substr {
  765. return last
  766. }
  767. for i := last-1; i >= 0; i -= 1 {
  768. h *= PRIME_RABIN_KARP
  769. h += u32(s[i])
  770. h -= pow * u32(s[i+n])
  771. if h == hash && s[i:i+n] == substr {
  772. return i
  773. }
  774. }
  775. return -1
  776. }
  777. /*
  778. returns the index of any first char of `chars` found in `s`, -1 if not found
  779. strings.index_any("test", "s") -> 2
  780. strings.index_any("test", "se") -> 1
  781. strings.index_any("test", "et") -> 0
  782. strings.index_any("test", "set") -> 0
  783. strings.index_any("test", "x") -> -1
  784. */
  785. index_any :: proc(s, chars: string) -> int {
  786. if chars == "" {
  787. return -1
  788. }
  789. if len(chars) == 1 {
  790. r := rune(chars[0])
  791. if r >= utf8.RUNE_SELF {
  792. r = utf8.RUNE_ERROR
  793. }
  794. return index_rune(s, r)
  795. }
  796. if len(s) > 8 {
  797. if as, ok := ascii_set_make(chars); ok {
  798. for i in 0..<len(s) {
  799. if ascii_set_contains(as, s[i]) {
  800. return i
  801. }
  802. }
  803. return -1
  804. }
  805. }
  806. for c, i in s {
  807. if index_rune(chars, c) >= 0 {
  808. return i
  809. }
  810. }
  811. return -1
  812. }
  813. /*
  814. returns the last matching index in `s` of any char in `chars` found in `s`, -1 if not found
  815. iterates the string in reverse
  816. strings.last_index_any("test", "s") -> 2
  817. strings.last_index_any("test", "se") -> 2
  818. strings.last_index_any("test", "et") -> 3
  819. strings.last_index_any("test", "set") -> 3
  820. strings.last_index_any("test", "x") -> -1
  821. */
  822. last_index_any :: proc(s, chars: string) -> int {
  823. if chars == "" {
  824. return -1
  825. }
  826. if len(s) == 1 {
  827. r := rune(s[0])
  828. if r >= utf8.RUNE_SELF {
  829. r = utf8.RUNE_ERROR
  830. }
  831. return index_rune(chars, r)
  832. }
  833. if len(s) > 8 {
  834. if as, ok := ascii_set_make(chars); ok {
  835. for i := len(s)-1; i >= 0; i -= 1 {
  836. if ascii_set_contains(as, s[i]) {
  837. return i
  838. }
  839. }
  840. return -1
  841. }
  842. }
  843. if len(chars) == 1 {
  844. r := rune(chars[0])
  845. if r >= utf8.RUNE_SELF {
  846. r = utf8.RUNE_ERROR
  847. }
  848. for i := len(s); i > 0; /**/ {
  849. c, w := utf8.decode_last_rune_in_string(s[:i])
  850. i -= w
  851. if c == r {
  852. return i
  853. }
  854. }
  855. return -1
  856. }
  857. for i := len(s); i > 0; /**/ {
  858. r, w := utf8.decode_last_rune_in_string(s[:i])
  859. i -= w
  860. if index_rune(chars, r) >= 0 {
  861. return i
  862. }
  863. }
  864. return -1
  865. }
  866. /*
  867. returns the count of the string `substr` found in the string `s`
  868. returns the rune_count + 1 of the string `s` on empty `substr`
  869. strings.count("abbccc", "a") -> 1
  870. strings.count("abbccc", "b") -> 2
  871. strings.count("abbccc", "c") -> 3
  872. strings.count("abbccc", "ab") -> 1
  873. strings.count("abbccc", " ") -> 0
  874. */
  875. count :: proc(s, substr: string) -> int {
  876. if len(substr) == 0 { // special case
  877. return rune_count(s) + 1
  878. }
  879. if len(substr) == 1 {
  880. c := substr[0]
  881. switch len(s) {
  882. case 0:
  883. return 0
  884. case 1:
  885. return int(s[0] == c)
  886. }
  887. n := 0
  888. for i := 0; i < len(s); i += 1 {
  889. if s[i] == c {
  890. n += 1
  891. }
  892. }
  893. return n
  894. }
  895. // TODO(bill): Use a non-brute for approach
  896. n := 0
  897. str := s
  898. for {
  899. i := index(str, substr)
  900. if i == -1 {
  901. return n
  902. }
  903. n += 1
  904. str = str[i+len(substr):]
  905. }
  906. return n
  907. }
  908. /*
  909. repeats the string `s` multiple `count` times and returns the allocated string
  910. panics when `count` is below 0
  911. strings.repeat("abc", 2) -> "abcabc"
  912. */
  913. repeat :: proc(s: string, count: int, allocator := context.allocator) -> string {
  914. if count < 0 {
  915. panic("strings: negative repeat count")
  916. } else if count > 0 && (len(s)*count)/count != len(s) {
  917. panic("strings: repeat count will cause an overflow")
  918. }
  919. b := make([]byte, len(s)*count, allocator)
  920. i := copy(b, s)
  921. for i < len(b) { // 2^N trick to reduce the need to copy
  922. copy(b[i:], b[:i])
  923. i *= 2
  924. }
  925. return string(b)
  926. }
  927. /*
  928. replaces all instances of `old` in the string `s` with the `new` string
  929. returns the `output` string and true when an a allocation through a replace happened
  930. strings.replace_all("xyzxyz", "xyz", "abc") -> "abcabc", true
  931. strings.replace_all("xyzxyz", "abc", "xyz") -> "xyzxyz", false
  932. strings.replace_all("xyzxyz", "xy", "z") -> "zzzz", true
  933. */
  934. replace_all :: proc(s, old, new: string, allocator := context.allocator) -> (output: string, was_allocation: bool) {
  935. return replace(s, old, new, -1, allocator)
  936. }
  937. /*
  938. replaces `n` instances of `old` in the string `s` with the `new` string
  939. if n < 0, no limit on the number of replacements
  940. returns the `output` string and true when an a allocation through a replace happened
  941. strings.replace("xyzxyz", "xyz", "abc", 2) -> "abcabc", true
  942. strings.replace("xyzxyz", "xyz", "abc", 1) -> "abcxyz", true
  943. strings.replace("xyzxyz", "abc", "xyz", -1) -> "xyzxyz", false
  944. strings.replace("xyzxyz", "xy", "z", -1) -> "zzzz", true
  945. */
  946. replace :: proc(s, old, new: string, n: int, allocator := context.allocator) -> (output: string, was_allocation: bool) {
  947. if old == new || n == 0 {
  948. was_allocation = false
  949. output = s
  950. return
  951. }
  952. byte_count := n
  953. if m := count(s, old); m == 0 {
  954. was_allocation = false
  955. output = s
  956. return
  957. } else if n < 0 || m < n {
  958. byte_count = m
  959. }
  960. t := make([]byte, len(s) + byte_count*(len(new) - len(old)), allocator)
  961. was_allocation = true
  962. w := 0
  963. start := 0
  964. for i := 0; i < byte_count; i += 1 {
  965. j := start
  966. if len(old) == 0 {
  967. if i > 0 {
  968. _, width := utf8.decode_rune_in_string(s[start:])
  969. j += width
  970. }
  971. } else {
  972. j += index(s[start:], old)
  973. }
  974. w += copy(t[w:], s[start:j])
  975. w += copy(t[w:], new)
  976. start = j + len(old)
  977. }
  978. w += copy(t[w:], s[start:])
  979. output = string(t[0:w])
  980. return
  981. }
  982. /*
  983. removes the `key` string `n` times from the `s` string
  984. if n < 0, no limit on the number of removes
  985. returns the `output` string and true when an a allocation through a remove happened
  986. strings.remove("abcabc", "abc", 1) -> "abc", true
  987. strings.remove("abcabc", "abc", -1) -> "", true
  988. strings.remove("abcabc", "a", -1) -> "bcbc", true
  989. strings.remove("abcabc", "x", -1) -> "abcabc", false
  990. */
  991. remove :: proc(s, key: string, n: int, allocator := context.allocator) -> (output: string, was_allocation: bool) {
  992. return replace(s, key, "", n, allocator)
  993. }
  994. /*
  995. removes all the `key` string instanes from the `s` string
  996. returns the `output` string and true when an a allocation through a remove happened
  997. strings.remove("abcabc", "abc") -> "", true
  998. strings.remove("abcabc", "a") -> "bcbc", true
  999. strings.remove("abcabc", "x") -> "abcabc", false
  1000. */
  1001. remove_all :: proc(s, key: string, allocator := context.allocator) -> (output: string, was_allocation: bool) {
  1002. return remove(s, key, -1, allocator)
  1003. }
  1004. @(private) _ascii_space := [256]bool{'\t' = true, '\n' = true, '\v' = true, '\f' = true, '\r' = true, ' ' = true}
  1005. // return true when the `r` rune is '\t', '\n', '\v', '\f', '\r' or ' '
  1006. is_ascii_space :: proc(r: rune) -> bool {
  1007. if r < utf8.RUNE_SELF {
  1008. return _ascii_space[u8(r)]
  1009. }
  1010. return false
  1011. }
  1012. // returns true when the `r` rune is any asci or utf8 based whitespace
  1013. is_space :: proc(r: rune) -> bool {
  1014. if r < 0x2000 {
  1015. switch r {
  1016. case '\t', '\n', '\v', '\f', '\r', ' ', 0x85, 0xa0, 0x1680:
  1017. return true
  1018. }
  1019. } else {
  1020. if r <= 0x200a {
  1021. return true
  1022. }
  1023. switch r {
  1024. case 0x2028, 0x2029, 0x202f, 0x205f, 0x3000:
  1025. return true
  1026. }
  1027. }
  1028. return false
  1029. }
  1030. // returns true when the `r` rune is a nul byte
  1031. is_null :: proc(r: rune) -> bool {
  1032. return r == 0x0000
  1033. }
  1034. /*
  1035. runs trough the `s` string linearly and watches wether the `p` procedure matches the `truth` bool
  1036. returns the rune offset or -1 when no match was found
  1037. call :: proc(r: rune) -> bool {
  1038. return r == 'a'
  1039. }
  1040. strings.index_proc("abcabc", call) -> 0
  1041. strings.index_proc("cbacba", call) -> 2
  1042. strings.index_proc("cbacba", call, false) -> 0
  1043. strings.index_proc("abcabc", call, false) -> 1
  1044. strings.index_proc("xyz", call) -> -1
  1045. */
  1046. index_proc :: proc(s: string, p: proc(rune) -> bool, truth := true) -> int {
  1047. for r, i in s {
  1048. if p(r) == truth {
  1049. return i
  1050. }
  1051. }
  1052. return -1
  1053. }
  1054. // same as `index_proc` but with a `p` procedure taking a rawptr for state
  1055. index_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr, truth := true) -> int {
  1056. for r, i in s {
  1057. if p(state, r) == truth {
  1058. return i
  1059. }
  1060. }
  1061. return -1
  1062. }
  1063. // same as `index_proc` but runs through the string in reverse
  1064. last_index_proc :: proc(s: string, p: proc(rune) -> bool, truth := true) -> int {
  1065. // TODO(bill): Probably use Rabin-Karp Search
  1066. for i := len(s); i > 0; {
  1067. r, size := utf8.decode_last_rune_in_string(s[:i])
  1068. i -= size
  1069. if p(r) == truth {
  1070. return i
  1071. }
  1072. }
  1073. return -1
  1074. }
  1075. // same as `index_proc_with_state` but runs through the string in reverse
  1076. last_index_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr, truth := true) -> int {
  1077. // TODO(bill): Probably use Rabin-Karp Search
  1078. for i := len(s); i > 0; {
  1079. r, size := utf8.decode_last_rune_in_string(s[:i])
  1080. i -= size
  1081. if p(state, r) == truth {
  1082. return i
  1083. }
  1084. }
  1085. return -1
  1086. }
  1087. /*
  1088. trims the input string `s` until the procedure `p` returns false
  1089. does not allocate - only returns a cut variant of the input string
  1090. returns an empty string when no match was found at all
  1091. find :: proc(r: rune) -> bool {
  1092. return r != 'i'
  1093. }
  1094. strings.trim_left_proc("testing", find) -> "ing"
  1095. */
  1096. trim_left_proc :: proc(s: string, p: proc(rune) -> bool) -> string {
  1097. i := index_proc(s, p, false)
  1098. if i == -1 {
  1099. return ""
  1100. }
  1101. return s[i:]
  1102. }
  1103. /*
  1104. trims the input string `s` until the procedure `p` with state returns false
  1105. returns an empty string when no match was found at all
  1106. */
  1107. trim_left_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr) -> string {
  1108. i := index_proc_with_state(s, p, state, false)
  1109. if i == -1 {
  1110. return ""
  1111. }
  1112. return s[i:]
  1113. }
  1114. /*
  1115. trims the input string `s` from the right until the procedure `p` returns false
  1116. does not allocate - only returns a cut variant of the input string
  1117. returns an empty string when no match was found at all
  1118. find :: proc(r: rune) -> bool {
  1119. return r != 't'
  1120. }
  1121. strings.trim_left_proc("testing", find) -> "test"
  1122. */
  1123. trim_right_proc :: proc(s: string, p: proc(rune) -> bool) -> string {
  1124. i := last_index_proc(s, p, false)
  1125. if i >= 0 && s[i] >= utf8.RUNE_SELF {
  1126. _, w := utf8.decode_rune_in_string(s[i:])
  1127. i += w
  1128. } else {
  1129. i += 1
  1130. }
  1131. return s[0:i]
  1132. }
  1133. /*
  1134. trims the input string `s` from the right until the procedure `p` with state returns false
  1135. returns an empty string when no match was found at all
  1136. */
  1137. trim_right_proc_with_state :: proc(s: string, p: proc(rawptr, rune) -> bool, state: rawptr) -> string {
  1138. i := last_index_proc_with_state(s, p, state, false)
  1139. if i >= 0 && s[i] >= utf8.RUNE_SELF {
  1140. _, w := utf8.decode_rune_in_string(s[i:])
  1141. i += w
  1142. } else {
  1143. i += 1
  1144. }
  1145. return s[0:i]
  1146. }
  1147. // procedure for `trim_*_proc` variants, which has a string rawptr cast + rune comparison
  1148. is_in_cutset :: proc(state: rawptr, r: rune) -> bool {
  1149. if state == nil {
  1150. return false
  1151. }
  1152. cutset := (^string)(state)^
  1153. for c in cutset {
  1154. if r == c {
  1155. return true
  1156. }
  1157. }
  1158. return false
  1159. }
  1160. // trims the `cutset` string from the `s` string
  1161. trim_left :: proc(s: string, cutset: string) -> string {
  1162. if s == "" || cutset == "" {
  1163. return s
  1164. }
  1165. state := cutset
  1166. return trim_left_proc_with_state(s, is_in_cutset, &state)
  1167. }
  1168. // trims the `cutset` string from the `s` string from the right
  1169. trim_right :: proc(s: string, cutset: string) -> string {
  1170. if s == "" || cutset == "" {
  1171. return s
  1172. }
  1173. state := cutset
  1174. return trim_right_proc_with_state(s, is_in_cutset, &state)
  1175. }
  1176. // trims the `cutset` string from the `s` string, both from left and right
  1177. trim :: proc(s: string, cutset: string) -> string {
  1178. return trim_right(trim_left(s, cutset), cutset)
  1179. }
  1180. // trims until a valid non space rune: "\t\txyz\t\t" -> "xyz\t\t"
  1181. trim_left_space :: proc(s: string) -> string {
  1182. return trim_left_proc(s, is_space)
  1183. }
  1184. // trims from the right until a valid non space rune: "\t\txyz\t\t" -> "\t\txyz"
  1185. trim_right_space :: proc(s: string) -> string {
  1186. return trim_right_proc(s, is_space)
  1187. }
  1188. // trims from both sides until a valid non space rune: "\t\txyz\t\t" -> "xyz"
  1189. trim_space :: proc(s: string) -> string {
  1190. return trim_right_space(trim_left_space(s))
  1191. }
  1192. // trims nul runes from the left: "\x00\x00testing\x00\x00" -> "testing\x00\x00"
  1193. trim_left_null :: proc(s: string) -> string {
  1194. return trim_left_proc(s, is_null)
  1195. }
  1196. // trims nul runes from the right: "\x00\x00testing\x00\x00" -> "\x00\x00testing"
  1197. trim_right_null :: proc(s: string) -> string {
  1198. return trim_right_proc(s, is_null)
  1199. }
  1200. // trims nul runes from both sides: "\x00\x00testing\x00\x00" -> "testing"
  1201. trim_null :: proc(s: string) -> string {
  1202. return trim_right_null(trim_left_null(s))
  1203. }
  1204. /*
  1205. trims a `prefix` string from the start of the `s` string and returns the trimmed string
  1206. returns the input string `s` when no prefix was found
  1207. strings.trim_prefix("testing", "test") -> "ing"
  1208. strings.trim_prefix("testing", "abc") -> "testing"
  1209. */
  1210. trim_prefix :: proc(s, prefix: string) -> string {
  1211. if has_prefix(s, prefix) {
  1212. return s[len(prefix):]
  1213. }
  1214. return s
  1215. }
  1216. /*
  1217. trims a `suffix` string from the end of the `s` string and returns the trimmed string
  1218. returns the input string `s` when no suffix was found
  1219. strings.trim_suffix("todo.txt", ".txt") -> "todo"
  1220. strings.trim_suffix("todo.doc", ".txt") -> "todo.doc"
  1221. */
  1222. trim_suffix :: proc(s, suffix: string) -> string {
  1223. if has_suffix(s, suffix) {
  1224. return s[:len(s)-len(suffix)]
  1225. }
  1226. return s
  1227. }
  1228. /*
  1229. splits the input string `s` by all possible `substrs` []string
  1230. returns the allocated []string, nil on any empty substring or no matches
  1231. splits := [?]string { "---", "~~~", ".", "_", "," }
  1232. res := strings.split_multi("testing,this.out_nice---done~~~last", splits[:])
  1233. fmt.eprintln(res) // -> [testing, this, out, nice, done, last]
  1234. */
  1235. split_multi :: proc(s: string, substrs: []string, allocator := context.allocator) -> (buf: []string) #no_bounds_check {
  1236. if s == "" || len(substrs) <= 0 {
  1237. return
  1238. }
  1239. // disallow "" substr
  1240. for substr in substrs {
  1241. if len(substr) == 0 {
  1242. return
  1243. }
  1244. }
  1245. // TODO maybe remove duplicate substrs
  1246. // sort substrings by string size, largest to smallest
  1247. temp_substrs := slice.clone(substrs, context.temp_allocator)
  1248. slice.sort_by(temp_substrs, proc(a, b: string) -> bool {
  1249. return len(a) > len(b)
  1250. })
  1251. substrings_found: int
  1252. temp := s
  1253. // count substr results found in string
  1254. first_pass: for len(temp) > 0 {
  1255. for substr in temp_substrs {
  1256. size := len(substr)
  1257. // check range and compare string to substr
  1258. if size <= len(temp) && temp[:size] == substr {
  1259. substrings_found += 1
  1260. temp = temp[size:]
  1261. continue first_pass
  1262. }
  1263. }
  1264. // step through string
  1265. _, skip := utf8.decode_rune_in_string(temp[:])
  1266. temp = temp[skip:]
  1267. }
  1268. // skip when no results
  1269. if substrings_found < 1 {
  1270. return
  1271. }
  1272. buf = make([]string, substrings_found + 1, allocator)
  1273. buf_index: int
  1274. temp = s
  1275. temp_old := temp
  1276. // gather results in the same fashion
  1277. second_pass: for len(temp) > 0 {
  1278. for substr in temp_substrs {
  1279. size := len(substr)
  1280. // check range and compare string to substr
  1281. if size <= len(temp) && temp[:size] == substr {
  1282. buf[buf_index] = temp_old[:len(temp_old) - len(temp)]
  1283. buf_index += 1
  1284. temp = temp[size:]
  1285. temp_old = temp
  1286. continue second_pass
  1287. }
  1288. }
  1289. // step through string
  1290. _, skip := utf8.decode_rune_in_string(temp[:])
  1291. temp = temp[skip:]
  1292. }
  1293. buf[buf_index] = temp_old[:]
  1294. return buf
  1295. }
  1296. // state for the split multi iterator
  1297. Split_Multi :: struct {
  1298. temp: string,
  1299. temp_old: string,
  1300. substrs: []string,
  1301. }
  1302. // returns split multi state with sorted `substrs`
  1303. split_multi_init :: proc(s: string, substrs: []string) -> Split_Multi {
  1304. // sort substrings, largest to smallest
  1305. temp_substrs := slice.clone(substrs, context.temp_allocator)
  1306. slice.sort_by(temp_substrs, proc(a, b: string) -> bool {
  1307. return len(a) > len(b)
  1308. })
  1309. return {
  1310. temp = s,
  1311. temp_old = s,
  1312. substrs = temp_substrs,
  1313. }
  1314. }
  1315. /*
  1316. splits the input string `s` by all possible `substrs` []string in an iterator fashion
  1317. returns the split string every iteration, the full string on no match
  1318. splits := [?]string { "---", "~~~", ".", "_", "," }
  1319. state := strings.split_multi_init("testing,this.out_nice---done~~~last", splits[:])
  1320. for str in strings.split_multi_iterate(&state) {
  1321. fmt.eprintln(str) // every iteration -> [testing, this, out, nice, done, last]
  1322. }
  1323. */
  1324. split_multi_iterate :: proc(using sm: ^Split_Multi) -> (res: string, ok: bool) #no_bounds_check {
  1325. pass: for len(temp) > 0 {
  1326. for substr in substrs {
  1327. size := len(substr)
  1328. // check range and compare string to substr
  1329. if size <= len(temp) && temp[:size] == substr {
  1330. res = temp_old[:len(temp_old) - len(temp)]
  1331. temp = temp[size:]
  1332. temp_old = temp
  1333. ok = true
  1334. return
  1335. }
  1336. }
  1337. // step through string
  1338. _, skip := utf8.decode_rune_in_string(temp[:])
  1339. temp = temp[skip:]
  1340. }
  1341. // allow last iteration
  1342. if temp_old != "" {
  1343. res = temp_old[:]
  1344. ok = true
  1345. temp_old = ""
  1346. }
  1347. return
  1348. }
  1349. // scrub scruvs invalid utf-8 characters and replaces them with the replacement string
  1350. // Adjacent invalid bytes are only replaced once
  1351. scrub :: proc(s: string, replacement: string, allocator := context.allocator) -> string {
  1352. str := s
  1353. b: Builder
  1354. builder_init(&b, 0, len(s), allocator)
  1355. has_error := false
  1356. cursor := 0
  1357. origin := str
  1358. for len(str) > 0 {
  1359. r, w := utf8.decode_rune_in_string(str)
  1360. if r == utf8.RUNE_ERROR {
  1361. if !has_error {
  1362. has_error = true
  1363. write_string(&b, origin[:cursor])
  1364. }
  1365. } else if has_error {
  1366. has_error = false
  1367. write_string(&b, replacement)
  1368. origin = origin[cursor:]
  1369. cursor = 0
  1370. }
  1371. cursor += w
  1372. str = str[w:]
  1373. }
  1374. return to_string(b)
  1375. }
  1376. /*
  1377. returns a reversed version of the `s` string
  1378. a := "abcxyz"
  1379. b := strings.reverse(a)
  1380. fmt.eprintln(a, b) // abcxyz zyxcba
  1381. */
  1382. reverse :: proc(s: string, allocator := context.allocator) -> string {
  1383. str := s
  1384. n := len(str)
  1385. buf := make([]byte, n)
  1386. i := n
  1387. for len(str) > 0 {
  1388. _, w := utf8.decode_rune_in_string(str)
  1389. i -= w
  1390. copy(buf[i:], str[:w])
  1391. str = str[w:]
  1392. }
  1393. return string(buf)
  1394. }
  1395. /*
  1396. expands the string to a grid spaced by `tab_size` whenever a `\t` character appears
  1397. returns the tabbed string, panics on tab_size <= 0
  1398. strings.expand_tabs("abc1\tabc2\tabc3", 4) -> abc1 abc2 abc3
  1399. strings.expand_tabs("abc1\tabc2\tabc3", 5) -> abc1 abc2 abc3
  1400. strings.expand_tabs("abc1\tabc2\tabc3", 6) -> abc1 abc2 abc3
  1401. */
  1402. expand_tabs :: proc(s: string, tab_size: int, allocator := context.allocator) -> string {
  1403. if tab_size <= 0 {
  1404. panic("tab size must be positive")
  1405. }
  1406. if s == "" {
  1407. return ""
  1408. }
  1409. b: Builder
  1410. builder_init(&b, allocator)
  1411. writer := to_writer(&b)
  1412. str := s
  1413. column: int
  1414. for len(str) > 0 {
  1415. r, w := utf8.decode_rune_in_string(str)
  1416. if r == '\t' {
  1417. expand := tab_size - column%tab_size
  1418. for i := 0; i < expand; i += 1 {
  1419. io.write_byte(writer, ' ')
  1420. }
  1421. column += expand
  1422. } else {
  1423. if r == '\n' {
  1424. column = 0
  1425. } else {
  1426. column += w
  1427. }
  1428. io.write_rune(writer, r)
  1429. }
  1430. str = str[w:]
  1431. }
  1432. return to_string(b)
  1433. }
  1434. /*
  1435. splits the `str` string by the seperator `sep` string and returns 3 parts
  1436. `head`: before the split, `match`: the seperator, `tail`: the end of the split
  1437. returns the input string when the `sep` was not found
  1438. text := "testing this out"
  1439. strings.partition(text, " this ") -> head: "testing", match: " this ", tail: "out"
  1440. strings.partition(text, "hi") -> head: "testing t", match: "hi", tail: "s out"
  1441. strings.partition(text, "xyz") -> head: "testing this out", match: "", tail: ""
  1442. */
  1443. partition :: proc(str, sep: string) -> (head, match, tail: string) {
  1444. i := index(str, sep)
  1445. if i == -1 {
  1446. head = str
  1447. return
  1448. }
  1449. head = str[:i]
  1450. match = str[i:i+len(sep)]
  1451. tail = str[i+len(sep):]
  1452. return
  1453. }
  1454. center_justify :: centre_justify // NOTE(bill): Because Americans exist
  1455. // centre_justify returns a string with a pad string at boths sides if the str's rune length is smaller than length
  1456. centre_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> string {
  1457. n := rune_count(str)
  1458. if n >= length || pad == "" {
  1459. return clone(str, allocator)
  1460. }
  1461. remains := length-n
  1462. pad_len := rune_count(pad)
  1463. b: Builder
  1464. builder_init(&b, allocator)
  1465. builder_grow(&b, len(str) + (remains/pad_len + 1)*len(pad))
  1466. w := to_writer(&b)
  1467. write_pad_string(w, pad, pad_len, remains/2)
  1468. io.write_string(w, str)
  1469. write_pad_string(w, pad, pad_len, (remains+1)/2)
  1470. return to_string(b)
  1471. }
  1472. // left_justify returns a string with a pad string at right side if the str's rune length is smaller than length
  1473. left_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> string {
  1474. n := rune_count(str)
  1475. if n >= length || pad == "" {
  1476. return clone(str, allocator)
  1477. }
  1478. remains := length-n
  1479. pad_len := rune_count(pad)
  1480. b: Builder
  1481. builder_init(&b, allocator)
  1482. builder_grow(&b, len(str) + (remains/pad_len + 1)*len(pad))
  1483. w := to_writer(&b)
  1484. io.write_string(w, str)
  1485. write_pad_string(w, pad, pad_len, remains)
  1486. return to_string(b)
  1487. }
  1488. // right_justify returns a string with a pad string at left side if the str's rune length is smaller than length
  1489. right_justify :: proc(str: string, length: int, pad: string, allocator := context.allocator) -> string {
  1490. n := rune_count(str)
  1491. if n >= length || pad == "" {
  1492. return clone(str, allocator)
  1493. }
  1494. remains := length-n
  1495. pad_len := rune_count(pad)
  1496. b: Builder
  1497. builder_init(&b, allocator)
  1498. builder_grow(&b, len(str) + (remains/pad_len + 1)*len(pad))
  1499. w := to_writer(&b)
  1500. write_pad_string(w, pad, pad_len, remains)
  1501. io.write_string(w, str)
  1502. return to_string(b)
  1503. }
  1504. @private
  1505. write_pad_string :: proc(w: io.Writer, pad: string, pad_len, remains: int) {
  1506. repeats := remains / pad_len
  1507. for i := 0; i < repeats; i += 1 {
  1508. io.write_string(w, pad)
  1509. }
  1510. n := remains % pad_len
  1511. p := pad
  1512. for i := 0; i < n; i += 1 {
  1513. r, width := utf8.decode_rune_in_string(p)
  1514. io.write_rune(w, r)
  1515. p = p[width:]
  1516. }
  1517. }
  1518. // fields splits the string s around each instance of one or more consecutive white space character, defined by unicode.is_space
  1519. // returning a slice of substrings of s or an empty slice if s only contains white space
  1520. fields :: proc(s: string, allocator := context.allocator) -> []string #no_bounds_check {
  1521. n := 0
  1522. was_space := 1
  1523. set_bits := u8(0)
  1524. // check to see
  1525. for i in 0..<len(s) {
  1526. r := s[i]
  1527. set_bits |= r
  1528. is_space := int(_ascii_space[r])
  1529. n += was_space & ~is_space
  1530. was_space = is_space
  1531. }
  1532. if set_bits >= utf8.RUNE_SELF {
  1533. return fields_proc(s, unicode.is_space, allocator)
  1534. }
  1535. if n == 0 {
  1536. return nil
  1537. }
  1538. a := make([]string, n, allocator)
  1539. na := 0
  1540. field_start := 0
  1541. i := 0
  1542. for i < len(s) && _ascii_space[s[i]] {
  1543. i += 1
  1544. }
  1545. field_start = i
  1546. for i < len(s) {
  1547. if !_ascii_space[s[i]] {
  1548. i += 1
  1549. continue
  1550. }
  1551. a[na] = s[field_start : i]
  1552. na += 1
  1553. i += 1
  1554. for i < len(s) && _ascii_space[s[i]] {
  1555. i += 1
  1556. }
  1557. field_start = i
  1558. }
  1559. if field_start < len(s) {
  1560. a[na] = s[field_start:]
  1561. }
  1562. return a
  1563. }
  1564. // fields_proc splits the string s at each run of unicode code points `ch` satisfying f(ch)
  1565. // returns a slice of substrings of s
  1566. // If all code points in s satisfy f(ch) or string is empty, an empty slice is returned
  1567. //
  1568. // fields_proc makes no guarantee about the order in which it calls f(ch)
  1569. // it assumes that `f` always returns the same value for a given ch
  1570. fields_proc :: proc(s: string, f: proc(rune) -> bool, allocator := context.allocator) -> []string #no_bounds_check {
  1571. substrings := make([dynamic]string, 0, 32, allocator)
  1572. start, end := -1, -1
  1573. for r, offset in s {
  1574. end = offset
  1575. if f(r) {
  1576. if start >= 0 {
  1577. append(&substrings, s[start : end])
  1578. // -1 could be used, but just speed it up through bitwise not
  1579. // gotta love 2's complement
  1580. start = ~start
  1581. }
  1582. } else {
  1583. if start < 0 {
  1584. start = end
  1585. }
  1586. }
  1587. }
  1588. if start >= 0 {
  1589. append(&substrings, s[start : len(s)])
  1590. }
  1591. return substrings[:]
  1592. }
  1593. // `fields_iterator` returns the first run of characters in `s` that does not contain white space, defined by `unicode.is_space`
  1594. // `s` will then start from any space after the substring, or be an empty string if the substring was the remaining characters
  1595. fields_iterator :: proc(s: ^string) -> (field: string, ok: bool) {
  1596. start, end := -1, -1
  1597. for r, offset in s {
  1598. end = offset
  1599. if unicode.is_space(r) {
  1600. if start >= 0 {
  1601. field = s[start : end]
  1602. ok = true
  1603. s^ = s[end:]
  1604. return
  1605. }
  1606. } else {
  1607. if start < 0 {
  1608. start = end
  1609. }
  1610. }
  1611. }
  1612. // if either of these are true, the string did not contain any characters
  1613. if end < 0 || start < 0 {
  1614. return "", false
  1615. }
  1616. field = s[start:]
  1617. ok = true
  1618. s^ = s[len(s):]
  1619. return
  1620. }
  1621. // `levenshtein_distance` returns the Levenshtein edit distance between 2 strings.
  1622. // This is a single-row-version of the Wagner–Fischer algorithm, based on C code by Martin Ettl.
  1623. // Note: allocator isn't used if the length of string b in runes is smaller than 64.
  1624. levenshtein_distance :: proc(a, b: string, allocator := context.allocator) -> int {
  1625. LEVENSHTEIN_DEFAULT_COSTS: []int : {
  1626. 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
  1627. 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
  1628. 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
  1629. 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
  1630. 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
  1631. 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
  1632. 60, 61, 62, 63,
  1633. }
  1634. m, n := utf8.rune_count_in_string(a), utf8.rune_count_in_string(b)
  1635. if m == 0 {
  1636. return n
  1637. }
  1638. if n == 0 {
  1639. return m
  1640. }
  1641. costs: []int
  1642. if n + 1 > len(LEVENSHTEIN_DEFAULT_COSTS) {
  1643. costs = make([]int, n + 1, allocator)
  1644. for k in 0..=n {
  1645. costs[k] = k
  1646. }
  1647. } else {
  1648. costs = LEVENSHTEIN_DEFAULT_COSTS
  1649. }
  1650. defer if n + 1 > len(LEVENSHTEIN_DEFAULT_COSTS) {
  1651. delete(costs, allocator)
  1652. }
  1653. i: int
  1654. for c1 in a {
  1655. costs[0] = i + 1
  1656. corner := i
  1657. j: int
  1658. for c2 in b {
  1659. upper := costs[j + 1]
  1660. if c1 == c2 {
  1661. costs[j + 1] = corner
  1662. } else {
  1663. t := upper if upper < corner else corner
  1664. costs[j + 1] = (costs[j] if costs[j] < t else t) + 1
  1665. }
  1666. corner = upper
  1667. j += 1
  1668. }
  1669. i += 1
  1670. }
  1671. return costs[n]
  1672. }