add a substring function to line_gap.sml which is null terminated, which may be required for C FFI
This commit is contained in:
103
src/line_gap.sml
103
src/line_gap.sml
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user