瀏覽代碼

sokol_args.h: emscripten support

Andre Weissflog 7 年之前
父節點
當前提交
a85bf31b55
共有 1 個文件被更改,包括 90 次插入6 次删除
  1. 90 6
      sokol_args.h

+ 90 - 6
sokol_args.h

@@ -61,6 +61,14 @@
         Return value associated with key, or the provided default
         Return value associated with key, or the provided default
         value if the value doesn't exist or has no key.
         value if the value doesn't exist or has no key.
 
 
+    bool sargs_equals(const char* key, const char* val);
+        Return true if the value associated with key matches
+        the 'val' argument.
+
+    bool sargs_boolean(const char* key)
+        Return true if the value string associated with 'key' is one
+        of 'true', 'yes', 'on'.
+
     int sargs_find(const char* key)
     int sargs_find(const char* key)
         Find argument by key name and return its index, or -1 if not found.
         Find argument by key name and return its index, or -1 if not found.
 
 
@@ -110,7 +118,7 @@ extern "C" {
 
 
 typedef struct {
 typedef struct {
     int argc;
     int argc;
-    const char** argv;
+    char** argv;
     int max_args;
     int max_args;
     int buf_size;
     int buf_size;
 } sargs_desc;
 } sargs_desc;
@@ -127,6 +135,10 @@ extern bool sargs_exists(const char* key);
 extern const char* sargs_value(const char* key);
 extern const char* sargs_value(const char* key);
 /* get value by key name, return provided default if key doesn't exist */
 /* get value by key name, return provided default if key doesn't exist */
 extern const char* sargs_value_def(const char* key, const char* def);
 extern const char* sargs_value_def(const char* key, const char* def);
+/* return true if val arg matches the value associated with key */
+extern bool sargs_equals(const char* key, const char* val);
+/* return true if key's value is "true", "yes" or "on" */
+extern bool sargs_boolean(const char* key);
 /* get index of arg by key name, return -1 if not exists */
 /* get index of arg by key name, return -1 if not exists */
 extern int sargs_find(const char* key);
 extern int sargs_find(const char* key);
 /* get number of parsed arguments */
 /* get number of parsed arguments */
@@ -144,6 +156,10 @@ extern const char* sargs_value_at(int index);
 #ifdef SOKOL_IMPL
 #ifdef SOKOL_IMPL
 #include <string.h>
 #include <string.h>
 
 
+#if defined(__EMSCRIPTEN__)
+#include <emscripten/emscripten.h>
+#endif
+
 #ifndef SOKOL_DEBUG
 #ifndef SOKOL_DEBUG
     #ifdef _DEBUG
     #ifdef _DEBUG
         #define SOKOL_DEBUG (1)
         #define SOKOL_DEBUG (1)
@@ -184,13 +200,15 @@ extern const char* sargs_value_at(int index);
 #define _SARGS_MAX_ARGS_DEF (16)
 #define _SARGS_MAX_ARGS_DEF (16)
 #define _SARGS_BUF_SIZE_DEF (16*1024)
 #define _SARGS_BUF_SIZE_DEF (16*1024)
 
 
-/* parser state */
+/* parser state (no parser needed on emscripten) */
+#if !defined(__EMSCRIPTEN__)
 #define _SARGS_EXPECT_KEY (1<<0)
 #define _SARGS_EXPECT_KEY (1<<0)
 #define _SARGS_EXPECT_SEP (1<<1)
 #define _SARGS_EXPECT_SEP (1<<1)
 #define _SARGS_EXPECT_VAL (1<<2)
 #define _SARGS_EXPECT_VAL (1<<2)
 #define _SARGS_PARSING_KEY (1<<3)
 #define _SARGS_PARSING_KEY (1<<3)
 #define _SARGS_PARSING_VAL (1<<4)
 #define _SARGS_PARSING_VAL (1<<4)
 #define _SARGS_ERROR (1<<5)
 #define _SARGS_ERROR (1<<5)
+#endif
 
 
 /* a key/value pair struct */
 /* a key/value pair struct */
 typedef struct {
 typedef struct {
@@ -207,9 +225,13 @@ typedef struct {
     int buf_pos;        /* current buffer position */
     int buf_pos;        /* current buffer position */
     char* buf;          /* character buffer, first char is reserved and zero for 'empty string' */
     char* buf;          /* character buffer, first char is reserved and zero for 'empty string' */
     bool valid;
     bool valid;
+    
+    /* arg parsing isn't needed on emscripten */
+    #if !defined(__EMSCRIPTEN__)
     uint32_t parse_state;
     uint32_t parse_state;
     char quote;         /* current quote char, 0 if not in a quote */
     char quote;         /* current quote char, 0 if not in a quote */
     bool in_escape;     /* currently in an escape sequence */
     bool in_escape;     /* currently in an escape sequence */
+    #endif
 } _sargs_state;
 } _sargs_state;
 static _sargs_state _sargs;
 static _sargs_state _sargs;
 
 
@@ -221,6 +243,13 @@ _SOKOL_PRIVATE void _sargs_putc(char c) {
     }
     }
 }
 }
 
 
