/** regexp_match : 'regexp -> string -> pos:int -> len:int -> bool <doc>Match [len] chars of a string starting at [pos] using the regexp. Return true if match found</doc> **/ static value regexp_match( value o, value s, value p, value len ) { pcredata *d; int pp,ll; val_check_kind(o,k_regexp); val_check(s,string); val_check(p,int); val_check(len,int); pp = val_int(p); ll = val_int(len); if( pp < 0 || ll < 0 || pp > val_strlen(s) || pp + ll > val_strlen(s) ) neko_error(); d = PCRE(o); if( pcre_exec(d->r,NULL,val_string(s)+pp,ll,0,0,d->matchs,d->nmatchs * 3) >= 0 ) { if( pp > 0 ) { int i; for(i=0;i<d->nmatchs * 3;i++) d->matchs[i] += pp; } d->str = s; return val_true; } else { d->str = val_null; return val_false; } }
/** file_write : 'file -> s:string -> p:int -> l:int -> int <doc> Write up to [l] chars of string [s] starting at position [p]. Returns the number of chars written which is >= 0. </doc> **/ static value file_write( value o, value s, value pp, value n ) { int p, len; fio *f; val_check_kind(o,k_file); val_check(s,string); val_check(pp,int); val_check(n,int); f = val_file(o); p = val_int(pp); len = val_int(n); if( p < 0 || len < 0 || p > val_strlen(s) || p + len > val_strlen(s) ) neko_error(); while( len > 0 ) { int d; POSIX_LABEL(file_write_again); d = (int)fwrite(val_string(s)+p,1,len,f->io); if( d <= 0 ) { HANDLE_FINTR(f->io,file_write_again); file_error("file_write",f); } p += d; len -= d; } return n; }
static value key_from_pem(value data, value pub, value pass){ mbedtls_pk_context *pk; int r, len; value v; unsigned char *buf; val_check(data, string); val_check(pub, bool); if (!val_is_null(pass)) val_check(pass, string); len = val_strlen(data)+1; buf = (unsigned char *)alloc(len); memcpy(buf, val_string(data), len-1); buf[len-1] = '\0'; pk = (mbedtls_pk_context *)alloc(sizeof(mbedtls_pk_context)); mbedtls_pk_init(pk); if( val_bool(pub) ) r = mbedtls_pk_parse_public_key( pk, buf, len ); else if( val_is_null(pass) ) r = mbedtls_pk_parse_key( pk, buf, len, NULL, 0 ); else r = mbedtls_pk_parse_key( pk, buf, len, (const unsigned char*)val_string(pass), val_strlen(pass) ); if( r != 0 ){ mbedtls_pk_free(pk); return ssl_error(r); } v = alloc_abstract(k_pkey,pk); val_gc(v,free_pkey); return v; }
/** file_read : 'file -> s:string -> p:int -> l:int -> int <doc> Read up to [l] chars into the string [s] starting at position [p]. Returns the number of chars readed which is > 0 (or 0 if l == 0). </doc> **/ static value file_read( value o, value s, value pp, value n ) { fio *f; int p; int len; val_check_kind(o,k_file); val_check(s,string); val_check(pp,int); val_check(n,int); f = val_file(o); p = val_int(pp); len = val_int(n); if( p < 0 || len < 0 || p > val_strlen(s) || p + len > val_strlen(s) ) neko_error(); while( len > 0 ) { int d; POSIX_LABEL(file_read_again); d = (int)fread((char*)val_string(s)+p,1,len,f->io); if( d <= 0 ) { int size = val_int(n) - len; HANDLE_FINTR(f->io,file_read_again); if( size == 0 ) file_error("file_read",f); return alloc_int(size); } p += d; len -= d; } return n; }
EXTERN int val_compare( value a, value b ) { char tmp_buf[32]; switch( C(val_type(a),val_type(b)) ) { case C(VAL_INT,VAL_INT): return icmp(val_int(a),val_int(b)); case C(VAL_INT32,VAL_INT): return icmp(val_int32(a),val_int(b)); case C(VAL_INT,VAL_INT32): return icmp(val_int(a),val_int32(b)); case C(VAL_INT32,VAL_INT32): return icmp(val_int32(a),val_int32(b)); case C(VAL_INT,VAL_FLOAT): return fcmp(val_int(a),val_float(b)); case C(VAL_INT32,VAL_FLOAT): return fcmp(val_int32(a),val_float(b)); case C(VAL_INT,VAL_STRING): return scmp(tmp_buf,sprintf(tmp_buf,"%d",val_int(a)),val_string(b),val_strlen(b)); case C(VAL_INT32,VAL_STRING): return scmp(tmp_buf,sprintf(tmp_buf,"%d",val_int32(a)),val_string(b),val_strlen(b)); case C(VAL_FLOAT,VAL_INT): return fcmp(val_float(a),val_int(b)); case C(VAL_FLOAT,VAL_INT32): return fcmp(val_float(a),val_int32(b)); case C(VAL_FLOAT,VAL_FLOAT): return fcmp(val_float(a),val_float(b)); case C(VAL_FLOAT,VAL_STRING): return scmp(tmp_buf,sprintf(tmp_buf,FLOAT_FMT,val_float(a)),val_string(b),val_strlen(b)); case C(VAL_STRING,VAL_INT): return scmp(val_string(a),val_strlen(a),tmp_buf,sprintf(tmp_buf,"%d",val_int(b))); case C(VAL_STRING,VAL_INT32): return scmp(val_string(a),val_strlen(a),tmp_buf,sprintf(tmp_buf,"%d",val_int32(b))); case C(VAL_STRING,VAL_FLOAT): return scmp(val_string(a),val_strlen(a),tmp_buf,sprintf(tmp_buf,FLOAT_FMT,val_float(b))); case C(VAL_STRING,VAL_BOOL): return scmp(val_string(a),val_strlen(a),val_bool(b)?"true":"false",val_bool(b)?4:5); case C(VAL_BOOL,VAL_STRING): return scmp(val_bool(a)?"true":"false",val_bool(a)?4:5,val_string(b),val_strlen(b)); case C(VAL_STRING,VAL_STRING): return scmp(val_string(a),val_strlen(a),val_string(b),val_strlen(b)); case C(VAL_BOOL,VAL_BOOL): return (a == b) ? 0 : (val_bool(a) ? 1 : -1); case C(VAL_OBJECT,VAL_OBJECT): if( a == b ) return 0; { value tmp = val_field(a,id_compare); if( tmp == val_null ) return invalid_comparison; a = val_callEx(a,tmp,&b,1,NULL); } if( val_is_int(a) ) return val_int(a); return invalid_comparison; default: if( a == b ) return 0; return invalid_comparison; } }
value neko_append_strings( value s1, value s2 ) { int len1 = val_strlen(s1); int len2 = val_strlen(s2); value v = alloc_empty_string(len1+len2); memcpy((char*)val_string(v),val_string(s1),len1); memcpy((char*)val_string(v)+len1,val_string(s2),len2+1); return v; }
/** escape : 'connection -> string -> string <doc>Escape the string for inserting into a SQL request</doc> **/ static value escape( value o, value s ) { int len; value sout; val_check_kind(o,k_connection); val_check(s,string); len = val_strlen(s) * 2; sout = alloc_empty_string(len); len = mysql_real_escape_string(CNX(o)->m,val_string(sout),val_string(s),val_strlen(s)); val_set_length(sout,len); return sout; }
/** buffer_add_sub : 'buffer -> s:string -> p:int -> l:int -> void <doc>Add [l] characters of the string [s] starting at position [p]. An error occurs if out of string bounds.</doc> **/ static value buffer_add_sub( value b, value v, value p, value l ) { val_check_kind(b,k_buffer); val_check(v,string); val_check(p,int); val_check(l,int); if( val_int(p) < 0 || val_int(l) < 0 ) neko_error(); if( val_strlen(v) < val_int(p) || val_strlen(v) < val_int(p) + val_int(l) ) neko_error(); buffer_append_sub( (buffer)val_data(b), val_string(v) + val_int(p) , val_int(l) ); return val_true; }
/** socket_send_to : 'socket -> buf:string -> pos:int -> length:int -> addr:{host:'int32,port:int} -> int <doc> Send data from an unconnected UDP socket to the given address. </doc> **/ static value socket_send_to( value o, value data, value pos, value len, value vaddr ) { int p,l,dlen; value host, port; struct sockaddr_in addr; val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); val_check(vaddr,object); host = val_field(vaddr, f_host); port = val_field(vaddr, f_port); val_check(host,int32); val_check(port,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); memset(&addr,0,sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = htons(val_int(port)); *(int*)&addr.sin_addr.s_addr = val_int32(host); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(send_again); dlen = sendto(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL, (struct sockaddr*)&addr, sizeof(addr)); if( dlen == SOCKET_ERROR ) { HANDLE_EINTR(send_again); return block_error(); } return alloc_int(dlen); }
/** socket_recv : 'socket -> buf:string -> pos:int -> len:int -> int <doc>Read up to [len] bytes from [buf] starting at [pos] from a connected socket. Return the number of bytes readed.</doc> **/ static value socket_recv( value o, value data, value pos, value len ) { int p,l,dlen,ret; int retry = 0; val_check_kind(o,k_socket); val_check(data,string); val_check(pos,int); val_check(len,int); p = val_int(pos); l = val_int(len); dlen = val_strlen(data); if( p < 0 || l < 0 || p > dlen || p + l > dlen ) neko_error(); POSIX_LABEL(recv_again); if( retry++ > NRETRYS ) { sock_tmp t; t.sock = val_sock(o); t.buf = val_string(data) + p; t.size = l; neko_thread_blocking(tmp_recv,&t); ret = t.ret; } else ret = recv(val_sock(o), val_string(data) + p , l, MSG_NOSIGNAL); if( ret == SOCKET_ERROR ) { HANDLE_EINTR(recv_again); return block_error(); } return alloc_int(ret); }
/** udpr_write : ENetPeer-> data:string -> Channel->Reliable:Bool->void Send a full string [data] **/ static value udpr_write(value p, value data, value chan, value reliable) { ENetPeer *peer; ENetPacket *packet; int c; val_check_kind(p,k_udprpeer); val_check(data,string); val_check(chan,int); val_check(reliable,bool); c = val_int(chan); peer = (ENetPeer *)val_data(p); #ifdef ENET_DEBUG_FULL fprintf(stderr, "udpr_write: Writing packet '%s' to peer %x on channel %d\n", val_string(data), peer, c); fprintf(stderr, "peer state: %d peer channels: %d\n", peer -> state, peer->channelCount); #endif if(peer == NULL || c < 0 || c > 255) neko_error(); packet = enet_packet_create( val_string(data), val_strlen(data), val_bool(reliable) ? ENET_PACKET_FLAG_RELIABLE : 0); if(enet_peer_send(peer, c, packet)) { #ifdef ENET_DEBUG fprintf(stderr, "ERROR: udpr_write: enet_peer_send error\n"); fprintf(stderr, "peer state: %d peer channels: %d\n", peer -> state, peer->channelCount); #endif neko_error(); } return val_true; }
static value dgst_sign(value data, value key, value alg){ const mbedtls_md_info_t *md; int r = -1; size_t olen = 0; value out; unsigned char *buf; unsigned char hash[32]; val_check(data, string); val_check_kind(key, k_pkey); val_check(alg, string); md = mbedtls_md_info_from_string(val_string(alg)); if( md == NULL ){ val_throw(alloc_string("Invalid hash algorithm")); return val_null; } if( (r = mbedtls_md( md, (const unsigned char *)val_string(data), val_strlen(data), hash )) != 0 ) return ssl_error(r); out = alloc_empty_string(MBEDTLS_MPI_MAX_SIZE); buf = (unsigned char *)val_string(out); if( (r = mbedtls_pk_sign( val_pkey(key), mbedtls_md_get_type(md), hash, 0, buf, &olen, mbedtls_ctr_drbg_random, &ctr_drbg )) != 0 ) return ssl_error(r); buf[olen] = 0; val_set_size(out, olen); return out; }
/** udpr_send : peer -> data:string -> pos:int -> len:int -> chan:int -> reliable:bool -> int Send up to [len] bytes from [buf] starting at [pos] over a connected socket on channel [chan] using reliable setting [reliable] Return the number of bytes sent. **/ static value udpr_send( value p, value data, value pos, value len, value chan, value reliable ) { ENetPeer *peer; ENetPacket *packet; int pp,l,sLen,c; val_check_kind(p,k_udprpeer); val_check(data,string); val_check(pos,int); val_check(len,int); val_check(chan,int); val_check(reliable,bool); peer = (ENetPeer *)val_data(p); pp = val_int(pos); l = val_int(len); sLen = val_strlen(data); c = val_int(chan); if( peer == NULL || c < 0 || c > 255 || pp < 0 || l < 0 || pp > sLen || pp + l > sLen ) neko_error(); packet = enet_packet_create( val_string(data) + pp, l, val_bool(reliable) ? ENET_PACKET_FLAG_RELIABLE : 0); if(enet_peer_send(peer, c, packet)) neko_error(); return alloc_int(l); }
value hxfcgi_print(value hreq,value msg) { val_check(msg,string); hxfcgi::Request *req = get_request(hreq); req->printHeaders(); for (int i = 0; i < val_strlen(msg);i++) req->pchar(val_string(msg)[i]); return val_null; }
/** escape : 'connection -> string -> string <doc>Escape the string for inserting into a SQL request</doc> **/ static value escape( value o, value s ) { int len; value sout; val_check_kind(o,k_connection); val_check(s,string); len = val_strlen(s) * 2; sout = alloc_empty_string(len); len = mysql_real_escape_string(CNX(o)->m,val_string(sout),val_string(s),val_strlen(s)); if( len < 0 ) { buffer b = alloc_buffer("Unsupported charset : "); buffer_append(b,mysql_character_set_name(CNX(o)->m)); bfailure(b); } val_set_length(sout,len); val_string(sout)[len] = 0; return sout; }
/** update_crc32 : crc:'int32 -> string -> pos:int -> len:int -> 'int32 <doc>Update a CRC32 value with a substring</doc> **/ static value update_crc32( value crc, value s, value pos, value len ) { val_check(crc,int); val_check(s,string); val_check(pos,int); val_check(len,int); if( val_int(pos) < 0 || val_int(len) < 0 || val_int(pos) + val_int(len) > val_strlen(s) ) return alloc_null(); return alloc_int32(crc32(val_int(crc),(Bytef*)(val_string(s)+val_int(pos)),val_int(len))); }
// String access int api_val_strlen(value arg1) { if (val_is_string(arg1)) return val_strlen(arg1); value l = val_field(arg1,length_id); if (val_is_int(l)) return val_int(l); return 0; }
/** $sget : string -> n:int -> int? <doc>Return the [n]th char of a string or [null] if out of bounds</doc> **/ static value builtin_sget( value s, value p ) { int pp; val_check(s,string); val_check(p,int); pp = val_int(p); if( pp < 0 || pp >= val_strlen(s) ) return val_null; return alloc_int( (unsigned char)(val_string(s)[pp]) ); }
/** request : 'db -> sql:string -> 'result <doc>Executes the SQL request and returns its result</doc> **/ static value request( value v, value sql ) { database *db; result *r; const char *tl; int i,j; val_check_kind(v,k_db); val_check(sql,string); db = val_db(v); r = (result*)alloc(sizeof(result)); r->db = db; if( sqlite3_prepare(db->db,val_string(sql),val_strlen(sql),&r->r,&tl) != SQLITE_OK ) { buffer b = alloc_buffer("Sqlite error in "); val_buffer(b,sql); buffer_append(b," : "); buffer_append(b,sqlite3_errmsg(db->db)); val_throw(buffer_to_string(b)); } if( *tl ) { sqlite3_finalize(r->r); val_throw(alloc_string("Cannot execute several SQL requests at the same time")); } r->ncols = sqlite3_column_count(r->r); r->names = (field*)alloc_private(sizeof(field)*r->ncols); r->bools = (int*)alloc_private(sizeof(int)*r->ncols); r->first = 1; r->done = 0; for(i=0;i<r->ncols;i++) { field id = val_id(sqlite3_column_name(r->r,i)); const char *dtype = sqlite3_column_decltype(r->r,i); for(j=0;j<i;j++) if( r->names[j] == id ) { if( strcmp(sqlite3_column_name(r->r,i),sqlite3_column_name(r->r,j)) == 0 ) { buffer b = alloc_buffer("Error, same field is two times in the request "); val_buffer(b,sql); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } else { buffer b = alloc_buffer("Error, same field ids for : "); buffer_append(b,sqlite3_column_name(r->r,i)); buffer_append(b," and "); buffer_append(b,sqlite3_column_name(r->r,j)); buffer_append_char(b,'.'); sqlite3_finalize(r->r); val_throw(buffer_to_string(b)); } } r->names[i] = id; r->bools[i] = dtype?(strcmp(dtype,"BOOL") == 0):0; } // changes in an update/delete if( db->last != NULL ) finalize_result(val_result(db->last),0); db->last = alloc_abstract(k_result,r); return db->last; }
/** $sfind : src:string -> pos:int -> pat:string -> int? <doc> Return the first position starting at [pos] in [src] where [pat] was found. Return null if not found. Error if [pos] is outside [src] bounds. </doc> **/ static value builtin_sfind( value src, value pos, value pat ) { int p, l, l2; const char *ptr; val_check(src,string); val_check(pos,int); val_check(pat,string); p = val_int(pos); l = val_strlen(src); l2 = val_strlen(pat); if( p < 0 || p >= l ) neko_error(); ptr = val_string(src) + p; while( l - p >= l2 ) { if( memcmp(ptr,val_string(pat),l2) == 0 ) return alloc_int(p); p++; ptr++; } return val_null; }
/** $ssub : string -> p:int -> l:int -> string <doc> Return [l] chars starting at position [p] of a string. An error occurs if out of string bounds. </doc> **/ static value builtin_ssub( value s, value p, value l ) { int pp , ll; val_check(s,string); val_check(p,int); val_check(l,int); pp = val_int(p); ll = val_int(l); if( pp < 0 || ll < 0 || pp + ll < 0 || pp + ll > val_strlen(s) ) neko_error(); return copy_string( val_string(s) + pp , ll ); }
/** sys_command : string -> int <doc>Run the shell command and return exit code</doc> **/ static value sys_command( value cmd ) { val_check(cmd,string); if( val_strlen(cmd) == 0 ) return alloc_int(-1); #ifdef NEKO_WINDOWS return alloc_int( system(val_string(cmd)) ); #else int status = system(val_string(cmd)); return alloc_int( WEXITSTATUS(status) | (WTERMSIG(status) << 8) ); #endif }
/** regexp_match : 'regexp -> string -> pos:int -> len:int -> bool <doc>Match [len] chars of a string starting at [pos] using the regexp. Return true if match found</doc> **/ static value regexp_match( value o, value s, value p, value len ) { pcredata *d; int pp,ll; val_check_kind(o,k_regexp); val_check(s,string); val_check(p,int); val_check(len,int); pp = val_int(p); ll = val_int(len); if( pp < 0 || ll < 0 || pp > val_strlen(s) || pp + ll > val_strlen(s) ) return alloc_null(); d = PCRE(o); if( pcre_exec(d->r,NULL,val_string(s),ll+pp,pp,0,d->matchs,d->nmatchs * 3) >= 0 ) { d->str = s; return alloc_bool(true); } else { d->str = alloc_null(); return alloc_bool(false); } }
/** regexp_match : 'regexp -> string -> pos:int -> len:int -> bool <doc>Match [len] chars of a string starting at [pos] using the regexp. Return true if match found</doc> **/ static value regexp_match( value o, value s, value p, value len ) { pcredata *d; int pp,ll; val_check_kind(o,k_regexp); val_check(s,string); val_check(p,int); val_check(len,int); pp = val_int(p); ll = val_int(len); if( pp < 0 || ll < 0 || pp > val_strlen(s) || pp + ll > val_strlen(s) ) neko_error(); d = PCRE(o); if( do_exec(d,val_string(s),ll+pp,pp) ) { d->str = s; return val_true; } else { d->str = val_null; return val_false; } }
static value key_from_der( value data, value pub ){ mbedtls_pk_context *pk; int r; value v; val_check(data, string); val_check(pub, bool); pk = (mbedtls_pk_context *)alloc(sizeof(mbedtls_pk_context)); mbedtls_pk_init(pk); if( val_bool(pub) ) r = mbedtls_pk_parse_public_key( pk, (const unsigned char*)val_string(data), val_strlen(data) ); else r = mbedtls_pk_parse_key( pk, (const unsigned char*)val_string(data), val_strlen(data), NULL, 0 ); if( r != 0 ){ mbedtls_pk_free(pk); return ssl_error(r); } v = alloc_abstract(k_pkey, pk); val_gc(v,free_pkey); return v; }
value shaderSource( value shader, value string ) { const GLchar *s[] = {val_string( string )}; GLint len[] = {val_strlen( string )}; glShaderSource( (GLuint)val_int( shader ), (GLsizei)1, s, len ); return alloc_null( ); }
/** string_split : s:string -> sep:string -> string list <doc>split the string [s] using separator [sep]</doc> **/ static value string_split( value o, value s ) { value l, first; int ilen; int slen; int start = 0; int pos; val_check(s,string); val_check(o,string); ilen = val_strlen(o); slen = val_strlen(s); l = alloc_null(); first = alloc_null(); for(pos=slen?0:1;pos<=ilen-slen;pos++) if( memcmp(val_string(o)+pos,val_string(s),slen) == 0 ) { value ss = copy_string(val_string(o)+start,pos-start); value l2 = alloc_array(2); val_array_set_i(l2,0,ss); val_array_set_i(l2,1,alloc_null()); if( val_is_null(first) ) first = l2; else val_array_set_i(l,1,l2); l = l2; start = pos + slen; if( slen ) pos = start - 1; } if( ilen > 0 && slen ) { value ss = start ? copy_string(val_string(o)+start,ilen-start) : o; value l2 = alloc_array(2); val_array_set_i(l2,0,ss); val_array_set_i(l2,1,alloc_null()); if( val_is_null(first)) first = l2; else val_array_set_i(l,1,l2); } return first; }
/** unserialize : string -> #loader -> any <doc>Unserialize a stored value. Need a loader to look for modules if some bytecode functions have been serialized. </doc> **/ static value unserialize( value s, value loader ) { sbuffer b; val_check(s,string); b.cur = (unsigned char*)val_string(s); b.pos = 0; b.olds = NULL; b.trefs = NULL; b.tsize = 0; b.nrefs = 0; b.size = val_strlen(s); b.totlen = 0; return unserialize_rec(&b,loader); }
/** $sset : string -> n:int -> c:int -> int? <doc> Set the [n]th char of a string to ([c] & 255). Returns the char set or [null] if out of bounds. </doc> **/ static value builtin_sset( value s, value p, value c ) { int pp; unsigned char cc; val_check(s,string); val_check(p,int); val_check(c,int); pp = val_int(p); if( pp < 0 || pp >= val_strlen(s) ) return val_null; cc = (unsigned char)val_int(c); val_string(s)[pp] = (char)cc; return alloc_int(cc); }
/** module_read_string : string -> loader:object -> 'module <doc> Read a module using the specified string datas. </doc> **/ static value module_read_string( value str, value loader ) { neko_module *m; string_pos p; val_check(str,string); val_check(loader,object); p.p = val_string(str); p.len = val_strlen(str); m = neko_read_module(neko_string_reader,&p,loader); if( m == NULL ) neko_error(); m->name = alloc_string(""); return alloc_abstract(neko_kind_module,m); }