Browse Source

Custom temporary allocator

rexim 2 years ago
parent
commit
5b986bd400
2 changed files with 51 additions and 12 deletions
  1. 39 0
      README.md
  2. 12 12
      glob.h

+ 39 - 0
README.md

@@ -19,6 +19,45 @@ int main(void)
 }
 ```
 
+## Custom Allocator
+
+`glob_utf8` allocates and deallocates memory on each call because it needs to
+to decode UTF-8. If you want to avoid that you can define your custom temporary
+allocator.
+
+```console
+#include <stdio.h>
+
+char temp[1024];
+size_t temp_bump = 0;
+
+void *temp_alloc(size_t size)
+{
+    if (temp_bump + size > sizeof(temp)) return NULL;
+    void *result = temp + temp_bump;
+    temp_bump += size;
+    return result;
+}
+
+#define GLOB_IMPLEMENTATION
+#define GLOB_MALLOC temp_alloc
+#define GLOB_FREE(...)
+#include "glob.h"
+
+int main(void)
+{
+    const char *texts[] = { "main.c", "test.c", "index.js", "reset.css" };
+    size_t n = sizeof(texts)/sizeof(texts[0]);
+    for (size_t i = 0; i < n; ++i) {
+        if (!glob_utf8("*.c", texts[i])) {
+            printf("%s\n", texts[i]);
+        }
+        temp_bump = 0;
+    }
+    return 0;
+}
+```
+
 ## Testing
 
 ```console

+ 12 - 12
glob.h

@@ -4,18 +4,20 @@
 #include <assert.h>
 #include <stdint.h>
 #include <stdbool.h>
+#include <string.h>
 
 #if !defined(GLOB_MALLOC) && !defined(GLOB_FREE)
 #include <stdlib.h>
 #define GLOB_MALLOC malloc
 #define GLOB_FREE free
-#else
+#elif !defined(GLOB_MALLOC) || !defined(GLOB_FREE)
 #error "You must define both GLOB_MALLOC and GLOB_FREE"
 #endif
 
 // Matched - falsy
 // Not matched for any reason - truthy
 typedef enum {
+    GLOB_OOM_ERROR      = -4,
     GLOB_ENCODING_ERROR = -3,
     GLOB_SYNTAX_ERROR   = -2,
     GLOB_UNMATCHED      = -1,
@@ -216,10 +218,11 @@ ConversionResult ConvertUTF8toUTF32 (
 
 // HERE ENDS ConvertUTF CODE //////////////////////////////
 
-static ConversionResult decode_utf8_with_malloc(const char *in, uint32_t **out)
+static Glob_Result decode_utf8_with_malloc(const char *in, uint32_t **out)
 {
     size_t n = strlen(in);
     *out = GLOB_MALLOC(sizeof(uint32_t)*(n + 1));
+    if (*out == NULL) return GLOB_OOM_ERROR;
     assert(*out != NULL && "Buy more RAM lol");
     memset(*out, 0, sizeof(uint32_t)*(n + 1));
     uint32_t *out_end = *out;
@@ -227,7 +230,8 @@ static ConversionResult decode_utf8_with_malloc(const char *in, uint32_t **out)
     ConversionResult result = ConvertUTF8toUTF32(
                                   (const UTF8**) &in, (const UTF8*) (in + n),
                                   (UTF32**) &out_end, (UTF32*) out_end + n, 0);
-    return result;
+    if (result != conversionOK) return GLOB_ENCODING_ERROR;
+    return GLOB_MATCHED;
 }
 
 const char *glob_result_display(Glob_Result result)
@@ -237,6 +241,7 @@ const char *glob_result_display(Glob_Result result)
     case GLOB_MATCHED:        return "GLOB_MATCHED";
     case GLOB_SYNTAX_ERROR:   return "GLOB_SYNTAX_ERROR";
     case GLOB_ENCODING_ERROR: return "GLOB_ENCODING_ERROR";
+    case GLOB_OOM_ERROR:      return "GLOB_OOM_ERROR";
     default: assert(0 && "unreachable");
     }
 }
@@ -244,18 +249,13 @@ const char *glob_result_display(Glob_Result result)
 Glob_Result glob_utf8(const char *pattern, const char *text)
 {
     Glob_Result result = 0;
-
     uint32_t *pattern_utf32 = NULL;
     uint32_t *text_utf32 = NULL;
-    if (decode_utf8_with_malloc(pattern, &pattern_utf32) != conversionOK) {
-        result = GLOB_ENCODING_ERROR;
-        goto defer;
-    }
-    if (decode_utf8_with_malloc(text, &text_utf32) != conversionOK) {
-        result = GLOB_ENCODING_ERROR;
-        goto defer;
-    }
 
+    result = decode_utf8_with_malloc(pattern, &pattern_utf32);
+    if (result) goto defer;
+    result = decode_utf8_with_malloc(text, &text_utf32);
+    if (result) goto defer;
     result = glob_utf32(pattern_utf32, text_utf32);
 
 defer: