]> git.lizzy.rs Git - nothing.git/commitdiff
Merge pull request #1235 from tsoding/remove-line-stream
authorAlexey Kutepov <reximkut@gmail.com>
Sat, 4 Jan 2020 21:42:47 +0000 (04:42 +0700)
committerGitHub <noreply@github.com>
Sat, 4 Jan 2020 21:42:47 +0000 (04:42 +0700)
Remove line stream

39 files changed:
CMakeLists.txt
nothing.c
src/color.c
src/color.h
src/dynarray.c
src/dynarray.h
src/game/level.c
src/game/level/background.c
src/game/level/boxes.c
src/game/level/goals.c
src/game/level/labels.c
src/game/level/lava.c
src/game/level/lava/wavy_rect.c
src/game/level/level_editor.c
src/game/level/level_editor/background_layer.c
src/game/level/level_editor/background_layer.h
src/game/level/level_editor/color_picker.c
src/game/level/level_editor/color_picker.h
src/game/level/level_editor/label_layer.c
src/game/level/level_editor/label_layer.h
src/game/level/level_editor/player_layer.c
src/game/level/level_editor/player_layer.h
src/game/level/level_editor/point_layer.c
src/game/level/level_editor/point_layer.h
src/game/level/level_editor/rect_layer.c
src/game/level/level_editor/rect_layer.h
src/game/level/platforms.c
src/game/level/player.c
src/game/level/regions.c
src/game/level/rigid_bodies.c
src/system/file.c
src/system/file.h
src/system/line_stream.c [deleted file]
src/system/line_stream.h [deleted file]
src/system/memory.h [new file with mode: 0644]
src/system/s.h
src/system/str.c
src/system/str.h
src/ui/console.c

index 218247375ba39f97ba8bc805a91ed6ca898df0f7..23e623e45922095de400dfd251ff40efec0804b6 100644 (file)
@@ -145,8 +145,6 @@ add_executable(nothing
   src/game/level/level_editor/undo_history.c
   src/game/level/level_editor/action_picker.h
   src/game/level/level_editor/action_picker.c
-  src/system/line_stream.h
-  src/system/line_stream.c
   src/system/log.h
   src/system/log.c
   src/system/lt.h
index d460dba188ec545104d5f86ce0889a1c73394c82..ba503438a35e219ff976c0f7c86a638fd992bb31 100644 (file)
--- a/nothing.c
+++ b/nothing.c
@@ -43,7 +43,6 @@
 #include "src/game/level/level_editor/background_layer.c"
 #include "src/game/level/level_editor/undo_history.c"
 #include "src/game/level/level_editor/action_picker.c"
-#include "src/system/line_stream.c"
 #include "src/system/log.c"
 #include "src/system/lt_adapters.c"
 #include "src/system/nth_alloc.c"
index b0fc3728ceb0e8b39b5eddec55e3b4eef7c08f32..eb03f55f928a573b9a11d547e136b1efd5d0fbe4 100644 (file)
@@ -83,6 +83,17 @@ Color hexstr(const char *hexstr)
         1.0f);
 }
 
+Color hexs(String input)
+{
+    if (input.count < 6) return COLOR_BLACK;
+
+    return rgba(
+        parse_color_component(input.data) / 255.0f,
+        parse_color_component(input.data + 2) / 255.0f,
+        parse_color_component(input.data + 4) / 255.0f,
+        1.0f);
+}
+
 SDL_Color color_for_sdl(Color color)
 {
     const SDL_Color result = {
index 937782256b1057093ed08d4501ed89120654c91a..cffb7cf613f7e787d84fc6d76f58cb3447a27935 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <stdio.h>
 #include <SDL.h>
+#include "./system/s.h"
 
 #define COLOR_BLACK rgba(0.0f, 0.0f, 0.0f, 1.0f)
 #define COLOR_WHITE rgba(1.0f, 1.0f, 1.0f, 1.0f)
@@ -16,6 +17,7 @@ Color rgba(float r, float g, float b, float a);
 Color hsla(float h, float s, float l, float a);
 Color rgba_to_hsla(Color color);
 Color hexstr(const char *hexstr);
+Color hexs(String input);
 SDL_Color color_for_sdl(Color color);
 
 int color_hex_to_stream(Color color, FILE *stream);
index f6a7f8e51329fe657b933ae6f9c352c8315adc32..214e4d096326bbb1ae672624bb8f9b97bbf17d5f 100644 (file)
@@ -7,8 +7,6 @@
 #include "system/nth_alloc.h"
 #include "dynarray.h"
 
-#define DYNARRAY_INIT_CAPACITY 8
-
 void *dynarray_pointer_at(const Dynarray *dynarray, size_t index)
 {
     trace_assert(index < dynarray->count);
@@ -21,34 +19,11 @@ void dynarray_clear(Dynarray *dynarray)
     dynarray->count = 0;
 }
 
-static
-int dynarray_grow(Dynarray *dynarray)
-{
-    if (dynarray->count < dynarray->capacity) {
-        return 0;
-    }
-
-    if (dynarray->capacity == 0) {
-        dynarray->capacity = DYNARRAY_INIT_CAPACITY;
-    } else {
-        dynarray->capacity *= 2;
-    }
-
-    dynarray->data = nth_realloc(
-        dynarray->data,
-        dynarray->capacity * dynarray->element_size * 2);
-
-    return 0;
-}
-
 int dynarray_push(Dynarray *dynarray, const void *element)
 {
     trace_assert(dynarray);
     trace_assert(element);
-
-    if (dynarray_grow(dynarray) < 0) {
-        return -1;
-    }
+    trace_assert(dynarray->count < DYNARRAY_CAPACITY);
 
     memcpy(
         (char*) dynarray->data + dynarray->count * dynarray->element_size,
@@ -92,9 +67,7 @@ void dynarray_insert_before(Dynarray *dynarray, size_t index, void *element)
 {
     trace_assert(dynarray);
     trace_assert(element);
-    trace_assert(index <= dynarray->count);
-
-    dynarray_grow(dynarray);
+    trace_assert(index < dynarray->count);
 
     memmove(
         (uint8_t*) dynarray->data + (index + 1) * dynarray->element_size,
@@ -112,10 +85,7 @@ void dynarray_insert_before(Dynarray *dynarray, size_t index, void *element)
 int dynarray_push_empty(Dynarray *dynarray)
 {
     trace_assert(dynarray);
-
-    if (dynarray_grow(dynarray) < 0) {
-        return -1;
-    }
+    trace_assert(dynarray->count < DYNARRAY_CAPACITY);
 
     memset(
         (char*) dynarray->data + dynarray->count * dynarray->element_size,
index b86345038ac526d12713570346eb3040addedd58..39bc1b9157383b92b1910e41b03312a96b7c1a6b 100644 (file)
@@ -5,9 +5,10 @@
 #include <stdbool.h>
 #include <stdint.h>
 
+#define DYNARRAY_CAPACITY 256
+
 typedef struct {
     size_t element_size;
-    size_t capacity;
     size_t count;
     void *data;
 } Dynarray;
@@ -17,9 +18,8 @@ Dynarray create_dynarray(size_t element_size)
 {
     Dynarray result = {
         .element_size = element_size,
-        .capacity = 0,
         .count = 0,
-        .data = NULL
+        .data = malloc(DYNARRAY_CAPACITY * element_size)
     };
     return result;
 }
index b833895740fc21a8ab8046d76ad6f51114d1bab9..eeb5b65478b93c2a4145b50a22b23eddec18bd23 100644 (file)
@@ -18,7 +18,6 @@
 #include "game/level/level_editor/player_layer.h"
 #include "game/level/level_editor/label_layer.h"
 #include "game/level/level_editor/background_layer.h"
-#include "system/line_stream.h"
 #include "system/log.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
index ba6ed8fb3e538a943a40f27cba51860d661b61fc..7b13823f14e1a873687b08dd33cee5c333d0d787 100644 (file)
@@ -3,7 +3,6 @@
 #include "game/level/background.h"
 #include "math/rand.h"
 #include "math/rect.h"
-#include "system/line_stream.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
 #include "system/log.h"
index 64bdd893f8eca25add81184c21960e7f9b65f7d8..fa6827df341471080e4d169eb4b85e4776c38f84 100644 (file)
@@ -6,7 +6,6 @@
 #include "game/level/player.h"
 #include "game/level/rigid_bodies.h"
 #include "math/rand.h"
-#include "system/line_stream.h"
 #include "system/log.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
index 885383d0e064e3fc1b591e3cf9d1bcc28a183387..1d675f2f5f9debbad1487bda5468e8c0c2be1aa7 100644 (file)
@@ -7,7 +7,6 @@
 #include "goals.h"
 #include "math/pi.h"
 #include "math/triangle.h"
-#include "system/line_stream.h"
 #include "system/log.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
index 95ea708775fe2f2b184209775de286888f404271..9526463c1f58c02a57cd631dafafa0214e2a7801 100644 (file)
@@ -5,7 +5,6 @@
 #include "game/camera.h"
 #include "game/level/labels.h"
 #include "game/level/level_editor/label_layer.h"
-#include "system/line_stream.h"
 #include "system/log.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
index b6f66515ad393d40cc32708a9aa301ba70b5e611..ec580d4c075fe526ffac321a4f0ba7d5ee13990e 100644 (file)
@@ -7,7 +7,6 @@
 #include "lava.h"
 #include "math/rect.h"
 #include "system/lt.h"
-#include "system/line_stream.h"
 #include "system/nth_alloc.h"
 #include "system/log.h"
 #include "game/level/level_editor/rect_layer.h"
index 5c3e14081e13cee1e5917f7ca0e10992be8747b4..d41bc4398e104e89d83240cb7d6dda39b208af48 100644 (file)
@@ -5,7 +5,6 @@
 #include <time.h>
 
 #include "math/pi.h"
-#include "system/line_stream.h"
 #include "system/log.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
index 11af440e5e463a541e20980e8c13c23282f21593..36f80f45ae80d86fb832cf3ada2464040feab5e9 100644 (file)
 #include "system/str.h"
 #include "config.h"
 #include "math/extrema.h"
+#include "system/file.h"
 
 #include "level_editor.h"
 
 #define LEVEL_FOLDER_MAX_LENGTH 512
-#define LEVEL_LINE_MAX_LENGTH 512
 #define LEVEL_EDITOR_EDIT_FIELD_SIZE vec(5.0f, 5.0f)
 #define LEVEL_EDITOR_EDIT_FIELD_COLOR COLOR_BLACK
 
 #define LEVEL_EDITOR_NOTICE_SCALE vec(10.0f, 10.0f)
 #define LEVEL_EDITOR_NOTICE_DURATION 1.0f
 #define LEVEL_EDITOR_NOTICE_PADDING_TOP 100.0f
+#define LEVEL_EDITOR_TMPMEM_CAPACITY (640 * KILO)
 
 static int level_editor_dump(LevelEditor *level_editor);
 
@@ -172,110 +173,37 @@ LevelEditor *create_level_editor_from_file(const char *file_name, Cursor *cursor
             string_duplicate(file_name, NULL),
             free);
 
-    LineStream *level_stream = PUSH_LT(
-        lt,
-        create_line_stream(
-            file_name,
-            "r",
-            LEVEL_LINE_MAX_LENGTH),
-        destroy_line_stream);
-    if (level_stream == NULL) {
-        RETURN_LT(lt, NULL);
-    }
+    Memory tmpmem = {
+        .capacity = LEVEL_EDITOR_TMPMEM_CAPACITY,
+        .buffer = malloc(LEVEL_EDITOR_TMPMEM_CAPACITY),
+    };
+    trace_assert(tmpmem.buffer);
 
-    const char *line = line_stream_next(level_stream);
-    if (line == NULL) {
-        RETURN_LT(lt, NULL);
-    }
+    String input = read_whole_file(&tmpmem, file_name);
+    trace_assert(input.data);
+
+    String version = trim(chop_by_delim(&input, '\n'));
 
-    char version[METADATA_VERSION_MAX_SIZE] = {0};
-    memcpy(version, line,
-           MIN(size_t,
-               strlen(line),
-               METADATA_VERSION_MAX_SIZE - 1));
-    trim_endline(version);
-
-    if (strcmp(version, "1") == 0) {
-        if (line_stream_next(level_stream) == NULL)
-            RETURN_LT(lt, NULL);
-    } else if (strcmp(version, "2") == 0) {
+    if (string_equal(version, STRING_LIT("1"))) {
+        chop_by_delim(&input, '\n');
+    } else if (string_equal(version, STRING_LIT("2"))) {
         // Nothing
     } else {
         log_fail("Version `%s` is not supported. Expected version `%s`.\n",
-                 version, VERSION);
-        RETURN_LT(lt, NULL);
-    }
-
-    if (background_layer_read_from_line_stream(
-            &level_editor->background_layer,
-            level_stream) < 0) {
-        RETURN_LT(lt, NULL);
-    }
-
-    level_editor->player_layer =
-        create_player_layer_from_line_stream(level_stream);
-
-    level_editor->platforms_layer =
-        PUSH_LT(
-            lt,
-            create_rect_layer_from_line_stream(level_stream, "platform", cursor),
-            destroy_rect_layer);
-    if (level_editor->platforms_layer == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-
-    level_editor->goals_layer = PUSH_LT(
-        lt,
-        create_point_layer_from_line_stream(level_stream, "goal"),
-        destroy_point_layer);
-    if (level_editor->goals_layer == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-
-    level_editor->lava_layer =
-        PUSH_LT(
-            lt,
-            create_rect_layer_from_line_stream(level_stream, "lava", cursor),
-            destroy_rect_layer);
-    if (level_editor->lava_layer == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-
-    level_editor->back_platforms_layer =
-        PUSH_LT(
-            lt,
-            create_rect_layer_from_line_stream(level_stream, "back_platform", cursor),
-            destroy_rect_layer);
-    if (level_editor->back_platforms_layer == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-
-    level_editor->boxes_layer =
-        PUSH_LT(
-            lt,
-            create_rect_layer_from_line_stream(level_stream, "box", cursor),
-            destroy_rect_layer);
-    if (level_editor->boxes_layer == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-
-    level_editor->label_layer =
-        PUSH_LT(
-            lt,
-            create_label_layer_from_line_stream(level_stream, "label"),
-            destroy_label_layer);
-    if (level_editor->label_layer == NULL) {
+                 string_to_cstr(&tmpmem, version),
+                 VERSION);
         RETURN_LT(lt, NULL);
     }
 
-    level_editor->regions_layer =
-        PUSH_LT(
-            lt,
-            create_rect_layer_from_line_stream(level_stream, "region", cursor),
-            destroy_rect_layer);
-    if (level_editor->regions_layer == NULL) {
-        RETURN_LT(lt, NULL);
-    }
+    level_editor->background_layer = chop_background_layer(&input);
+    level_editor->player_layer = chop_player_layer(&tmpmem, &input);
+    level_editor->platforms_layer = chop_rect_layer(&tmpmem, &input, "platform", cursor);
+    level_editor->goals_layer = chop_point_layer(&tmpmem, &input, "goal");
+    level_editor->lava_layer = chop_rect_layer(&tmpmem, &input, "lava", cursor);
+    level_editor->back_platforms_layer = chop_rect_layer(&tmpmem, &input, "back_platform", cursor);
+    level_editor->boxes_layer = chop_rect_layer(&tmpmem, &input, "box", cursor);
+    level_editor->label_layer = chop_label_layer(&tmpmem, &input, "label");
+    level_editor->regions_layer = chop_rect_layer(&tmpmem, &input, "region", cursor),
 
     level_editor->layers[LAYER_PICKER_BOXES] = rect_layer_as_layer(level_editor->boxes_layer);
     level_editor->layers[LAYER_PICKER_PLATFORMS] = rect_layer_as_layer(level_editor->platforms_layer);
@@ -300,6 +228,10 @@ LevelEditor *create_level_editor_from_file(const char *file_name, Cursor *cursor
 
     level_editor->camera_scale = 1.0f;
 
+    log_info("%ld bytes of tmp memory consumed during parsing the level\n", tmpmem.size);
+
+    free(tmpmem.buffer);
+
     return level_editor;
 }
 
index 158eff00a673ecf2c7ac854427e48a51cef40063..3ac3c5da4646b2e1891ccc5be1c940bc41cf0927 100644 (file)
@@ -17,18 +17,10 @@ BackgroundLayer create_background_layer(Color color)
     return layer;
 }
 
-int background_layer_read_from_line_stream(BackgroundLayer *layer,
-                                           LineStream *line_stream)
+BackgroundLayer chop_background_layer(String *input)
 {
-    if (color_picker_read_from_line_stream(
-            &layer->color_picker,
-            line_stream) < 0) {
-        return -1;
-    }
-
-    layer->prev_color = color_picker_rgba(&layer->color_picker);
-
-    return 0;
+    String line = trim(chop_by_delim(input, '\n'));
+    return create_background_layer(hexs(line));
 }
 
 int background_layer_render(BackgroundLayer *layer,
index f63d361505135a14b8a975c32c1cd7d9957efc1c..998309c22bcbe05a675143a213bd2e2262d7c0d1 100644 (file)
@@ -2,6 +2,7 @@
 #define BACKGROUND_LAYER_H_
 
 #include "color_picker.h"
+#include "system/s.h"
 
 typedef struct {
     ColorPicker color_picker;
@@ -9,8 +10,7 @@ typedef struct {
 } BackgroundLayer;
 
 BackgroundLayer create_background_layer(Color color);
-int background_layer_read_from_line_stream(BackgroundLayer *layer,
-                                           LineStream *line_stream);
+BackgroundLayer chop_background_layer(String *input);
 
 static inline
 LayerPtr background_layer_as_layer(BackgroundLayer *layer)
index 6cacb7eb1f2e4ea063ae50e652a0c3c4fa728a54..c317f3279eff4d7cc0830be853c5c630c3e68039 100644 (file)
@@ -3,7 +3,6 @@
 
 #include "game/level/boxes.h"
 #include "system/stacktrace.h"
-#include "system/line_stream.h"
 #include "system/log.h"
 #include "game/camera.h"
 #include "color_picker.h"
@@ -36,24 +35,6 @@ ColorPicker create_color_picker_from_rgba(Color color)
     return color_picker;
 }
 
-int color_picker_read_from_line_stream(ColorPicker *color_picker,
-                                       LineStream *line_stream)
-{
-    char color[7];
-    const char *line = line_stream_next(line_stream);
-    if (line == NULL) {
-        return -1;
-    }
-
-    if (sscanf(line, "%6s", color) == EOF) {
-        log_fail("Could not read color\n");
-    }
-
-    *color_picker = create_color_picker_from_rgba(hexstr(color));
-
-    return 0;
-}
-
 int color_picker_render(const ColorPicker *color_picker,
                         const Camera *camera)
 {
index 2d60a085fdb132ae9ca6141f7ef3f9a03d6ede30..f0c4817bc2cb5d7e876cd014e8efab7fd75e629a 100644 (file)
@@ -16,13 +16,9 @@ typedef struct {
     Slider sliders[COLOR_SLIDER_N];
 } ColorPicker;
 
-typedef struct LineStream LineStream;
 
 ColorPicker create_color_picker_from_rgba(Color color);
 
-int color_picker_read_from_line_stream(ColorPicker *color_picker,
-                                       LineStream *line_stream);
-
 int color_picker_render(const ColorPicker *color_picker,
                         const Camera *camera);
 int color_picker_event(ColorPicker *color_picker,
index 739c2dae1995cebdd8f42ed0e975ca5f9a5d0ad7..9c7bf9c2507f02a2748c56080c4e8816e0c9913d 100644 (file)
@@ -2,7 +2,6 @@
 
 #include <SDL.h>
 
-#include "system/line_stream.h"
 #include "system/stacktrace.h"
 #include "system/nth_alloc.h"
 #include "system/lt.h"
@@ -200,61 +199,47 @@ LabelLayer *create_label_layer(const char *id_name_prefix)
     return label_layer;
 }
 
-LabelLayer *create_label_layer_from_line_stream(LineStream *line_stream, const char *id_name_prefix)
+LabelLayer *chop_label_layer(Memory *memory,
+                             String *input,
+                             const char *id_name_prefix)
 {
-    trace_assert(line_stream);
-    LabelLayer *label_layer = create_label_layer(id_name_prefix);
+    trace_assert(memory);
+    trace_assert(input);
+    trace_assert(id_name_prefix);
 
-    if (label_layer == NULL) {
-        RETURN_LT(label_layer->lt, NULL);
-    }
-
-    const char *line = line_stream_next(line_stream);
-    if (line == NULL) {
-        log_fail("Could not read amount of labels\n");
-        RETURN_LT(label_layer->lt, NULL);
-    }
+    LabelLayer *label_layer = create_label_layer(id_name_prefix);
 
-    size_t n = 0;
-    if (sscanf(line, "%zu", &n) == EOF) {
-        log_fail("Could not parse amount of labels\n");
-        RETURN_LT(label_layer->lt, NULL);
-    }
+    int n = atoi(string_to_cstr(memory, trim(chop_by_delim(input, '\n'))));
+    char id[LABEL_LAYER_ID_MAX_SIZE];
+    char label_text[LABEL_LAYER_TEXT_MAX_SIZE];
+    for (int i = 0; i < n; ++i) {
+        String meta = trim(chop_by_delim(input, '\n'));
 
-    for (size_t i = 0; i < n; ++i) {
-        char hex[7];
-        char id[LABEL_LAYER_ID_MAX_SIZE];
+        String string_id = trim(chop_word(&meta));
         Vec2f position;
-
-        line = line_stream_next(line_stream);
-        if (line == NULL) {
-            log_fail("Could not read label meta info\n");
-            RETURN_LT(label_layer->lt, NULL);
-        }
-
-        if (sscanf(
-                line,
-                "%"STRINGIFY(LABEL_LAYER_ID_MAX_SIZE)"s%f%f%6s\n",
-                id, &position.x, &position.y, hex) == EOF) {
-            log_fail("Could not parse label meta info\n");
-            RETURN_LT(label_layer->lt, NULL);
-        }
-
-        Color color = hexstr(hex);
+        position.x = strtof(string_to_cstr(memory, trim(chop_word(&meta))), NULL);
+        position.y = strtof(string_to_cstr(memory, trim(chop_word(&meta))), NULL);
+        Color color = hexs(trim(chop_word(&meta)));
+
+        memset(id, 0, LABEL_LAYER_ID_MAX_SIZE);
+        memcpy(
+            id,
+            string_id.data,
+            min_size_t(LABEL_LAYER_ID_MAX_SIZE - 1, string_id.count));
+
+        String label_text_string =
+            trim(chop_by_delim(input, '\n'));
+        memset(label_text, 0, LABEL_LAYER_TEXT_MAX_SIZE);
+        memcpy(
+            label_text,
+            label_text_string.data,
+            min_size_t(LABEL_LAYER_TEXT_MAX_SIZE - 1,
+                       label_text_string.count));
 
         dynarray_push(&label_layer->ids, id);
         dynarray_push(&label_layer->positions, &position);
         dynarray_push(&label_layer->colors, &color);
-
-        line = line_stream_next(line_stream);
-        if (line == NULL) {
-            log_fail("Could not read label text\n");
-        }
-
-        char label_text[LABEL_LAYER_TEXT_MAX_SIZE] = {0};
-        memcpy(label_text, line, LABEL_LAYER_TEXT_MAX_SIZE - 1);
-        trim_endline(label_text);
-        dynarray_push(&label_layer->texts, &label_text);
+        dynarray_push(&label_layer->texts, label_text);
     }
 
     return label_layer;
index 6d8d710fd9bb108983b55e84a33d2578563b97de..00454a1bbf159f72f9fea845f8eb19d856d23246 100644 (file)
 #define LABEL_LAYER_TEXT_MAX_SIZE 256
 
 typedef struct LabelLayer LabelLayer;
-typedef struct LineStream LineStream;
 
 LayerPtr label_layer_as_layer(LabelLayer *label_layer);
 
 // NOTE: create_label_layer and create_label_layer_from_line_stream do
 // not own id_name_prefix
 LabelLayer *create_label_layer(const char *id_name_prefix);
-LabelLayer *create_label_layer_from_line_stream(LineStream *line_stream,
-                                                const char *id_name_prefix);
+LabelLayer *chop_label_layer(Memory *memory,
+                             String *input,
+                             const char *id_name_prefix);
 void destroy_label_layer(LabelLayer *label_layer);
 
 int label_layer_render(const LabelLayer *label_layer,
index 711ade5b300f3e9afcd91b9f9846288a06e052ae..0e7bd8d8e635a9920e7e66ae07c37ba7e84eca3c 100644 (file)
@@ -8,6 +8,7 @@
 #include "system/nth_alloc.h"
 #include "system/log.h"
 #include "undo_history.h"
+#include "system/memory.h"
 
 typedef struct {
     PlayerLayer *layer;
@@ -50,27 +51,17 @@ PlayerLayer create_player_layer(Vec2f position, Color color)
     };
 }
 
-PlayerLayer create_player_layer_from_line_stream(LineStream *line_stream)
+PlayerLayer chop_player_layer(Memory *memory, String *input)
 {
-    trace_assert(line_stream);
+    trace_assert(memory);
+    trace_assert(input);
 
-    const char *line = line_stream_next(line_stream);
-    trace_assert(line);
+    String line = chop_by_delim(input, '\n');
+    float x = strtof(string_to_cstr(memory, chop_word(&line)), NULL);
+    float y = strtof(string_to_cstr(memory, chop_word(&line)), NULL);
+    Color color = hexs(chop_word(&line));
 
-    char colorstr[7] = "000000";
-    Vec2f position = vec(0.0f, 0.0f);
-
-    const int bound =
-        sscanf(line, "%f%f%6s", &position.x, &position.y, colorstr);
-
-#define BOUND_EXPECTED 3
-    if (bound != BOUND_EXPECTED) {
-        log_fail("Could not read Player Layer properly. Parsed tokens: %d. Expected: %d\n",
-                 bound, BOUND_EXPECTED);
-    }
-#undef BOUND_EXPECTED
-
-    return create_player_layer(position, hexstr(colorstr));
+    return create_player_layer(vec(x, y), color);
 }
 
 LayerPtr player_layer_as_layer(PlayerLayer *player_layer)
index 3fa4c8e517f363a617ebe11c378bf30aedfaf0f4..6144f3ff0ffa50d56c06a3e0cf99ebdea122e3f9 100644 (file)
@@ -4,7 +4,8 @@
 #include "color_picker.h"
 #include "layer.h"
 #include "system/lt.h"
-#include "system/line_stream.h"
+#include "system/memory.h"
+#include "system/s.h"
 
 typedef struct {
     Vec2f position;
@@ -13,7 +14,7 @@ typedef struct {
 } PlayerLayer;
 
 PlayerLayer create_player_layer(Vec2f position, Color color);
-PlayerLayer create_player_layer_from_line_stream(LineStream *line_stream);
+PlayerLayer chop_player_layer(Memory *memory, String *input);
 
 LayerPtr player_layer_as_layer(PlayerLayer *player_layer);
 int player_layer_render(const PlayerLayer *player_layer,
index 0050d95edb7e9b70286dfc2f9499d0331015e226..c0550919315a9e954b5d361825177c25b82059f1 100644 (file)
@@ -4,7 +4,6 @@
 
 #include "dynarray.h"
 #include "game/camera.h"
-#include "system/line_stream.h"
 #include "system/log.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
@@ -197,43 +196,38 @@ PointLayer *create_point_layer(const char *id_name_prefix)
     return point_layer;
 }
 
-PointLayer *create_point_layer_from_line_stream(LineStream *line_stream,
-                                                const char *id_name_prefix)
+PointLayer *chop_point_layer(Memory *memory,
+                             String *input,
+                             const char *id_name_prefix)
 {
-    trace_assert(line_stream);
+    trace_assert(memory);
+    trace_assert(input);
+    trace_assert(id_name_prefix);
 
     PointLayer *point_layer = create_point_layer(id_name_prefix);
 
-    size_t count = 0;
-    if (sscanf(
-            line_stream_next(line_stream),
-            "%zu",
-            &count) == EOF) {
-        log_fail("Could not read amount of points");
-        RETURN_LT(point_layer->lt, NULL);
-    }
-
-    char color_name[7];
-    char id[ID_MAX_SIZE];
-    float x, y;
-    for (size_t i = 0; i < count; ++i) {
-        if (sscanf(
-                line_stream_next(line_stream),
-                "%"STRINGIFY(ID_MAX_SIZE)"s%f%f%6s",
-                id, &x, &y, color_name) < 0) {
-            log_fail("Could not read %dth goal\n", i);
-            RETURN_LT(point_layer->lt, NULL);
-        }
-        const Color color = hexstr(color_name);
-        const Vec2f point = vec(x, y);
+    int n = atoi(string_to_cstr(memory, trim(chop_by_delim(input, '\n'))));
+    char id[ENTITY_MAX_ID_SIZE];
+    for (int i = 0; i < n; ++i) {
+        String line = trim(chop_by_delim(input, '\n'));
+        String string_id = trim(chop_word(&line));
+        Vec2f point;
+        point.x = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        point.y = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        Color color = hexs(trim(chop_word(&line)));
+
+        memset(id, 0, ENTITY_MAX_ID_SIZE);
+        memcpy(
+            id,
+            string_id.data,
+            min_size_t(ENTITY_MAX_ID_SIZE - 1, string_id.count));
 
-        dynarray_push(&point_layer->colors, &color);
         dynarray_push(&point_layer->positions, &point);
+        dynarray_push(&point_layer->colors, &color);
         dynarray_push(&point_layer->ids, id);
     }
 
     point_layer->selection = -1;
-
     point_layer->color_picker = create_color_picker_from_rgba(COLOR_RED);
 
     return point_layer;
index 0260b61296d40f670cc07392d7d56a816cebf40c..d08df7104b541a4f8e86edd2faa9f61f4b1fa9cb 100644 (file)
@@ -8,14 +8,14 @@
 #define ID_MAX_SIZE 36
 
 typedef struct PointLayer PointLayer;
-typedef struct LineStream LineStream;
 
 LayerPtr point_layer_as_layer(PointLayer *point_layer);
 // NOTE: create_point_layer and create_point_layer_from_line_stream do
 // not own id_name_prefix
 PointLayer *create_point_layer(const char *id_name_prefix);
-PointLayer *create_point_layer_from_line_stream(LineStream *line_stream,
-                                                const char *id_name_prefix);
+PointLayer *chop_point_layer(Memory *memory,
+                             String *input,
+                             const char *id_name_prefix);
 void destroy_point_layer(PointLayer *point_layer);
 
 int point_layer_render(const PointLayer *point_layer,
index aa4f75c8f40d07d6e53979415b5267ec92c71088..778c324cf8f2f9fc9d4a1c069f103153f3ec941e 100644 (file)
@@ -10,7 +10,6 @@
 #include "color.h"
 #include "rect_layer.h"
 #include "dynarray.h"
-#include "system/line_stream.h"
 #include "color_picker.h"
 #include "system/str.h"
 #include "ui/edit_field.h"
@@ -18,6 +17,7 @@
 #include "game/level/action.h"
 #include "action_picker.h"
 #include "game.h"
+#include "math/extrema.h"
 
 #define RECT_LAYER_SELECTION_THICCNESS 15.0f
 #define RECT_LAYER_ID_LABEL_SIZE vec(3.0f, 3.0f)
@@ -886,70 +886,59 @@ RectLayer *create_rect_layer(const char *id_name_prefix, Cursor *cursor)
     return layer;
 }
 
-RectLayer *create_rect_layer_from_line_stream(LineStream *line_stream,
-                                              const char *id_name_prefix,
-                                              Cursor *cursor)
+RectLayer *chop_rect_layer(Memory *memory,
+                           String *input,
+                           const char *id_name_prefix,
+                           Cursor *cursor)
 {
-    trace_assert(line_stream);
+    trace_assert(memory);
+    trace_assert(input);
 
     RectLayer *layer = create_rect_layer(id_name_prefix, cursor);
-    if (layer == NULL) {
-        return NULL;
-    }
-
-    const char *line = line_stream_next(line_stream);
-    if (line == NULL) {
-        RETURN_LT(layer->lt, NULL);
-    }
-
-    size_t count = 0;
-    if (sscanf(line, "%zu", &count) < 0) {
-        RETURN_LT(layer->lt, NULL);
-    }
-
-    for (size_t i = 0; i < count; ++i) {
-        line = line_stream_next(line_stream);
-        if (line == NULL) {
-            RETURN_LT(layer->lt, NULL);
-        }
+    trace_assert(layer);
 
-        char hex[7];
+    int n = atoi(string_to_cstr(memory, trim(chop_by_delim(input, '\n'))));
+    char id[ENTITY_MAX_ID_SIZE];
+    for (int i = 0; i < n; ++i) {
         Rect rect;
-        char id[ENTITY_MAX_ID_SIZE];
-
-        int n = 0;
-        if (sscanf(line,
-                   "%"STRINGIFY(ENTITY_MAX_ID_SIZE)"s%f%f%f%f%6s%n",
-                   id,
-                   &rect.x, &rect.y,
-                   &rect.w, &rect.h,
-                   hex, &n) <= 0) {
-            log_fail("%s\n", strerror(errno));
-            RETURN_LT(layer->lt, NULL);
-        }
-        line += n;
+        String line = trim(chop_by_delim(input, '\n'));
+        String string_id = trim(chop_word(&line));
+        rect.x = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        rect.y = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        rect.w = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        rect.h = strtof(string_to_cstr(memory, trim(chop_word(&line))), NULL);
+        Color color = hexs(trim(chop_word(&line)));
+
+        memset(id, 0, ENTITY_MAX_ID_SIZE);
+        memcpy(
+            id,
+            string_id.data,
+            min_size_t(ENTITY_MAX_ID_SIZE - 1, string_id.count));
 
-        Color color = hexstr(hex);
         dynarray_push(&layer->rects, &rect);
-        dynarray_push(&layer->ids, id);
         dynarray_push(&layer->colors, &color);
+        dynarray_push(&layer->ids, id);
 
         Action action = {
             .type = ACTION_NONE,
             .entity_id = {0}
         };
 
-        if (sscanf(line, "%d%n", (int*)&action.type, &n) > 0) {
-            line += n;
+        String action_string = trim(chop_word(&line));
+        if (action_string.count > 0) {
+            action.type = (ActionType)atol(string_to_cstr(memory, action_string));
             switch (action.type) {
             case ACTION_NONE: break;
-
             case ACTION_TOGGLE_GOAL:
             case ACTION_HIDE_LABEL: {
-                if (sscanf(line, "%"STRINGIFY(ENTITY_MAX_ID_SIZE)"s", action.entity_id) <= 0) {
-                    log_fail("%s\n", strerror(errno));
-                    RETURN_LT(layer->lt, NULL);
-                }
+                String label_id = trim(chop_word(&line));
+                trace_assert(label_id.count > 0);
+                memset(action.entity_id, 0, ENTITY_MAX_ID_SIZE);
+                memcpy(action.entity_id,
+                       label_id.data,
+                       min_size_t(
+                           ENTITY_MAX_ID_SIZE - 1,
+                           label_id.count));
             } break;
 
             case ACTION_N: break;
index c0b2803045396751d3a17624c5e3ab4af1d9563b..03ae371732ffbb5b36b7ac3fb6b58a4a3ec58320 100644 (file)
@@ -6,17 +6,16 @@
 #include "ui/cursor.h"
 
 typedef struct RectLayer RectLayer;
-typedef struct LineStream LineStream;
 
 LayerPtr rect_layer_as_layer(RectLayer *layer);
 // NOTE: create_rect_layer and create_rect_layer_from_line_stream does
 // not own id_name_prefix
 RectLayer *create_rect_layer(const char *id_name_prefix,
                              Cursor *cursor);
-RectLayer *create_rect_layer_from_line_stream(
-    LineStream *line_stream,
-    const char *id_name_prefix,
-    Cursor *cursor);
+RectLayer *chop_rect_layer(Memory *memory,
+                           String *input,
+                           const char *id_name_prefix,
+                           Cursor *cursor);
 void destroy_rect_layer(RectLayer *layer);
 
 int rect_layer_render(const RectLayer *layer, const Camera *camera, int active);
index 6a670db9d60138254806bbd3baebf6b84bf30b4f..67b552ff874ecec977c6cfc81ef153acbaab5f82 100644 (file)
@@ -7,7 +7,6 @@
 
 #include "platforms.h"
 #include "system/lt.h"
-#include "system/line_stream.h"
 #include "system/nth_alloc.h"
 #include "system/log.h"
 #include "game/level/level_editor/rect_layer.h"
index 7f23fc4e56bb66ee5b78a9c7eb6b17de613680dd..373c400b55754ad4dd7934aa3757c6d56e9b3fb3 100644 (file)
@@ -9,7 +9,6 @@
 #include "math/vec.h"
 #include "platforms.h"
 #include "player.h"
-#include "system/line_stream.h"
 #include "system/log.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
index 276c41f0c2fff90ea00f924a28905552b183fc5e..dd34a01fc39e16761ba7dc403d861f21cecf0dd8 100644 (file)
@@ -4,7 +4,6 @@
 #include "player.h"
 #include "regions.h"
 #include "system/str.h"
-#include "system/line_stream.h"
 #include "system/log.h"
 #include "system/lt.h"
 #include "system/nth_alloc.h"
index 4282f206c4593c7b984525af5e705d7c6a8b1360..019e1f4e7f074a0d1f14ce1f755f85db850b895d 100644 (file)
@@ -6,7 +6,6 @@
 #include "system/lt.h"
 #include "system/nth_alloc.h"
 #include "system/stacktrace.h"
-#include "system/line_stream.h"
 #include "system/str.h"
 #include "system/log.h"
 
@@ -222,7 +221,7 @@ int rigid_bodies_render(RigidBodies *rigid_bodies,
         return -1;
     }
 
-    snprintf(text_buffer, 256, 
+    snprintf(text_buffer, 256,
         "id: %zd\n"
         "p:(%.2f, %.2f)\n"
         "v:(%.2f, %.2f)\n"
index adc9acad6942954a7704ff3a1c6672f526cc7afd..706535f69a49106f277a32dc5eb0a74fadf05ce4 100644 (file)
@@ -75,7 +75,7 @@ void closedir(DIR *dirp)
 
 #endif
 
-String read_whole_file(const char *filepath)
+String read_whole_file(Memory *memory, const char *filepath)
 {
     trace_assert(filepath);
 
@@ -85,8 +85,9 @@ String read_whole_file(const char *filepath)
     if (fseek(f, 0, SEEK_END) < 0) goto end;
     long m = ftell(f);
     if (m < 0) goto end;
+    if (fseek(f, 0, SEEK_SET) < 0) goto end;
     result.count = (size_t) m;
-    char *buffer = nth_calloc(1, result.count);
+    char *buffer = memory_alloc(memory, result.count);
     size_t n = fread(buffer, 1, result.count, f);
     trace_assert(n == result.count);
     result.data = buffer;
index 4a713bf33c81cc78af4269c3151db63357c6e43a..aea060217bd7d74eec8033d4f149eda789d92066 100644 (file)
@@ -25,6 +25,6 @@ struct dirent *readdir(DIR *dirp);
 void closedir(DIR *dirp);
 #endif
 
-String read_whole_file(const char *filepath);
+String read_whole_file(Memory *memory, const char *filepath);
 
 #endif  // FILE_H_
diff --git a/src/system/line_stream.c b/src/system/line_stream.c
deleted file mode 100644 (file)
index a061793..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-#include "system/stacktrace.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <stdbool.h>
-
-#include "line_stream.h"
-#include "lt.h"
-#include "lt_adapters.h"
-#include "system/nth_alloc.h"
-#include "system/log.h"
-#include "system/str.h"
-
-struct LineStream
-{
-    Lt *lt;
-    FILE *stream;
-    char *buffer;
-    size_t capacity;
-    bool unfinished;
-};
-
-// TODO(#905): create_line_stream probably does not need mode
-//   Because LineStream interface doesn't even have anything
-//   for writing to files. So we can just hardcode the mode
-//   inside of the ctor.
-LineStream *create_line_stream(const char *filename,
-                               const char *mode,
-                               size_t capacity)
-{
-    trace_assert(filename);
-    trace_assert(mode);
-
-    Lt *lt = create_lt();
-
-    LineStream *line_stream = PUSH_LT(
-        lt,
-        nth_calloc(1, sizeof(LineStream)),
-        free);
-    if (line_stream == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-    line_stream->lt = lt;
-
-    line_stream->stream = PUSH_LT(
-        lt,
-        fopen(filename, mode),
-        fclose_lt);
-    if (line_stream->stream == NULL) {
-        log_fail("Could not open file '%s': %s\n", filename, strerror(errno));
-        RETURN_LT(lt, NULL);
-    }
-
-    line_stream->buffer = PUSH_LT(
-        lt,
-        nth_calloc(1, sizeof(char) * capacity),
-        free);
-    if (line_stream->buffer == NULL) {
-        RETURN_LT(lt, NULL);
-    }
-
-    line_stream->capacity = capacity;
-    line_stream->unfinished = false;
-
-    return line_stream;
-}
-
-void destroy_line_stream(LineStream *line_stream)
-{
-    trace_assert(line_stream);
-
-    RETURN_LT0(line_stream->lt);
-}
-
-
-const char *line_stream_next_chunk(LineStream *line_stream)
-{
-    trace_assert(line_stream);
-
-    const char *s = fgets(line_stream->buffer,
-                          (int) line_stream->capacity,
-                          line_stream->stream);
-    if (s == NULL) {
-        return NULL;
-    }
-    size_t n = strlen(s);
-    line_stream->unfinished = s[n - 1] != '\n';
-
-    return s;
-}
-
-const char *line_stream_next(LineStream *line_stream)
-{
-    trace_assert(line_stream);
-
-    while (line_stream->unfinished) {
-        line_stream_next_chunk(line_stream);
-    }
-
-    return line_stream_next_chunk(line_stream);
-}
-
-char *line_stream_collect_n_lines(LineStream *line_stream, size_t n)
-{
-    char *result = string_append(NULL, "");
-    for (size_t i = 0; i < n; ++i) {
-        const char *line = line_stream_next(line_stream);
-        if (line == NULL) {
-            free(result);
-            return NULL;
-        }
-
-        result = string_append(result, line);
-    }
-
-    return result;
-}
-
-char *line_stream_collect_until_end(LineStream *line_stream)
-{
-    char *result = string_append(NULL, "");
-    const char *line = line_stream_next(line_stream);
-
-    /* TODO(#906): line_stream_collect_until_end does not distinguish between EOF and error during reading */
-    while (line != NULL) {
-        result = string_append(result, line);
-        line = line_stream_next(line_stream);
-    }
-
-    return result;
-}
diff --git a/src/system/line_stream.h b/src/system/line_stream.h
deleted file mode 100644 (file)
index 6b90cf5..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef LINE_STREAM_H_
-#define LINE_STREAM_H_
-
-#include <stdlib.h>
-
-typedef struct LineStream LineStream;
-
-LineStream *create_line_stream(const char *filename,
-                               const char *mode,
-                               size_t capacity);
-void destroy_line_stream(LineStream *line_stream);
-
-const char *line_stream_next_chunk(LineStream *line_stream);
-const char *line_stream_next(LineStream *line_stream);
-char *line_stream_collect_n_lines(LineStream *line_stream, size_t n);
-char *line_stream_collect_until_end(LineStream *line_stream);
-
-#endif  // LINE_STREAM_H_
diff --git a/src/system/memory.h b/src/system/memory.h
new file mode 100644 (file)
index 0000000..c12c8e4
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef MEMORY_H_
+#define MEMORY_H_
+
+#include <assert.h>
+#include <stdint.h>
+
+#define KILO 1024L
+#define MEGA (1024L * KILO)
+#define GIGA (1024L * MEGA)
+
+typedef struct {
+    size_t capacity;
+    size_t size;
+    uint8_t *buffer;
+} Memory;
+
+static inline
+void *memory_alloc(Memory *memory, size_t size)
+{
+    assert(memory);
+    assert(memory->size + size <= memory->capacity);
+
+
+    void *result = memory->buffer + memory->size;
+    memory->size += size;
+
+    return result;
+}
+
+static inline
+void memory_clean(Memory *memory)
+{
+    assert(memory);
+    memory->size = 0;
+}
+
+#endif  // MEMORY_H_
index 766789241e993a223adb16ef2c1d78915474f94c..43ff261cdf590ceb86b306d0c67926b483187ff0 100644 (file)
@@ -1,8 +1,11 @@
 #ifndef S_H_
 #define S_H_
 
+#include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 #include "system/stacktrace.h"
+#include "system/memory.h"
 
 typedef struct {
     size_t count;
@@ -62,4 +65,59 @@ int string_equal(String a, String b)
     return memcmp(a.data, b.data, a.count) == 0;
 }
 
+static inline
+String trim_begin(String input)
+{
+    while (input.count > 0 && isspace(*input.data)) {
+        input.data += 1;
+        input.count -= 1;
+    }
+
+    return input;
+}
+
+static inline
+String trim_end(String input)
+{
+    while (input.count > 0 && isspace(*(input.data + input.count - 1))) {
+        input.count -= 1;
+    }
+
+    return input;
+}
+
+static inline
+String trim(String input)
+{
+    return trim_end(trim_begin(input));
+}
+
+static inline
+String chop_word(String *input)
+{
+    trace_assert(input);
+
+    *input = trim_begin(*input);
+
+    size_t i = 0;
+    while (i < input->count && !isspace(input->data[i]))
+        i++;
+
+    String result = string(i, input->data);
+    input->data += i;
+    input->count -= i;
+    return result;
+}
+
+static inline
+char *string_to_cstr(Memory *memory, String s)
+{
+    trace_assert(memory);
+
+    char *result = memory_alloc(memory, s.count + 1);
+    memset(result, 0, s.count + 1);
+    memcpy(result, s.data, s.count);
+    return result;
+}
+
 #endif  // S_H_
index 60016b0339d5f5aeac5eb793f441b574b1d80b19..04f81003a40a633f6e3af6a632b7282de30e72f4 100644 (file)
@@ -42,15 +42,3 @@ char *trim_endline(char *s)
 
     return s;
 }
-
-char *string_append(char *prefix, const char *suffix)
-{
-    trace_assert(suffix);
-
-    if (prefix == NULL) {
-        return string_duplicate(suffix, NULL);
-    }
-
-    prefix = nth_realloc(prefix, strlen(prefix) + strlen(suffix) + 1);
-    return strcat(prefix, suffix);
-}
index b780bc220c12dc503de718f4234a10a53e2decf9..f6331031f96f6d79961c15549f635e5e73ad55ab 100644 (file)
@@ -6,8 +6,6 @@
 
 char *string_duplicate(const char *str,
                        const char *str_end);
-char *string_append(char *prefix,
-                    const char *suffix);
 char *trim_endline(char *s);
 
 #endif  // STR_H_
index 909189561b6b792f4b5d9bb94e8264fd110ba882..9b1458c4c5ffe560b94e6b43fbf54aa95e1d2ce5 100644 (file)
 #define CONSOLE_FOREGROUND (rgba(0.80f, 0.80f, 0.80f, CONSOLE_ALPHA))
 #define CONSOLE_ERROR (rgba(0.80f, 0.50f, 0.50f, CONSOLE_ALPHA))
 
-typedef struct {
-    const char *begin;
-    const char *end;
-} Token;
-
-
-static inline
-Token token(const char *begin, const char *end)
-{
-    Token t = {begin, end};
-    return t;
-}
-
-static inline
-int token_equals_str(Token t, const char *s)
-{
-    trace_assert(t.begin <= t.end);
-    size_t n1 = (size_t) (t.end - t.begin);
-    size_t n2 = strlen(s);
-    if (n1 != n2) return 0;
-    return memcmp(t.begin, s, n1) == 0;
-}
-
-static inline
-Token token_nt(const char *s)
-{
-    return token(s, s + strlen(s));
-}
-
-static inline
-void ltrim(Token *t)
-{
-    while (t->begin < t->end && isspace(*t->begin)) {
-        t->begin++;
-    }
-}
-
-static inline
-Token chop_word(Token *t)
-{
-    ltrim(t);
-    const char *end = t->begin;
-    while (end < t->end && !isspace(*end)) {
-        end++;
-    }
-    Token result = token(t->begin, end);
-    t->begin = end;
-    return result;
-}
-
 struct Console
 {
     Lt *lt;
@@ -146,10 +96,10 @@ static int console_eval_input(Console *console)
 {
     const char *input_text = edit_field_as_text(console->edit_field);
 
-    Token input = token_nt(input_text);
-    Token command = chop_word(&input);
+    String input = string_nt(input_text);
+    String command = chop_word(&input);
 
-    if (token_equals_str(command, "")) {
+    if (string_equal(command, STRING_LIT(""))) {
         edit_field_clean(console->edit_field);
         return 0;
     }
@@ -162,18 +112,18 @@ static int console_eval_input(Console *console)
         return -1;
     }
 
-    if (token_equals_str(command, "load")) {
-        Token level = chop_word(&input);
+    if (string_equal(command, STRING_LIT("load"))) {
+        String level = chop_word(&input);
         console_log_push_line(console->console_log, "Loading level:", NULL, CONSOLE_FOREGROUND);
-        console_log_push_line(console->console_log, level.begin, level.end, CONSOLE_FOREGROUND);
+        console_log_push_line(console->console_log, level.data, level.data + level.count, CONSOLE_FOREGROUND);
         char level_name[256];
         memset(level_name, 0, 256);
-        memcpy(level_name, level.begin, min_size_t((size_t)(level.end - level.begin), 255));
+        memcpy(level_name, level.data, min_size_t(level.count, 255));
 
         if (game_load_level(console->game, level_name) < 0) {
             console_log_push_line(console->console_log, "Could not load level", NULL, CONSOLE_ERROR);
         }
-    } else if (token_equals_str(command, "menu")) {
+    } else if (string_equal(command, STRING_LIT("menu"))) {
         console_log_push_line(console->console_log, "Loading menu", NULL, CONSOLE_FOREGROUND);
         game_switch_state(console->game, GAME_STATE_LEVEL_PICKER);
     } else {