Error count(Stack* S, Stack* scope_arr) { require(2); V haystack = popS(); V needle = popS(); if (getType(haystack) != T_STR || getType(needle) != T_STR) { clear_ref(haystack); clear_ref(needle); return TypeError; } size_t haystack_len = toNewString(haystack)->size; size_t needle_len = toNewString(needle)->size; if (needle_len == 0) { pushS(int_to_value(string_length(toNewString(haystack)) + 1)); clear_ref(haystack); clear_ref(needle); return Nothing; } utf8 haystack_c = toNewString(haystack)->text; utf8 needle_c = toNewString(needle)->text; utf8index ix; int count = 0; for (ix = 0; ix < haystack_len - needle_len + 1; ) { if (!memcmp(haystack_c + ix, needle_c, needle_len)) { count++; ix += needle_len; } else { ix = nextchar(haystack_c, ix); } } pushS(int_to_value(count)); clear_ref(haystack); clear_ref(needle); return Nothing; }
Error find(Stack* S, Stack* scope_arr) { require(2); V haystack = popS(); V needle = popS(); if (getType(needle) != T_STR || getType(haystack) != T_STR) { clear_ref(needle); clear_ref(haystack); return TypeError; } NewString *needle_s = toNewString(needle); NewString *haystack_s = toNewString(haystack); if (string_length(needle_s) <= string_length(haystack_s)) { size_t haystack_len = haystack_s->size; size_t needle_len = needle_s->size; utf8 haystack_c = haystack_s->text; utf8 needle_c = needle_s->text; utf8index ix; int i = 0; for (ix = 0; ix < haystack_len - needle_len + 1; ix = nextchar(haystack_c, ix)) { if (!memcmp(haystack_c + ix, needle_c, needle_len)) { pushS(int_to_value(i)); clear_ref(needle); clear_ref(haystack); return Nothing; } i++; } } pushS(int_to_value(-1)); clear_ref(needle); clear_ref(haystack); return Nothing; }
Error ord(Stack* S, Stack* scope_arr) { require(1); V v = popS(); if (getType(v) != T_STR) { clear_ref(v); return TypeError; } NewString *s = toNewString(v); if (s->size == 0) { clear_ref(v); return ValueError; } utf8index n = 0; pushS(int_to_value(decode_codepoint(s->text, &n))); clear_ref(v); return Nothing; }
Error getbyte_blob_(Stack *S, Stack *scope_arr) { require(2); V blob = popS(); V index = popS(); Error e = Nothing; if (getType(blob) != T_BLOB || getType(index) != T_NUM) { e = TypeError; goto cleanup; } int byte = getbyte_blob(blob, toNumber(index)); if (byte < 0) { set_error_msg("Index out of range"); e = ValueError; goto cleanup; } pushS(int_to_value(byte)); cleanup: clear_ref(blob); clear_ref(index); return e; }
bool read_literals(char *oldpos, size_t size, Header* h) { int i, j; int n = 0; char type; uint32_t str_length; uint32_t ref; char *startpos = oldpos + h->size * 4; char *curpos = startpos; while (!eofreached) { type = *curpos++; if (eofreached) { break; } n++; switch (type) { case TYPE_NUM: curpos += 8; break; case TYPE_NUM | TYPE_SHORT: curpos += 3; break; case TYPE_STR: case TYPE_IDENT: memcpy(&str_length, curpos, 4); curpos += 4 + ntohl(str_length); break; case TYPE_STR | TYPE_SHORT: case TYPE_IDENT | TYPE_SHORT: str_length = (unsigned char)*curpos++; curpos += str_length; break; case TYPE_PAIR: curpos += 6; break; case TYPE_FRAC: curpos += 16; break; case TYPE_FRAC | TYPE_SHORT: curpos += 2; break; case TYPE_LIST: memcpy(&str_length, curpos, 4); curpos += 4 + 3 * ntohl(str_length); break; case TYPE_DICT: memcpy(&str_length, curpos, 4); curpos += 4 + 6 * ntohl(str_length); break; } } V* arr = calloc(n, sizeof(V)); V t; curpos = startpos; for (i = 0; i < n; i++) { type = *curpos++; if (type == TYPE_NUM) { union double_or_uint64_t d; memcpy(&d, curpos, 8); curpos += 8; d.i = ntohll(d.i); t = double_to_value(d.d); } else if (type == (TYPE_NUM | TYPE_SHORT)) { ref = 0; memcpy(((char*)&ref) + 1, curpos, 3); ref = ntohl(ref); curpos += 3; t = int_to_value(ref); } else if (type == TYPE_STR) { memcpy(&str_length, curpos, 4); curpos += 4; str_length = ntohl(str_length); if (!valid_utf8(str_length, curpos)) { set_error_msg("wrong encoding for string literal, should be UTF-8"); return false; } t = str_to_string(str_length, curpos); curpos += str_length; } else if (type == TYPE_IDENT) { memcpy(&str_length, curpos, 4); curpos += 4; str_length = ntohl(str_length); char data[str_length + 1]; memcpy(&data, curpos, str_length); data[str_length] = '\0'; t = lookup_ident(str_length, data); curpos += str_length; } else if (type == (TYPE_STR | TYPE_SHORT)) { str_length = (unsigned char)*curpos++; if (!valid_utf8(str_length, curpos)) { set_error_msg("wrong encoding for string literal, should be UTF-8"); return false; } t = str_to_string(str_length, curpos); curpos += str_length; } else if (type == (TYPE_IDENT | TYPE_SHORT)) { str_length = *curpos++; char data[str_length + 1]; memcpy(&data, curpos, str_length); data[str_length] = '\0'; t = lookup_ident(str_length, data); curpos += str_length; } else if (type == TYPE_PAIR) { ref = 0; memcpy(((char*)&ref) + 1, curpos, 3); ref = ntohl(ref); if (ref >= i) { set_error_msg("illegal pair detected"); return false; } V v1 = arr[ref]; ref = 0; memcpy(((char*)&ref) + 1, curpos + 3, 3); ref = ntohl(ref); if (ref >= i) { set_error_msg("illegal pair detected"); return false; } V v2 = arr[ref]; t = new_pair(v1, v2); curpos += 6; } else if (type == TYPE_FRAC) { int64_t numer; int64_t denom; memcpy(&numer, curpos, 8); numer = ntohll(numer); memcpy(&denom, curpos + 8, 8); denom = ntohll(denom); t = new_frac(numer, denom); curpos += 16; } else if (type == (TYPE_FRAC | TYPE_SHORT)) { int8_t numer; uint8_t denom; numer = *curpos++; denom = *curpos++; t = new_frac(numer, denom); } else if (type == TYPE_LIST) { memcpy(&str_length, curpos, 4); str_length = ntohl(str_length); t = new_list(); curpos += 4; if (str_length > 0) { uint32_t size = 64; while (size < str_length) size <<= 1; toStack(t)->size = size; toStack(t)->used = str_length; toStack(t)->nodes = calloc(size, sizeof(V)); for (j = 0; j < str_length; j++) { ref = 0; memcpy(((char*)&ref) + 1, curpos, 3); ref = ntohl(ref); toStack(t)->nodes[j] = intToV((uint64_t)ref); curpos += 3; } } } else if (type == TYPE_DICT) { memcpy(&str_length, curpos, 4); curpos += 4; str_length = ntohl(str_length); t = new_dict(); if (str_length > 0) { uint32_t size = 16; while (size < str_length) size <<= 1; toHashMap(t)->size = size; toHashMap(t)->used = str_length; toHashMap(t)->map = (Bucket**)curpos; } curpos += 6 * str_length; } else { set_error_msg("Unknown literal type."); return false; } arr[i] = t; } for (i = 0; i < n; i++) { t = arr[i]; switch(getType(t)) { case TYPE_LIST: for (j = 0; j < toStack(t)->used; j++) { toStack(t)->nodes[j] = arr[toInt(toStack(t)->nodes[j])]; } break; case TYPE_DICT: if (toHashMap(t)->map) { curpos = ((char*)toHashMap(t)->map); toHashMap(t)->map = NULL; str_length = toHashMap(t)->used; //worst abuse of variable name ever Y/Y? toHashMap(t)->used = 0; for (j = 0; j < str_length; j++) { ref = 0; memcpy(((char*)&ref) + 1, curpos, 3); ref = ntohl(ref); V key = arr[ref]; ref = 0; memcpy(((char*)&ref) + 1, curpos + 3, 3); ref = ntohl(ref); V value = arr[ref]; set_hashmap(toHashMap(t), key, value); curpos += 6; } } break; } } h->n_literals = n; h->literals = arr; return true; }