
* Extend compiler to allow bytes()/bytes as type * Add split_any, to_fixed_size, size, to_any_size, Int.to_bytes and String.to_bytes * Add tests * Use and and not andalso in unify, some things have side-effects * Bump to aebytecode v3.3.0 * Changelog + update documentation * fix wording in documentation
121 lines
4.4 KiB
Plaintext
121 lines
4.4 KiB
Plaintext
include "List.aes"
|
|
namespace String =
|
|
// Gives a bytes() representation of the string
|
|
function to_bytes(s : string) : bytes() = StringInternal.to_bytes(s)
|
|
|
|
// Computes the SHA3/Keccak hash of the string
|
|
function sha3(s : string) : hash = StringInternal.sha3(s)
|
|
// Computes the SHA256 hash of the string.
|
|
function sha256(s : string) : hash = StringInternal.sha256(s)
|
|
// Computes the Blake2B hash of the string.
|
|
function blake2b(s : string) : hash = StringInternal.blake2b(s)
|
|
|
|
// The length of a string - equivalent to List.lenght(to_list(s))
|
|
function length(s : string) : int = StringInternal.length(s)
|
|
// Concatenates `s1` and `s2`.
|
|
function concat(s1 : string, s2 : string) : string = StringInternal.concat(s1, s2)
|
|
// Concatenates a list of strings.
|
|
function
|
|
concats : (list(string)) => string
|
|
concats([]) = ""
|
|
concats(s :: ss) = List.foldl(StringInternal.concat, s, ss)
|
|
|
|
// Converts a `string` to a list of `char` - the code points are normalized, but
|
|
// composite characters are possibly converted to multiple `char`s.
|
|
function from_list(cs : list(char)) : string = StringInternal.from_list(cs)
|
|
// Converts a list of characters into a normalized UTF-8 string.
|
|
function to_list(s : string) : list(char) = StringInternal.to_list(s)
|
|
|
|
// Converts a string to lowercase.
|
|
function to_lower(s : string) = StringInternal.to_lower(s)
|
|
// Converts a string to uppercase.
|
|
function to_upper(s : string) = StringInternal.to_upper(s)
|
|
|
|
// Splits a string at (zero-based) index `ix`.
|
|
function split(i : int, s : string) : string * string =
|
|
let cs = StringInternal.to_list(s)
|
|
(StringInternal.from_list(List.take(i, cs)), StringInternal.from_list(List.drop(i, cs)))
|
|
|
|
// Returns the character/codepoint at (zero-based) index `ix`.
|
|
function at(ix : int, s : string) =
|
|
switch(List.drop(ix, StringInternal.to_list(s)))
|
|
[] => None
|
|
x :: _ => Some(x)
|
|
|
|
// Searches for `pat` in `str`, returning `Some(ix)` if `pat` is a substring
|
|
// of `str` starting at position `ix`, otherwise returns `None`.
|
|
function contains(str : string, substr : string) : option(int) =
|
|
if(substr == "") Some(0)
|
|
else
|
|
contains_(0, StringInternal.to_list(str), StringInternal.to_list(substr))
|
|
|
|
// Splits `s` into tokens, `pat` is the divider of tokens.
|
|
function tokens(s : string, pat : string) =
|
|
require(pat != "", "String.tokens: empty pattern")
|
|
tokens_(StringInternal.to_list(pat), StringInternal.to_list(s), [])
|
|
|
|
// Converts a decimal ("123", "-253") or a hexadecimal ("0xa2f", "-0xBBB") string
|
|
// into an integer. If the string doesn't contain a valid number `None` is returned.
|
|
function to_int(str : string) : option(int) =
|
|
let lst = StringInternal.to_list(str)
|
|
switch(is_prefix(['-'], lst))
|
|
None => to_int_pos(lst)
|
|
Some(s) => switch(to_int_pos(s))
|
|
None => None
|
|
Some(x) => Some(-x)
|
|
|
|
// Private helper functions below
|
|
private function to_int_pos(chs : list(char)) =
|
|
switch(is_prefix(['0', 'x'], chs))
|
|
None =>
|
|
to_int_(chs, ch_to_int_10, 0, 10)
|
|
Some(str) =>
|
|
to_int_(str, ch_to_int_16, 0, 16)
|
|
|
|
private function
|
|
tokens_(_, [], acc) = [StringInternal.from_list(List.reverse(acc))]
|
|
tokens_(pat, str, acc) =
|
|
switch(is_prefix(pat, str))
|
|
Some(str') =>
|
|
StringInternal.from_list(List.reverse(acc)) :: tokens_(pat, str', [])
|
|
None =>
|
|
let c :: cs = str
|
|
tokens_(pat, cs, c :: acc)
|
|
|
|
private function
|
|
contains_(_, [], _) = None
|
|
contains_(ix, str, substr) =
|
|
switch(is_prefix(substr, str))
|
|
None =>
|
|
let _ :: tailstr = str
|
|
contains_(ix + 1, tailstr, substr)
|
|
Some(_) =>
|
|
Some(ix)
|
|
|
|
private function
|
|
is_prefix([], ys) = Some(ys)
|
|
is_prefix(_, []) = None
|
|
is_prefix(x :: xs, y :: ys) =
|
|
if(x == y) is_prefix(xs, ys)
|
|
else None
|
|
|
|
private function
|
|
to_int_([], _, x, _) = Some(x)
|
|
to_int_(i :: is, value, x, b) =
|
|
switch(value(i))
|
|
None => None
|
|
Some(n) => to_int_(is, value, x * b + n, b)
|
|
|
|
private function ch_to_int_10(ch) =
|
|
let c = Char.to_int(ch)
|
|
if(c >= 48 && c =< 57) Some(c - 48)
|
|
else None
|
|
|
|
private function ch_to_int_16(ch) =
|
|
let c = Char.to_int(ch)
|
|
if(c >= 48 && c =< 57) Some(c - 48)
|
|
elif(c >= 65 && c =< 70) Some(c - 55)
|
|
elif(c >= 97 && c =< 102) Some(c - 87)
|
|
else None
|
|
|