hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 73967c5db7a596fe8d70d90a27d8492b21c82b7a
parent 0dff0b7458bec03afe552955b37c82561cbb0f86
Author: Byron Torres <b@torresjrjr.com>
Date:   Sat, 11 Dec 2021 00:40:11 +0000

rename formatting functions

Signed-off-by: Byron Torres <b@torresjrjr.com>

Diffstat:
Mdatetime/format.ha | 195+++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 100 insertions(+), 95 deletions(-)

diff --git a/datetime/format.ha b/datetime/format.ha @@ -1,6 +1,6 @@ use ascii; use errors; -use fmt; +use fmtlib = fmt; use io; use strconv; use strings; @@ -40,76 +40,9 @@ def MONTHS_SHORT: [_]str = [ "Oct", "Nov", "Dec", ]; -fn get_default_locale_string_index(iter: *strings::iterator, list: []str) (int | errors::invalid) = { - const name = strings::iter_str(iter); - if (len(name) == 0) { - return errors::invalid; - }; - for(let i = 0z; i < len(list); i += 1) { - if (strings::hasprefix(name, list[i])) { - // Consume name - for (let j = 0z; j < len(list[i]); j += 1) { - strings::next(iter); - }; - return (i: int) + 1; - }; - }; - return errors::invalid; -}; - -fn get_max_n_digits(iter: *strings::iterator, n: uint) (int | errors::invalid) = { - let buf: [64]u8 = [0...]; - let bufstr = strio::fixed(buf); - defer io::close(bufstr); - for (let i = 0z; i < n; i += 1) { - let r: rune = match (strings::next(iter)) { - case void => - break; - case let r: rune => - yield r; - }; - if (!ascii::isdigit(r)) { - strings::prev(iter); - break; - }; - match (strio::appendrune(bufstr, r)) { - case io::error => - return errors::invalid; - case => - void; - }; - }; - return match (strconv::stoi(strio::string(bufstr))) { - case let res: int => - yield res; - case => - yield errors::invalid; - }; -}; - -fn eat_one_rune(iter: *strings::iterator, needle: rune) (uint | errors::invalid) = { - let s_r = match (strings::next(iter)) { - case void => - return errors::invalid; - case let r: rune => - yield r; - }; - if (s_r == needle) { - return 1; - } else { - strings::prev(iter); - return 0; - }; -}; - -fn clamp_int(i: int, min: int, max: int) int = { - return if (i < min) { - yield min; - } else if (i > max) { - yield max; - } else { - yield i; - }; +// TODO: docstr, reconcile fn names +export fn parse(fmt: str, s: str, dt: *datetime) (void | errors::invalid) = { + strptime(fmt, s, dt)?; }; // Parses a datetime string into a [[datetime::datetime]]. @@ -117,8 +50,8 @@ fn clamp_int(i: int, min: int, max: int) int = { // The resulting [[datetime::datetime]] may not contain sufficient information // to be valid. Incremental parsing of data is possible, but the caller should // validate the [[datetime::datetime]] when appropriate. -export fn strptime(format: str, s: str, dt: *datetime) (void | errors::invalid) = { - const format_iter = strings::iter(format); +export fn strptime(fmt: str, s: str, dt: *datetime) (void | errors::invalid) = { + const format_iter = strings::iter(fmt); const s_iter = strings::iter(s); let escaped = false; for (true) { @@ -290,38 +223,38 @@ export fn strptime(format: str, s: str, dt: *datetime) (void | errors::invalid) dt.date.weekday = get_default_locale_string_index( &s_iter, WEEKDAYS_SHORT[..])?; if (eat_one_rune(&s_iter, ' ')? != 1) { - fmt::printfln("no space after weekday")!; + fmtlib::printfln("no space after weekday")!; return errors::invalid; }; dt.date.month = get_default_locale_string_index( &s_iter, MONTHS_SHORT[..])?; if (eat_one_rune(&s_iter, ' ')? != 1) { - fmt::printfln("no space after month")!; + fmtlib::printfln("no space after month")!; return errors::invalid; }; const max_n_digits = 2 - eat_one_rune(&s_iter, ' ')?; dt.date.day = clamp_int( get_max_n_digits(&s_iter, max_n_digits)?, 1, 31); if (eat_one_rune(&s_iter, ' ')? != 1) { - fmt::printfln("no space after day")!; + fmtlib::printfln("no space after day")!; return errors::invalid; }; dt.time.hour = clamp_int( get_max_n_digits(&s_iter, 2)?, 0, 23); if (eat_one_rune(&s_iter, ':')? != 1) { - fmt::printfln("no : after hour")!; + fmtlib::printfln("no : after hour")!; return errors::invalid; }; dt.time.min = clamp_int( get_max_n_digits(&s_iter, 2)?, 0, 59); if (eat_one_rune(&s_iter, ':')? != 1) { - fmt::printfln("no : after minute")!; + fmtlib::printfln("no : after minute")!; return errors::invalid; }; dt.time.sec = clamp_int( get_max_n_digits(&s_iter, 2)?, 0, 61); if (eat_one_rune(&s_iter, ' ')? != 1) { - fmt::printfln("no space after sec")!; + fmtlib::printfln("no space after sec")!; return errors::invalid; }; dt.date.year = get_max_n_digits(&s_iter, 4)?; @@ -431,24 +364,24 @@ export fn strptime(format: str, s: str, dt: *datetime) (void | errors::invalid) // Formats a [[datetime]] and writes it into a caller supplied buffer. // The returned string is borrowed from this buffer. -export fn bstrftime(buf: []u8, format: str, dt: *datetime) (str | errors::invalid | io::error) = { +export fn bstrftime(buf: []u8, fmt: str, dt: *datetime) (str | errors::invalid | io::error) = { let sink = strio::fixed(buf); defer io::close(sink); - fmttime(sink, format, dt)?; + format(sink, fmt, dt)?; return strio::string(sink); }; // Formats a [[datetime]] and writes it into a heap-allocated string. // The caller must free the return value. -export fn strftime(format: str, dt: *datetime) (str | errors::invalid | io::error) = { +export fn strftime(fmt: str, dt: *datetime) (str | errors::invalid | io::error) = { let sink = strio::dynamic(); - fmttime(sink, format, dt)?; + format(sink, fmt, dt)?; return strio::finish(sink); }; // Formats a [[datetime]] and writes it into a [[io::handle]]. -export fn fmttime(h: io::handle, format: str, dt: *datetime) (size | errors::invalid | io::error) = { - const iter = strings::iter(format); +export fn format(h: io::handle, fmt: str, dt: *datetime) (size | errors::invalid | io::error) = { + const iter = strings::iter(fmt); let escaped = false; let n = 0z; for (true) { @@ -491,9 +424,9 @@ export fn fmttime(h: io::handle, format: str, dt: *datetime) (size | errors::inv case 'D' => yield strftime("%m/%d/%y", dt)?; case 'd' => - yield fmt::asprintf("{:02}", day(dt)); + yield fmtlib::asprintf("{:02}", day(dt)); case 'e' => - yield fmt::asprintf("{:2}", day(dt)); + yield fmtlib::asprintf("{:2}", day(dt)); case 'F' => yield strftime("%Y-%m-%d", dt)?; case 'g' => @@ -503,13 +436,13 @@ export fn fmttime(h: io::handle, format: str, dt: *datetime) (size | errors::inv case 'G' => yield strconv::itos(isoweekyear(dt)); case 'H' => - yield fmt::asprintf("{:02}", hour(dt)); + yield fmtlib::asprintf("{:02}", hour(dt)); case 'I' => let mod_hour = hour(dt) % 12; if (mod_hour == 0) { mod_hour = 12; }; - yield fmt::asprintf("{:02}", mod_hour); + yield fmtlib::asprintf("{:02}", mod_hour); case 'j' => yield strconv::itos(yearday(dt)); case 'k' => @@ -521,9 +454,9 @@ export fn fmttime(h: io::handle, format: str, dt: *datetime) (size | errors::inv }; yield strconv::itos(mod_hour); case 'm' => - yield fmt::asprintf("{:02}", month(dt)); + yield fmtlib::asprintf("{:02}", month(dt)); case 'M' => - yield fmt::asprintf("{:02}", min(dt)); + yield fmtlib::asprintf("{:02}", min(dt)); case 'n' => yield "\n"; case 'N' => @@ -548,7 +481,7 @@ export fn fmttime(h: io::handle, format: str, dt: *datetime) (size | errors::inv case 'R' => yield strftime("%H:%M", dt)?; case 'S' => - yield fmt::asprintf("{:02}", sec(dt)); + yield fmtlib::asprintf("{:02}", sec(dt)); case 't' => yield "\t"; case 'T' => @@ -556,15 +489,15 @@ export fn fmttime(h: io::handle, format: str, dt: *datetime) (size | errors::inv case 'u' => yield strconv::itos(weekday(dt)); case 'U' => - // yield fmt::asprintf("{:02}", week_starting_sunday(dt)); + // yield fmtlib::asprintf("{:02}", week_starting_sunday(dt)); // TODO yield ""; case 'V' => - yield fmt::asprintf("{:02}", isoweek(dt)); + yield fmtlib::asprintf("{:02}", isoweek(dt)); case 'w' => yield strconv::itos(weekday(dt) % 7); case 'W' => - yield fmt::asprintf("{:02}", week(dt)); + yield fmtlib::asprintf("{:02}", week(dt)); case 'x' => // TODO: Localization yield strftime("%m/%d/%y", dt)?; @@ -597,3 +530,75 @@ export fn fmttime(h: io::handle, format: str, dt: *datetime) (size | errors::inv }; return n; }; + +fn get_default_locale_string_index(iter: *strings::iterator, list: []str) (int | errors::invalid) = { + const name = strings::iter_str(iter); + if (len(name) == 0) { + return errors::invalid; + }; + for(let i = 0z; i < len(list); i += 1) { + if (strings::hasprefix(name, list[i])) { + // Consume name + for (let j = 0z; j < len(list[i]); j += 1) { + strings::next(iter); + }; + return (i: int) + 1; + }; + }; + return errors::invalid; +}; + +fn get_max_n_digits(iter: *strings::iterator, n: uint) (int | errors::invalid) = { + let buf: [64]u8 = [0...]; + let bufstr = strio::fixed(buf); + defer io::close(bufstr); + for (let i = 0z; i < n; i += 1) { + let r: rune = match (strings::next(iter)) { + case void => + break; + case let r: rune => + yield r; + }; + if (!ascii::isdigit(r)) { + strings::prev(iter); + break; + }; + match (strio::appendrune(bufstr, r)) { + case io::error => + return errors::invalid; + case => + void; + }; + }; + return match (strconv::stoi(strio::string(bufstr))) { + case let res: int => + yield res; + case => + yield errors::invalid; + }; +}; + +fn eat_one_rune(iter: *strings::iterator, needle: rune) (uint | errors::invalid) = { + let s_r = match (strings::next(iter)) { + case void => + return errors::invalid; + case let r: rune => + yield r; + }; + if (s_r == needle) { + return 1; + } else { + strings::prev(iter); + return 0; + }; +}; + +fn clamp_int(i: int, min: int, max: int) int = { + return if (i < min) { + yield min; + } else if (i > max) { + yield max; + } else { + yield i; + }; +};