+_SOKOL_PRIVATE const char* _sargs_str(int index) {
+    SOKOL_ASSERT((index >= 0) && (index < _sargs.buf_size));
+    return &_sargs.buf[index];
+}
+
+/*-- argument parser functions (not required on emscripten) ------------------*/
+#if !defined(__EMSCRIPTEN__)
 _SOKOL_PRIVATE void _sargs_expect_key(void) {
 _SOKOL_PRIVATE void _sargs_expect_key(void) {
     _sargs.parse_state = _SARGS_EXPECT_KEY;
     _sargs.parse_state = _SARGS_EXPECT_KEY;
 }
 }
@@ -430,12 +459,49 @@ _SOKOL_PRIVATE bool _sargs_parse_cargs(int argc, const char** argv) {
     _sargs.parse_state = 0;
     _sargs.parse_state = 0;
     return retval;
     return retval;
 }
 }
+#endif /* __EMSCRIPTEN__ */
 
 
-_SOKOL_PRIVATE const char* _sargs_str(int index) {
-    SOKOL_ASSERT((index >= 0) && (index < _sargs.buf_size));
-    return &_sargs.buf[index];
+/*-- EMSCRIPTEN IMPLEMENTATION -----------------------------------------------*/
+#if defined(__EMSCRIPTEN__)
+
+EMSCRIPTEN_KEEPALIVE void _sargs_add_kvp(const char* key, const char* val) {
+    SOKOL_ASSERT(_sargs.valid && key && val);
+    if (_sargs.num_args >= _sargs.max_args) {
+        return;
+    }
+
+    /* copy key string */
+    char c;
+    _sargs.args[_sargs.num_args].key = _sargs.buf_pos;
+    const char* ptr = key;
+    while (0 != (c = *ptr++)) {
+        _sargs_putc(c);
+    }
+    _sargs_putc(0);
+
+    /* copy value string */
+    _sargs.args[_sargs.num_args].val = _sargs.buf_pos;
+    ptr = val;
+    while (0 != (c = *ptr++)) {
+        _sargs_putc(c);
+    }
+    _sargs_putc(0);
+
+    _sargs.num_args++;
 }
 }
 
 
+/* JS function to extract arguments from the page URL */
+EM_JS(void, sargs_js_parse_url, (), {
+    var params = new URLSearchParams(window.location.search).entries();
+    for (var p = params.next(); !p.done; p = params.next()) {
+        var key = p.value[0];
+        var val = p.value[1];
+        var res = Module.ccall('_sargs_add_kvp', 'void', ['string','string'], [key,val]);
+    }
+});
+
+#endif /* EMSCRIPTEN */
+
 /*== PUBLIC IMPLEMENTATION FUNCTIONS =========================================*/
 /*== PUBLIC IMPLEMENTATION FUNCTIONS =========================================*/
 void sargs_setup(const sargs_desc* desc) {
 void sargs_setup(const sargs_desc* desc) {
     SOKOL_ASSERT(desc);
     SOKOL_ASSERT(desc);
@@ -447,7 +513,13 @@ void sargs_setup(const sargs_desc* desc) {
     _sargs.buf = (char*) SOKOL_CALLOC(_sargs.buf_size, sizeof(char));
     _sargs.buf = (char*) SOKOL_CALLOC(_sargs.buf_size, sizeof(char));
     /* the first character in buf is reserved and always zero, this is the 'empty string' */
     /* the first character in buf is reserved and always zero, this is the 'empty string' */
     _sargs.buf_pos = 1;
     _sargs.buf_pos = 1;
-    _sargs_parse_cargs(desc->argc, desc->argv);
+    #if defined(__EMSCRIPTEN__)
+        /* on emscripten, ignore argc/argv, and parse the page URL instead */
+        sargs_js_parse_url();
+    #else
+        /* on native platform, parse argc/argv */
+        _sargs_parse_cargs(desc->argc, (const char**) desc->argv);
+    #endif
     _sargs.valid = true;
     _sargs.valid = true;
 }
 }
 
 
@@ -526,4 +598,16 @@ const char* sargs_value_def(const char* key, const char* def) {
     }
     }
 }
 }
 
 
+bool sargs_equals(const char* key, const char* val) {
+    SOKOL_ASSERT(_sargs.valid && key && val);
+    return 0 == strcmp(sargs_value(key), val);
+}
+
+bool sargs_boolean(const char* key) {
+    const char* val = sargs_value(key);
+    return (0 == strcmp("true", val)) ||
+           (0 == strcmp("yes", val)) ||
+           (0 == strcmp("on", val));
+}
+
 #endif /* SOKOL_IMPL */
 #endif /* SOKOL_IMPL */