static inline int enc_double(Encoder* e, double val) { char* start; size_t len; size_t i; if(!enc_ensure(e, 32)) { return 0; } start = &(e->p[e->i]); sprintf(start, "%0.20g", val); len = strlen(start); // Check if we have a decimal point for(i = 0; i < len; i++) { if(start[i] == '.' || start[i] == 'e' || start[i] == 'E') goto done; } if(len > 29) return 0; // Force a decimal point start[len++] = '.'; start[len++] = '0'; done: e->i += len; e->count++; return 1; }
static inline int enc_char(Encoder* e, char c) { if(!enc_ensure(e, 1)) { return 0; } e->p[e->i++] = c; return 1; }
static inline int enc_literal(Encoder* e, const char* literal, size_t len) { if(!enc_ensure(e, len)) { return 0; } memcpy(&(e->p[e->i]), literal, len); e->i += len; e->count++; return 1; }
static inline int enc_long(Encoder* e, long val) { if(!enc_ensure(e, 32)) { return 0; } snprintf(&(e->p[e->i]), 32, "%ld", val); e->i += strlen(&(e->p[e->i])); e->count++; return 1; }
static inline int enc_double(Encoder* e, double val) { if(!enc_ensure(e, 32)) { return 0; } //snprintf(&(e->p[e->i]), 31, "%0.20g", val); sprintf(&(e->p[e->i]), "%.20g", val); e->i += strlen(&(e->p[e->i])); e->count++; return 1; }
static inline int enc_long(Encoder* e, ErlNifSInt64 val) { if(!enc_ensure(e, 32)) { return 0; } #if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) snprintf(&(e->p[e->i]), 32, "%ld", val); #elif SIZEOF_LONG == 8 snprintf(&(e->p[e->i]), 32, "%ld", val); #else snprintf(&(e->p[e->i]), 32, "%lld", val); #endif e->i += strlen(&(e->p[e->i])); e->count++; return 1; }
static inline int enc_double(Encoder* e, double val) { char* start; size_t len; if(!enc_ensure(e, 32)) { return 0; } start = &(e->p[e->i]); if(!double_to_shortest(start, e->curr->size, &len, val)) { return 0; } e->i += len; e->count++; return 1; }
static inline int enc_string(Encoder* e, ERL_NIF_TERM val) { ErlNifBinary bin; char atom[512]; unsigned char* data; size_t size; int esc_extra = 0; int ulen; int uval; int i; if(enif_is_binary(e->env, val)) { if(!enif_inspect_binary(e->env, val, &bin)) { return 0; } data = bin.data; size = bin.size; } else if(enif_is_atom(e->env, val)) { if(!enif_get_atom(e->env, val, atom, 512, ERL_NIF_LATIN1)) { return 0; } data = (unsigned char*) atom; size = strlen(atom); } else { return 0; } i = 0; while(i < size) { switch((char) data[i]) { case '\"': case '\\': case '\b': case '\f': case '\n': case '\r': case '\t': esc_extra += 1; i++; continue; default: if(data[i] < 0x20) { esc_extra += 5; i++; continue; } else if(data[i] < 0x80) { i++; continue; } ulen = utf8_validate(&(data[i]), size - i); if(ulen < 0) { return 0; } if(e->uescape) { uval = utf8_to_unicode(&(data[i]), ulen); if(uval < 0) { return 0; } esc_extra += utf8_esc_len(uval); if(ulen < 0) { return 0; } } i += ulen; } } if(!enc_ensure(e, size + esc_extra + 2)) { return 0; } e->p[e->i++] = '\"'; i = 0; while(i < size) { switch((char) data[i]) { case '\"': case '\\': e->p[e->i++] = '\\'; e->u[e->i++] = data[i]; i++; continue; case '\b': e->p[e->i++] = '\\'; e->p[e->i++] = 'b'; i++; continue; case '\f': e->p[e->i++] = '\\'; e->p[e->i++] = 'f'; i++; continue; case '\n': e->p[e->i++] = '\\'; e->p[e->i++] = 'n'; i++; continue; case '\r': e->p[e->i++] = '\\'; e->p[e->i++] = 'r'; i++; continue; case '\t': e->p[e->i++] = '\\'; e->p[e->i++] = 't'; i++; continue; default: if(data[i] < 0x20) { ulen = unicode_uescape(data[i], &(e->p[e->i])); if(ulen < 0) { return 0; } e->i += ulen; i++; } else if((data[i] & 0x80) && e->uescape) { uval = utf8_to_unicode(&(data[i]), size-i); if(uval < 0) { return 0; } ulen = unicode_uescape(uval, &(e->p[e->i])); if(ulen < 0) { return 0; } e->i += ulen; ulen = utf8_len(uval); if(ulen < 0) { return 0; } i += ulen; } else { e->u[e->i++] = data[i++]; } } } e->p[e->i++] = '\"'; e->count++; return 1; }