瀏覽代碼

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
         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)
         Find argument by key name and return its index, or -1 if not found.
 
@@ -110,7 +118,7 @@ extern "C" {
 
 typedef struct {
     int argc;
-    const char** argv;
+    char** argv;
     int max_args;
     int buf_size;
 } sargs_desc;
@@ -127,6 +135,10 @@ extern bool sargs_exists(const char* key);
 extern const char* sargs_value(const char* key);
 /* 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);
+/* 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 */
 extern int sargs_find(const char* key);
 /* get number of parsed arguments */
@@ -144,6 +156,10 @@ extern const char* sargs_value_at(int index);
 #ifdef SOKOL_IMPL
 #include <string.h>
 
+#if defined(__EMSCRIPTEN__)
+#include <emscripten/emscripten.h>
+#endif
+
 #ifndef SOKOL_DEBUG
     #ifdef _DEBUG
         #define SOKOL_DEBUG (1)
@@ -184,13 +200,15 @@ extern const char* sargs_value_at(int index);
 #define _SARGS_MAX_ARGS_DEF (16)
 #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_SEP (1<<1)
 #define _SARGS_EXPECT_VAL (1<<2)
 #define _SARGS_PARSING_KEY (1<<3)
 #define _SARGS_PARSING_VAL (1<<4)
 #define _SARGS_ERROR (1<<5)
+#endif
 
 /* a key/value pair struct */
 typedef struct {
@@ -207,9 +225,13 @@ typedef struct {
     int buf_pos;        /* current buffer position */
     char* buf;          /* character buffer, first char is reserved and zero for 'empty string' */
     bool valid;
+    
+    /* arg parsing isn't needed on emscripten */
+    #if !defined(__EMSCRIPTEN__)
     uint32_t parse_state;
     char quote;         /* current quote char, 0 if not in a quote */
     bool in_escape;     /* currently in an escape sequence */
+    #endif
 } _sargs_state;
 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) {
     _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;
     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 =========================================*/
 void sargs_setup(const sargs_desc* 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));
     /* the first character in buf is reserved and always zero, this is the 'empty string' */
     _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;
 }
 
@@ -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 */