MIRROR: javascript for 馃悳's, a tiny runtime with big ambitions
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at mir/inline-method 178 lines 4.8 kB view raw
1#include <stdlib.h> 2#include <string.h> 3#include <uthash.h> 4 5#include "ant.h" 6#include "errors.h" 7#include "runtime.h" 8#include "internal.h" 9#include "descriptors.h" 10 11#include "modules/symbol.h" 12#include "modules/sessionstorage.h" 13 14typedef struct storage_entry { 15 char *key; 16 char *value; 17 UT_hash_handle hh; 18} storage_entry_t; 19 20static storage_entry_t *session_storage = NULL; 21 22static void storage_set_item(const char *key, size_t key_len, const char *value, size_t value_len) { 23 storage_entry_t *entry = NULL; 24 25 HASH_FIND(hh, session_storage, key, key_len, entry); 26 27 if (entry) { 28 HASH_DEL(session_storage, entry); 29 free(entry); 30 } 31 32 entry = ant_calloc(sizeof(storage_entry_t) + key_len + 1 + value_len + 1); 33 if (!entry) return; 34 35 entry->key = (char *)(entry + 1); 36 entry->value = entry->key + key_len + 1; 37 38 memcpy(entry->key, key, key_len); 39 entry->key[key_len] = '\0'; 40 memcpy(entry->value, value, value_len); 41 entry->value[value_len] = '\0'; 42 43 HASH_ADD_KEYPTR(hh, session_storage, entry->key, key_len, entry); 44} 45 46static char *storage_get_item(const char *key, size_t key_len) { 47 storage_entry_t *entry = NULL; 48 HASH_FIND(hh, session_storage, key, key_len, entry); 49 return entry ? entry->value : NULL; 50} 51 52static void storage_remove_item(const char *key, size_t key_len) { 53 storage_entry_t *entry = NULL; 54 HASH_FIND(hh, session_storage, key, key_len, entry); 55 56 if (entry) { 57 HASH_DEL(session_storage, entry); 58 free(entry); 59 } 60} 61 62static void storage_clear(void) { 63 storage_entry_t *entry, *tmp; 64 HASH_ITER(hh, session_storage, entry, tmp) { 65 HASH_DEL(session_storage, entry); 66 free(entry); 67 } 68} 69 70static size_t storage_length(void) { 71 return HASH_COUNT(session_storage); 72} 73 74static char *storage_key(size_t index) { 75 storage_entry_t *entry; 76 size_t i = 0; 77 78 for (entry = session_storage; entry != NULL; entry = entry->hh.next) { 79 if (i == index) return entry->key; 80 i++; 81 } 82 83 return NULL; 84} 85 86// sessionStorage.setItem(key, value) 87static ant_value_t js_sessionstorage_setItem(ant_t *js, ant_value_t *args, int nargs) { 88 if (nargs < 2) { 89 return js_mkerr(js, "Failed to execute 'setItem' on 'Storage': 2 arguments required"); 90 } 91 92 size_t key_len, value_len; 93 char *key = js_getstr(js, args[0], &key_len); 94 char *value = js_getstr(js, js_tostring_val(js, args[1]), &value_len); 95 96 storage_set_item(key, key_len, value, value_len); 97 98 return js_mkundef(); 99} 100 101// sessionStorage.getItem(key) 102static ant_value_t js_sessionstorage_getItem(ant_t *js, ant_value_t *args, int nargs) { 103 if (nargs < 1) { 104 return js_mkerr(js, "Failed to execute 'getItem' on 'Storage': 1 argument required"); 105 } 106 107 size_t key_len; 108 char *key = js_getstr(js, args[0], &key_len); 109 char *value = storage_get_item(key, key_len); 110 111 if (!value) return js_mknull(); 112 113 return js_mkstr(js, value, strlen(value)); 114} 115 116// sessionStorage.removeItem(key) 117static ant_value_t js_sessionstorage_removeItem(ant_t *js, ant_value_t *args, int nargs) { 118 if (nargs < 1) { 119 return js_mkerr(js, "Failed to execute 'removeItem' on 'Storage': 1 argument required"); 120 } 121 122 size_t key_len; 123 char *key = js_getstr(js, args[0], &key_len); 124 storage_remove_item(key, key_len); 125 126 return js_mkundef(); 127} 128 129// sessionStorage.clear() 130static ant_value_t js_sessionstorage_clear(ant_params_t) { 131 storage_clear(); 132 return js_mkundef(); 133} 134 135// sessionStorage.key(index) 136static ant_value_t js_sessionstorage_key(ant_t *js, ant_value_t *args, int nargs) { 137 if (nargs < 1) { 138 return js_mkerr(js, "Failed to execute 'key' on 'Storage': 1 argument required"); 139 } 140 141 if (vtype(args[0]) != T_NUM) { 142 return js_mknull(); 143 } 144 145 double idx = js_getnum(args[0]); 146 if (idx < 0) return js_mknull(); 147 148 size_t index = (size_t)idx; 149 char *key = storage_key(index); 150 151 if (!key) return js_mknull(); 152 153 return js_mkstr(js, key, strlen(key)); 154} 155 156// sessionStorage.length 157static ant_value_t js_sessionstorage_length(ant_params_t) { 158 return js_mknum((double)storage_length()); 159} 160 161void init_sessionstorage_module(void) { 162 ant_t *js = rt->js; 163 164 ant_value_t glob = js_glob(js); 165 ant_value_t storage_obj = js_mkobj(js); 166 167 js_set(js, storage_obj, "setItem", js_mkfun(js_sessionstorage_setItem)); 168 js_set(js, storage_obj, "getItem", js_mkfun(js_sessionstorage_getItem)); 169 js_set(js, storage_obj, "removeItem", js_mkfun(js_sessionstorage_removeItem)); 170 js_set(js, storage_obj, "clear", js_mkfun(js_sessionstorage_clear)); 171 js_set(js, storage_obj, "key", js_mkfun(js_sessionstorage_key)); 172 173 ant_value_t length_getter = js_mkfun(js_sessionstorage_length); 174 js_set_getter_desc(js, storage_obj, "length", 6, length_getter, JS_DESC_E); 175 176 js_set_sym(js, storage_obj, get_toStringTag_sym(), ANT_STRING("Storage")); 177 js_set(js, glob, "sessionStorage", storage_obj); 178}