add a substring function to line_gap.sml which is null terminated, which may be required for C FFI

This commit is contained in:
2024-11-10 21:57:04 +00:00
parent c2e74d89fd
commit 6eb74c4332

View File

@@ -14,7 +14,10 @@ sig
val fromString: string -> t val fromString: string -> t
val toString: t -> string val toString: t -> string
val substring: int * int * t -> string val substring: int * int * t -> string
val nullSubstring: int * int * t -> string
val substringWithEnd: int * int * t * string -> string
val delete: int * int * t -> t val delete: int * int * t -> t
val insert: int * string * t -> t val insert: int * string * t -> t
@@ -1950,41 +1953,49 @@ struct
end end
local local
fun subRightFromHere (curIdx, finish, right, acc) = fun consIfNotEmpty (s, acc) =
if String.size s > 0 then
s :: acc
else
acc
(* We build up the string list and, at the end,
* we always make sure to reverse the list too
* because the order of the list matters for String.concat *)
fun subRightFromHere (curIdx, finish, right, acc, endWith) =
case right of case right of
hd :: tl => hd :: tl =>
let let
val nextIdx = curIdx + String.size hd val nextIdx = curIdx + String.size hd
in in
if nextIdx < finish then if nextIdx < finish then
subRightFromHere (curIdx, finish, tl, hd :: acc) subRightFromHere (curIdx, finish, tl, hd :: acc, endWith)
else if nextIdx > finish then else if nextIdx > finish then
let let
val length = finish - curIdx val length = finish - curIdx
val accHd = String.substring (hd, 0, length) val accHd = String.substring (hd, 0, length)
val acc = accHd :: acc val acc = consIfNotEmpty (endWith, accHd :: acc)
val acc = List.rev acc
in in
acc List.rev acc
end end
else else
(* nextIdx = finish (* nextIdx = finish
* so add current hd to vec and then concat *) * so add current hd to vec and then concat *)
let let
val acc = hd :: acc val acc = hd :: acc
val acc = List.rev acc val acc = consIfNotEmpty (endWith, acc)
in in
acc List.rev acc
end end
end end
| [] => | [] =>
let let
val acc = List.rev acc val acc = consIfNotEmpty (endWith, acc)
in in
acc List.rev acc
end end
fun moveRightAndSub (start, finish, curIdx, right) = fun moveRightAndSub (start, finish, curIdx, right, endWith) =
case right of case right of
hd :: tl => hd :: tl =>
let let
@@ -1992,7 +2003,7 @@ struct
in in
if nextIdx < start then if nextIdx < start then
(* continue moving rightwards *) (* continue moving rightwards *)
moveRightAndSub (start, finish, nextIdx, tl) moveRightAndSub (start, finish, nextIdx, tl, endWith)
else if nextIdx > start then else if nextIdx > start then
if nextIdx < finish then if nextIdx < finish then
(* get starting acc, (* get starting acc,
@@ -2001,7 +2012,7 @@ struct
val substart = start - curIdx val substart = start - curIdx
val length = String.size hd - substart val length = String.size hd - substart
val acc = [String.substring (hd, substart, length)] val acc = [String.substring (hd, substart, length)]
val acc = subRightFromHere (nextIdx, finish, tl, acc) val acc = subRightFromHere (nextIdx, finish, tl, acc, endWith)
in in
String.concat acc String.concat acc
end end
@@ -2011,23 +2022,29 @@ struct
val substart = start - curIdx val substart = start - curIdx
val subfinish = finish - curIdx val subfinish = finish - curIdx
val length = subfinish - substart val length = subfinish - substart
val str = String.substring (hd, substart, length)
in in
String.substring (hd, substart, length) if String.size endWith > 0
then str ^ endWith
else str
end end
else else
(* have to get substring from middle to end *) (* have to get substring from middle to end *)
let let
val substart = start - curIdx val substart = start - curIdx
val length = String.size hd - substart val length = String.size hd - substart
val str = String.substring (hd, substart, length)
in in
String.substring (hd, substart, length) if String.size endWith > 0
then str ^ endWith
else str
end end
else else
(* nextIdx = start (* nextIdx = start
* so we have to ignore this string * so we have to ignore this string
* and start building acc from tl *) * and start building acc from tl *)
let let
val acc = subRightFromHere (nextIdx, finish, tl, []) val acc = subRightFromHere (nextIdx, finish, tl, [], endWith)
in in
String.concat acc String.concat acc
end end
@@ -2036,7 +2053,7 @@ struct
(* if there are no strings to the right, (* if there are no strings to the right,
* return empty string, * return empty string,
* as we cannot do much else. *) * as we cannot do much else. *)
"" endWith
fun subLeftFromHere (start, curIdx, left, acc) = fun subLeftFromHere (start, curIdx, left, acc) =
case left of case left of
@@ -2069,14 +2086,14 @@ struct
end end
| [] => String.concat acc | [] => String.concat acc
fun subFromLeftAndRight (start, finish, curIdx, left, right) = fun subFromLeftAndRight (start, finish, curIdx, left, right, endWith) =
let let
val acc = subRightFromHere (curIdx, finish, right, []) val acc = subRightFromHere (curIdx, finish, right, [], endWith)
in in
subLeftFromHere (start, curIdx, left, acc) subLeftFromHere (start, curIdx, left, acc)
end end
fun moveLeftAndSub (start, finish, curIdx, left) = fun moveLeftAndSub (start, finish, curIdx, left, endWith) =
case left of case left of
hd :: tl => hd :: tl =>
let let
@@ -2084,14 +2101,14 @@ struct
in in
if prevIdx > finish then if prevIdx > finish then
(* continue *) (* continue *)
moveLeftAndSub (start, finish, prevIdx, tl) moveLeftAndSub (start, finish, prevIdx, tl, endWith)
else if prevIdx < finish then else if prevIdx < finish then
if prevIdx > start then if prevIdx > start then
(* get initial acc (* get initial acc
* and continue substring leftwards *) * and continue substring leftwards *)
let let
val length = finish - prevIdx val length = finish - prevIdx
val acc = [String.substring (hd, 0, length)] val str = String.substring (hd, 0, length) val acc = [str, endWith]
in in
subLeftFromHere (start, prevIdx, tl, acc) subLeftFromHere (start, prevIdx, tl, acc)
end end
@@ -2102,8 +2119,11 @@ struct
val substart = start - prevIdx val substart = start - prevIdx
val subfinish = finish - prevIdx val subfinish = finish - prevIdx
val length = subfinish - substart val length = subfinish - substart
val str = String.substring (hd, substart, length)
in in
String.substring (hd, substart, length) if String.size endWith > 0
then str ^ endWith
else str
end end
else else
(* prevIdx = start (* prevIdx = start
@@ -2111,41 +2131,62 @@ struct
let let
val subfinish = finish - prevIdx val subfinish = finish - prevIdx
val length = String.size hd - subfinish val length = String.size hd - subfinish
val str = String.substring (hd, 0, length)
in in
String.substring (hd, 0, length) if String.size endWith > 0
then str ^ endWith
else str
end end
else else
(* prevIdx = finish (* prevIdx = finish
* so we want to ignore hd and start * so we want to ignore hd and start
* subLeftFromHere with an empty list *) * subLeftFromHere with an empty list *)
subLeftFromHere (start, prevIdx, tl, []) subLeftFromHere (start, prevIdx, tl, [endWith])
end end
| [] => "" | [] => endWith
fun sub (start, finish, curIdx, left, right) = fun sub (start, finish, curIdx, left, right, endWith) =
if start > curIdx then if start > curIdx then
(* move rightwards to begin getting substring *) (* move rightwards to begin getting substring *)
moveRightAndSub (start, finish, curIdx, right) moveRightAndSub (start, finish, curIdx, right, endWith)
else if start < curIdx then else if start < curIdx then
if finish <= curIdx then if finish <= curIdx then
moveLeftAndSub (start, finish, curIdx, left) moveLeftAndSub (start, finish, curIdx, left, endWith)
else else
(* in middle of buffer we want to get substring from *) (* in middle of buffer we want to get substring from *)
subFromLeftAndRight (start, finish, curIdx, left, right) subFromLeftAndRight (start, finish, curIdx, left, right, endWith)
else else
let let
(* start = curIdx so only need to traverse right *) (* start = curIdx so only need to traverse right *)
val acc = subRightFromHere (curIdx, finish, right, []) val acc = subRightFromHere (curIdx, finish, right, [], endWith)
in in
String.concat acc String.concat acc
end end
in in
fun substringWithEnd (start, length, buffer : t, endWith) =
let
val finish = start + length
val {idx, leftStrings, rightStrings, ...} = buffer
in
sub (start, finish, idx, leftStrings, rightStrings, endWith)
end
fun nullSubstring (start, length, buffer : t) =
let
val finish = start + length
val {idx, leftStrings, rightStrings, ...} = buffer
val endWith = Char.chr 0
val endWith = Char.toString endWith
in
sub (start, finish, idx, leftStrings, rightStrings, endWith)
end
fun substring (start, length, buffer : t) = fun substring (start, length, buffer : t) =
let let
val finish = start + length val finish = start + length
val {idx, leftStrings, rightStrings, ...} = buffer val {idx, leftStrings, rightStrings, ...} = buffer
in in
sub (start, finish, idx, leftStrings, rightStrings) sub (start, finish, idx, leftStrings, rightStrings, "")
end end
end end