damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

nostrscript.c (5046B)


      1 //
      2 //  nostrscript.c
      3 //  damus
      4 //
      5 //  Created by William Casarin on 2023-06-02.
      6 //
      7 
      8 #include "nostrscript.h"
      9 #include "wasm.h"
     10 #include "array_size.h"
     11 
     12 // function to check if the character is in surrogate pair range
     13 static INLINE int is_surrogate(uint16_t uc) {
     14     return (uc - 0xd800u) < 2048u;
     15 }
     16 
     17 // function to convert utf16 to utf8
     18 static int utf16_to_utf8(u16 utf16, u8 *utf8) {
     19     if (utf16 < 0x80) { // 1-byte sequence
     20         utf8[0] = (uint8_t) utf16;
     21         return 1;
     22     }
     23     else if (utf16 < 0x800) { // 2-byte sequence
     24         utf8[0] = (uint8_t) (0xc0 | (utf16 >> 6));
     25         utf8[1] = (uint8_t) (0x80 | (utf16 & 0x3f));
     26         return 2;
     27     }
     28     else if (!is_surrogate(utf16)) { // 3-byte sequence
     29         utf8[0] = (uint8_t) (0xe0 | (utf16 >> 12));
     30         utf8[1] = (uint8_t) (0x80 | ((utf16 >> 6) & 0x3f));
     31         utf8[2] = (uint8_t) (0x80 | (utf16 & 0x3f));
     32         return 3;
     33     }
     34     else { // surrogate pair, return error
     35         return -1;
     36     }
     37 }
     38 
     39 static int nostr_cmd(struct wasm_interp *interp) {
     40     struct val *params = NULL;
     41     const char *val = NULL;
     42     int len, cmd, ival;
     43     
     44     if (!get_params(interp, &params, 3) || params == NULL)
     45         return interp_error(interp, "get params");
     46 
     47     // command
     48     cmd = params[0].num.i32;
     49     
     50     // value
     51     
     52     ival = params[1].num.i32;
     53     if (!mem_ptr_str(interp, ival, &val))
     54         val = 0;
     55 
     56     // length
     57     len = params[2].num.i32;
     58 
     59     intptr_t iptr = ival;
     60     return nscript_nostr_cmd(interp, cmd, val ? (void*)val : (void*)iptr, len);
     61 }
     62 
     63 static int print_utf16_str(u16 *chars) {
     64     u16 *p = chars;
     65     int c;
     66     
     67     while (*p) {
     68         if (utf16_to_utf8(*p, (u8*)&c) == -1)
     69             return 0;
     70         
     71         printf("%c", c);
     72         
     73         p++;
     74     }
     75     
     76     return 1;
     77 }
     78 
     79 static int nostr_log(struct wasm_interp *interp) {
     80     struct val *vals;
     81     const char *str;
     82     struct callframe *callframe;
     83     
     84     if (!get_params(interp, &vals, 1))
     85         return interp_error(interp, "nostr_log get params");
     86     
     87     if (!mem_ptr_str(interp, vals[0].num.i32, &str))
     88         return interp_error(interp, "nostr_log log param");
     89     
     90     if (!(callframe = top_callframes(&interp->callframes, 2)))
     91         return interp_error(interp, "nostr_log callframe");
     92     
     93     printf("nostr_log:%s: ", callframe->func->name);
     94     
     95     print_utf16_str((u16*)str);
     96     printf("\n");
     97     
     98     return 1;
     99 }
    100 
    101 static int nostr_set_bool(struct wasm_interp *interp) {
    102     struct val *params = NULL;
    103     const u16 *setting;
    104     u32 val, len;
    105 
    106     if (!get_params(interp, &params, 3) || params == NULL)
    107         return 0;
    108 
    109     if (!mem_ptr_str(interp, params[0].num.i32, (const char**)&setting))
    110         return 0;
    111 
    112     len = params[1].num.i32;
    113     val = params[2].num.i32 > 0 ? 1 : 0;
    114 
    115     return nscript_set_bool(interp, setting, len, val);
    116 }
    117 
    118 static int nostr_pool_send_to(struct wasm_interp *interp) {
    119     struct val *params = NULL;
    120     const u16 *req, *to;
    121     int req_len, to_len;
    122     
    123     if (!get_params(interp, &params, 4) || params == NULL)
    124         return 0;
    125 
    126     if (!mem_ptr_str(interp, params[0].num.i32, (const char**)&req))
    127         return 0;
    128     
    129     req_len = params[1].num.i32;
    130     
    131     if (!mem_ptr_str(interp, params[2].num.i32, (const char**)&to))
    132         return 0;
    133     
    134     to_len = params[3].num.i32;
    135     
    136     return nscript_pool_send_to(interp, req, req_len, to, to_len);
    137 }
    138 
    139 static int nscript_abort(struct wasm_interp *interp) {
    140     struct val *params = NULL;
    141     const char *msg = "", *filename;
    142     int line, col;
    143     
    144     if (!get_params(interp, &params, 4) || params == NULL)
    145         return interp_error(interp, "get params");
    146     
    147     if (params[0].ref.addr != 0 && !mem_ptr_str(interp, params[0].ref.addr, &msg))
    148         return interp_error(interp, "abort msg");
    149 
    150     if (!mem_ptr_str(interp, params[1].ref.addr, &filename))
    151         return interp_error(interp, "abort filename");
    152     
    153     line = params[2].num.i32;
    154     col = params[3].num.i32;
    155 
    156     printf("nscript_abort:");
    157     print_utf16_str((u16*)filename);
    158     printf(":%d:%d: ", line, col);
    159     print_utf16_str((u16*)msg);
    160     printf("\n");
    161     
    162     return 0;
    163 }
    164 
    165 static struct builtin nscript_builtins[] = {
    166     { .name = "null", .fn = 0 },
    167     { .name = "nostr_log", .fn = nostr_log },
    168     { .name = "nostr_cmd", .fn = nostr_cmd },
    169     { .name = "nostr_pool_send_to", .fn = nostr_pool_send_to },
    170     { .name = "nostr_set_bool", .fn = nostr_set_bool },
    171     { .name = "abort", .fn = nscript_abort },
    172 };
    173 
    174 int nscript_load(struct wasm_parser *p, struct wasm_interp *interp, unsigned char *wasm, unsigned long len) {
    175     wasm_parser_init(p, wasm, len, len * 16, nscript_builtins, ARRAY_SIZE(nscript_builtins));
    176 
    177     if (!parse_wasm(p)) {
    178         wasm_parser_free(p);
    179         return NSCRIPT_PARSE_ERR;
    180     }
    181 
    182     if (!wasm_interp_init(interp, &p->module)) {
    183         print_error_backtrace(&interp->errors);
    184         wasm_parser_free(p);
    185         return NSCRIPT_INIT_ERR;
    186     }
    187 
    188     //setup_wasi(&interp, argc, argv, env);
    189     //wasm_parser_free(&p);
    190     
    191     return NSCRIPT_LOADED;
    192 }