#include "common/string.h" #include "common/panic.h" #include "common/result.h" #include #include HeapString stringbuilder_build(StringBuilder* builder) { ASSERT(builder->length != 0, "builder cannot be empty"); if (*stringbuilder_get(builder, builder->length - 1) != '\0') stringbuilder_append(builder, '\0'); return heapstring_from(builder->data, builder->length); } RESULT_CTORS( HeapString, HeapString, UnescapeStringResult, unescaped_string_result ) UnescapeStringResult common_unescape_string(StringView source) { StringBuilder builder; stringbuilder_construct(&builder); size_t i = 0; while (i < source.length) { if (source.data[i] == '\\') { i++; if (i >= source.length) { stringbuilder_destroy(&builder); return unescaped_string_result_ok( heapstring_from_cstring("malformed escape sequence") ); } switch (source.data[i]) { case '0': stringbuilder_append(&builder, '\0'); break; case 't': stringbuilder_append(&builder, '\t'); break; case 'r': stringbuilder_append(&builder, '\r'); break; case 'n': stringbuilder_append(&builder, '\n'); break; default: stringbuilder_append(&builder, source.data[i]); break; } } else { stringbuilder_append(&builder, source.data[i]); } i++; } HeapString string = stringbuilder_build(&builder); stringbuilder_destroy(&builder); return unescaped_string_result_ok(string); } HeapString common_escape_string(StringView source) { StringBuilder builder; stringbuilder_construct(&builder); for (size_t i = 0; i < source.length; ++i) { switch (source.data[i]) { case '\0': stringbuilder_append(&builder, '\\'); stringbuilder_append(&builder, '0'); break; case '\t': stringbuilder_append(&builder, '\\'); stringbuilder_append(&builder, 't'); break; case '\r': stringbuilder_append(&builder, '\\'); stringbuilder_append(&builder, 'r'); break; case '\n': stringbuilder_append(&builder, '\\'); stringbuilder_append(&builder, 'n'); break; case '\\': stringbuilder_append(&builder, '\\'); stringbuilder_append(&builder, '\\'); break; case '\"': stringbuilder_append(&builder, '\\'); stringbuilder_append(&builder, '\"'); break; case '\'': stringbuilder_append(&builder, '\\'); stringbuilder_append(&builder, '\''); break; default: stringbuilder_append(&builder, source.data[i]); break; } } HeapString string = stringbuilder_build(&builder); stringbuilder_destroy(&builder); return string; }