diff --git a/docs/Stdlib.md b/docs/Stdlib.md index 71e7e5a..9407f69 100644 --- a/docs/Stdlib.md +++ b/docs/Stdlib.md @@ -141,6 +141,7 @@ String manipulation utilities. | `String_FromInt` | `func String_FromInt(n: int64) -> String` | Int to string | | `String_FromFloat` | `func String_FromFloat(f: float64) -> String` | Float to string | | `String_ToInt` | `func String_ToInt(s: String) -> int64` | String to int | +| `String_ToFloat` | `func String_ToFloat(s: String) -> float64` | String to float | ### Find, Replace & Format diff --git a/library/runtime/runtime.c b/library/runtime/runtime.c index 1da07e3..d210304 100644 --- a/library/runtime/runtime.c +++ b/library/runtime/runtime.c @@ -221,6 +221,11 @@ char* bux_strncpy(char* dest, const char* src, unsigned int n) { return strncpy(dest, src, (size_t)n); } +double bux_str_to_float(const char* s) { + if (!s) return 0.0; + return strtod(s, NULL); +} + /* String find: returns pointer to first occurrence of needle in haystack, or NULL */ const char* bux_strstr(const char* haystack, const char* needle) { if (!haystack || !needle) return NULL; diff --git a/library/std/Json.bux b/library/std/Json.bux index a4c294c..8f3dcff 100644 --- a/library/std/Json.bux +++ b/library/std/Json.bux @@ -236,7 +236,7 @@ func JsonParser_ParseString(p: *JsonParser) -> String { return ""; } JsonParser_Advance(p); - let start: uint = p.pos; + let sb: StringBuilder = StringBuilder_New(); while true { let c: int = JsonParser_Peek(p); if c == 0 || c == 34 { @@ -244,22 +244,40 @@ func JsonParser_ParseString(p: *JsonParser) -> String { } if c == 92 { JsonParser_Advance(p); - if JsonParser_Peek(p) == 0 { + let esc: int = JsonParser_Peek(p); + if esc == 0 { p.error = "Unterminated string escape"; + StringBuilder_Free(&sb); return ""; } + if esc == 110 { StringBuilder_AppendChar(&sb, 10 as char8); } // \n + else if esc == 116 { StringBuilder_AppendChar(&sb, 9 as char8); } // \t + else if esc == 114 { StringBuilder_AppendChar(&sb, 13 as char8); } // \r + else if esc == 98 { StringBuilder_AppendChar(&sb, 8 as char8); } // \b + else if esc == 102 { StringBuilder_AppendChar(&sb, 12 as char8); } // \f + else if esc == 34 { StringBuilder_AppendChar(&sb, 34 as char8); } // \" + else if esc == 92 { StringBuilder_AppendChar(&sb, 92 as char8); } // \\ + else { + // Unknown escape — keep literal + StringBuilder_AppendChar(&sb, 92 as char8); + StringBuilder_AppendChar(&sb, esc as char8); + } JsonParser_Advance(p); } else { + StringBuilder_AppendChar(&sb, c as char8); JsonParser_Advance(p); } } - let endPos: uint = p.pos; if JsonParser_Peek(p) != 34 { p.error = "Unterminated string"; + StringBuilder_Free(&sb); return ""; } JsonParser_Advance(p); - return String_Slice(p.src, start, endPos - start); + let raw: String = StringBuilder_Build(&sb); + let result: String = String_Copy(raw); + StringBuilder_Free(&sb); + return result; } func JsonParser_ParseNumber(p: *JsonParser) -> JsonValue { @@ -288,8 +306,8 @@ func JsonParser_ParseNumber(p: *JsonParser) -> JsonValue { } } let numStr: String = String_Slice(p.src, start, p.pos - start); - let n: int64 = String_ToInt(numStr); - return Json_Number(n as float64); + let n: float64 = String_ToFloat(numStr); + return Json_Number(n); } func JsonParser_ParseArray(p: *JsonParser) -> JsonValue { diff --git a/library/std/String.bux b/library/std/String.bux index c30ed26..878a18c 100644 --- a/library/std/String.bux +++ b/library/std/String.bux @@ -179,6 +179,12 @@ func String_Replace(s: String, old: String, new: String) -> String { return result; } +extern func bux_str_to_float(s: String) -> float64; + +func String_ToFloat(s: String) -> float64 { + return bux_str_to_float(s); +} + func String_FromFloat(f: float64) -> String { return bux_float_to_string(f); }