/** socket_epoll_register : 'epoll -> 'socket -> int <doc>Register a socket with an epoll instance to be notified of events. Returns the socket's fd.</doc> **/ static value socket_epoll_register(value e, value s, value events) { SOCKET sock; int event_types; epolldata *ep; val_check_kind(e,k_epoll); val_check_kind(s,k_socket); val_check(events,int); sock = val_sock(s); event_types = val_int(events); ep = val_epoll(e); #ifndef HAS_EPOLL if (sock >= FD_SETSIZE) val_throw(alloc_string("Can't register file descriptor >= FD_SETSIZE")); if (event_types & EPOLLIN) { if (ep->rcount >= FD_SETSIZE) val_throw(alloc_string("Too many sockets (on non-Linux platforms, 'epoll' uses select)")); val_array_ptr(ep->read)[ep->rcount++] = s; } if (event_types & EPOLLOUT) { if (ep->wcount >= FD_SETSIZE) val_throw(alloc_string("Too many sockets (on non-Linux platforms, 'epoll' uses select)")); val_array_ptr(ep->write)[ep->wcount++] = s; } #else struct epoll_event ev; ev.events = event_types; ev.data.fd = sock; int ret = epoll_ctl(ep->epollfd, EPOLL_CTL_ADD, sock, &ev); if (ret == -1) val_throw(alloc_int(errno)); #endif return alloc_int(sock); }
DEFINE_FUNC_1(webp_get_features, data_buffer_value) { if (!val_is_buffer(data_buffer_value)) { val_throw(alloc_string("webp_get_features: Expected to be a buffer")); return alloc_null(); } buffer data_buffer = val_to_buffer(data_buffer_value); int data_len = buffer_size(data_buffer); char *data_ptr = buffer_data(data_buffer); WebPBitstreamFeatures features = {0}; VP8StatusCode code = WebPGetFeatures((const unsigned char *)data_ptr, data_len, &features); if (code != VP8_STATUS_OK) { val_throw(alloc_string("webp_get_features: Error: (code != VP8_STATUS_OK)")); return alloc_null(); } value array = alloc_array(7); val_array_set_i(array, 0, alloc_int(features.width)); val_array_set_i(array, 1, alloc_int(features.height)); val_array_set_i(array, 2, alloc_int(features.has_alpha)); //val_array_set_i(array, 3, alloc_int(features.bitstream_version)); val_array_set_i(array, 3, alloc_int(0)); val_array_set_i(array, 4, alloc_int(features.no_incremental_decoding)); val_array_set_i(array, 5, alloc_int(features.rotate)); val_array_set_i(array, 6, alloc_int(features.uv_sampling)); return array; }
DEFINE_FUNC_1(webp_decode_argb, data_buffer_value) { if (!val_is_buffer(data_buffer_value)) { val_throw(alloc_string("webp_decode_argb: Expected to be a buffer")); return alloc_null(); } buffer data_buffer = val_to_buffer(data_buffer_value); int data_len = buffer_size(data_buffer); char *data_ptr = buffer_data(data_buffer); int webp_width = -1, webp_height = -1; char *webp_data_ptr = (char *)WebPDecodeARGB((const unsigned char *)data_ptr, data_len, &webp_width, &webp_height); int webp_data_len = webp_width * webp_height * 4; if (webp_data_ptr == NULL) { val_throw(alloc_string("webp_decode_argb: Invalid webp data")); return alloc_null(); } buffer webp_buffer = alloc_buffer_len(0); buffer_append_sub(webp_buffer, webp_data_ptr, webp_data_len); buffer_set_size(webp_buffer, webp_data_len); value array = alloc_array(3); val_array_set_i(array, 0, alloc_int(webp_width)); val_array_set_i(array, 1, alloc_int(webp_height)); val_array_set_i(array, 2, buffer_val(webp_buffer)); if (webp_data_ptr != NULL) free(webp_data_ptr); return array; }
value hx_zmq_construct (value io_threads) { if (!val_is_int(io_threads)) return alloc_null(); int _io_threads = val_int(io_threads); if (_io_threads <= 0) { val_throw(alloc_int(EINVAL)); return alloc_null(); } void *c = zmq_init (_io_threads); int err = zmq_errno(); if (c == NULL) { val_throw (alloc_int(err)); return alloc_null(); } // See: http://nekovm.org/doc/ffi#abstracts_and_kinds value v = alloc_abstract(k_zmq_context_handle,c); val_gc(v,finalize_context); // finalize_context is called when the abstract value is garbage collected return v; }
value hx_zmq_getbytessockopt(value socket_handle_,value option_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } int rc = 0; int err = 0; char optval [255]; size_t optvallen = 255; rc = zmq_getsockopt(val_data(socket_handle_),val_int(option_),&optval, &optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_int(0); } // Return data to Haxe // Create a return buffer byte array, by memcopying the message data, then discard the ZMQ message buffer b = alloc_buffer(NULL); buffer_append_sub(b,optval,optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return buffer_val(b); }
value hx_zmq_getint64sockopt(value socket_handle_,value option_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } int rc = 0; int err = 0; uint64_t optval = 0; size_t optvallen = sizeof(optval); rc = zmq_getsockopt(val_data(socket_handle_),val_int(option_),&optval, &optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_int(0); } value ret = alloc_empty_object(); alloc_field(ret, val_id("hi"),alloc_int(optval >> 32)); alloc_field(ret, val_id("lo"),alloc_int(optval & 0xFFFFFFFF)); return ret; }
value hx_zmq_setint64sockopt(value socket_handle_,value option_, value hi_optval_, value lo_optval_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } if (!val_is_int(hi_optval_) || !val_is_int(lo_optval_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } uint64_t _optval64 = val_int(hi_optval_); _optval64 <<= 32; // Shift the hi int into the top half of the uint64_t value _optval64 += val_int(lo_optval_); int rc = 0; int err = 0; int option = val_int(option_); size_t optvallen = sizeof(_optval64); rc = zmq_setsockopt (val_data(socket_handle_), option, &_optval64, optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return alloc_int(rc); }
/* See Socket.cpp from jzmq library */ value hx_zmq_setintsockopt(value socket_handle_,value option_, value optval_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } if (!val_is_int(optval_)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } int rc = 0; int err = 0; int ival = val_int(optval_); int option = val_int(option_); size_t optvallen = sizeof(ival); rc = zmq_setsockopt (val_data(socket_handle_), option, &ival, optvallen); err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return alloc_int(rc); }
/** result_next : 'result -> object? <doc>Returns the next row in the result or [null] if no more result.</doc> **/ static value result_next( value v ) { int i; result *r; val_check_kind(v,k_result); r = val_result(v); if( r->done ) return val_null; switch( sqlite3_step(r->r) ) { case SQLITE_ROW: r->first = 0; v = alloc_object(NULL); for(i=0;i<r->ncols;i++) { value f; switch( sqlite3_column_type(r->r,i) ) { case SQLITE_NULL: f = val_null; break; case SQLITE_INTEGER: if( r->bools[i] ) f = alloc_bool(sqlite3_column_int(r->r,i)); else f = alloc_int(sqlite3_column_int(r->r,i)); break; case SQLITE_FLOAT: f = alloc_float(sqlite3_column_double(r->r,i)); break; case SQLITE_TEXT: f = alloc_string((char*)sqlite3_column_text(r->r,i)); break; case SQLITE_BLOB: { int size = sqlite3_column_bytes(r->r,i); f = alloc_empty_string(size); memcpy(val_string(f),sqlite3_column_blob(r->r,i),size); break; } default: { buffer b = alloc_buffer("Unknown Sqlite type #"); val_buffer(b,alloc_int(sqlite3_column_type(r->r,i))); val_throw(buffer_to_string(b)); } } alloc_field(v,r->names[i],f); } return v; case SQLITE_DONE: finalize_result(r,1); return val_null; case SQLITE_BUSY: val_throw(alloc_string("Database is busy")); case SQLITE_ERROR: sqlite_error(r->db->db); default: neko_error(); } return val_null; }
/** 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; }
static value block_error() { #ifdef NEKO_WINDOWS int err = WSAGetLastError(); if( err == WSAEWOULDBLOCK || err == WSAEALREADY || err == WSAETIMEDOUT ) #else if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY ) #endif val_throw(alloc_string("Blocking")); val_throw(alloc_string("ssl network error")); return val_true; }
static value systray_create_icon( value w, value iconpath, value tooltip ) { val_check(tooltip,string); if ( !(val_is_string(iconpath) || val_is_null(iconpath)) ) val_throw(alloc_string(tray_icon_error)); else { tray_icon *tray = systools_win_create_tray_icon(val_hwnd(w),val_string(iconpath),val_string(tooltip)); if (!tray) val_throw(alloc_string(tray_icon_error)); return alloc_abstract(k_tray_icon,tray); } return val_null; }
static value block_error() { gc_exit_blocking(); #ifdef NEKO_WINDOWS int err = WSAGetLastError(); if( err == WSAEWOULDBLOCK || err == WSAEALREADY ) #else if( errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS || errno == EALREADY ) #endif val_throw(alloc_string("Blocking")); else { val_throw(alloc_string("EOF")); } return alloc_null(); }
/** Connect out from a server socket. Returns an ENetPeer *, which has not yet connected, or throws if connection fails. **/ static value udpr_connect_out(value h, value ip, value port, value channels, value timeout) { ENetAddress address; ENetEvent event; ENetHost *host; ENetPeer *peer; int to; val_check_kind(h,k_udprhost); // checked in address population //val_check(ip,int); //val_check(port,int); val_check(channels,int); val_check(timeout,int); to = val_int(timeout); if(to < 0) to = 5000; host = (ENetHost *)val_data(h); if(populate_address(&address, ip, port) != val_true) val_throw(alloc_string("address")); //neko_error(); // Initiate the connection with channels 0..channels-1 peer = enet_host_connect (host, &address, (size_t)val_int(channels)); if (peer == NULL) //val_throw( alloc_string("Host not found") ); neko_error(); value v = alloc_abstract(k_udprpeer,peer); return v; }
value fcListFonts( value v_add ) { int i; FcFontSet *fonts = FcConfigGetFonts( 0, FcSetSystem ); if( fonts == NULL ) val_throw( alloc_string("Fontconfig couldn't find any fonts") ); for( i=0; i<fonts->nfont; i++ ) { FcPattern *font = fonts->fonts[i]; FcChar8 *familyName; FcChar8 *style; int weight, slant; bool outline; FcPatternGetBool( font, FC_OUTLINE, 0, &outline ); if( outline ) { FcPatternGetString( font, FC_FAMILY, 0, &familyName ); FcPatternGetString( font, FC_STYLE, 0, &style); FcPatternGetInteger( font, FC_WEIGHT, 0, &weight); FcPatternGetInteger( font, FC_SLANT, 0, &slant); // name = FcNameUnparse( font ); // printf("\nFont: %s || %s\n", familyName, style ); // FcPatternPrint( font ); value arg[4] = { alloc_string((const char *)familyName), alloc_string((const char *)style), alloc_int(weight), alloc_int(slant) }; val_callN( v_add, arg, 4 ); } } }
EXTERN void neko_thread_blocking( thread_main_func f, void *p ) { # if !defined(NEKO_THREADS) f(p); // nothing # elif defined(NEKO_WINDOWS) f(p); // we don't have pthreads issues # else // we have different APIs depending on the GC version, make sure we load // the good one at runtime static callb_func do_blocking = NULL; static std_func start = NULL, end = NULL; if( do_blocking ) do_blocking(f,p); else if( start ) { start(); f(p); end(); } else { void *self = dlopen(NULL,0); do_blocking = (callb_func)dlsym(self,"GC_do_blocking"); if( !do_blocking ) { start = (std_func)dlsym(self,"GC_start_blocking"); end = (std_func)dlsym(self,"GC_end_blocking"); if( !start || !end ) val_throw(alloc_string("Could not init GC blocking API")); } neko_thread_blocking(f,p); } # endif }
/** process_exit : 'process -> int <doc> Wait until the process terminate, then returns its exit code. </doc> **/ static value process_exit( value vp ) { vprocess *p; val_check_kind(vp,k_process); p = val_process(vp); # ifdef NEKO_WINDOWS { DWORD rval; WaitForSingleObject(p->pinf.hProcess,INFINITE); if( !GetExitCodeProcess(p->pinf.hProcess,&rval) ) neko_error(); return alloc_int(rval); } # else int rval; while( waitpid(p->pid,&rval,0) != p->pid ) { if( errno == EINTR ) continue; neko_error(); } if( !WIFEXITED(rval) ) { if (WIFSIGNALED(rval)) { char msg[30]; sprintf(msg, "process killed by signal %d", WTERMSIG(rval)); val_throw(alloc_string(msg)); } else { neko_error(); } } return alloc_int(WEXITSTATUS(rval)); # endif }
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; }
value wx_scrolled_window_set_scrollbars(value *args, int nargs) { if (nargs < 8) val_throw(alloc_string("Too few arguments")); wxScrolledWindow *window; if (!ValueToWX(args[0], window)) val_throw(alloc_string("Invalid Window")); int ppuX = Val2Int(args[1]); int ppuY = Val2Int(args[2]); int nuX = Val2Int(args[3]); int nuY = Val2Int(args[4]); int xPos = Val2Int(args[5]); int yPos = Val2Int(args[6]); bool noRefresh = Val2Bool(args[7]); window->SetScrollbars(ppuX, ppuY, nuX, nuY, xPos, yPos, noRefresh); return alloc_null(); }
static int do_exec( pcredata *d, const char *str, int len, int pos ) { int res = pcre_exec(d->r,&limit,str,len,pos,0,d->matchs,d->nmatchs * 3); if( res >= 0 ) return 1; if( res != PCRE_ERROR_NOMATCH ) val_throw(alloc_string("An error occured while running pcre_exec")); return 0; }
value wx_scrolled_window_set_scroll_rate(value inWindow, value stepX, value stepY) { wxScrolledWindow *window; if (!ValueToWX(inWindow, window)) val_throw(alloc_string("Invalid Window")); window->SetScrollRate(Val2Int(stepX), Val2Int(stepY)); return alloc_null(); }
value hx_zmq_setbytessockopt(value socket_handle_, value option_, value bytes_optval_) { val_check_kind(socket_handle_, k_zmq_socket_handle); if (!val_is_int(option_)) { printf("option_ is not int"); val_throw(alloc_int(EINVAL)); return alloc_null(); } size_t size = 0; uint8_t *data = 0; // If data from neko if (val_is_string(bytes_optval_)) { size = val_strlen(bytes_optval_); data = (uint8_t *)val_string(bytes_optval_); } // else from C++ else if (val_is_buffer(bytes_optval_)) { buffer buf = val_to_buffer(bytes_optval_); size = buffer_size(buf); data = (uint8_t *)buffer_data(buf); } else { printf("bytes_optval_ not string or buffer"); val_throw(alloc_int(EINVAL)); return alloc_null(); } int rc = 0; int err = 0; int option = val_int(option_); rc = zmq_setsockopt (val_data(socket_handle_), option, data, size); err = zmq_errno(); if (rc != 0) { printf("err:%d",err); val_throw(alloc_int(err)); return alloc_null(); } return alloc_int(rc); }
static void file_error( const char *msg, fio *f, bool delete_f = false ) { gc_exit_blocking(); value a = alloc_array(2); val_array_set_i(a,0,alloc_string(msg)); val_array_set_i(a,1,alloc_filename(f->name.c_str())); if (delete_f) delete f; val_throw(a); }
value hx_zmq_bind(value socket_handle, value addr) { val_check_kind(socket_handle, k_zmq_socket_handle); if (!val_is_string(addr)) { val_throw(alloc_int(EINVAL)); return alloc_null(); } int rc = zmq_bind(val_data(socket_handle),val_string(addr)); int err = zmq_errno(); if (rc != 0) { val_throw(alloc_int(err)); return alloc_null(); } return alloc_int(rc); }
// Finalizer for context void finalize_context( value v) { gc_enter_blocking(); int ret = zmq_term( val_data(v)); gc_exit_blocking(); if (ret != 0) { int err = zmq_errno(); val_throw(alloc_int(err)); } }
value ftLoadFont( value _data, value _width, value _height ) { val_check(_data,string); val_check(_width,number); val_check(_height,number); int width = val_number(_width); int height = val_number(_height); value font = alloc_object(NULL); FT_Face *face = (FT_Face*)malloc( sizeof(FT_Face) ); if( !face ) val_throw( alloc_string("out of memory") ); int err = FT_New_Memory_Face( ft_library, (const FT_Byte*)val_string(_data), val_strlen(_data), 0, face ); if( err == FT_Err_Unknown_File_Format ) val_throw( alloc_string("Freetype cant read font (unknown format)")); else if( err ) val_throw( alloc_string("Freetype cant read font")); FT_Set_Char_Size( *face, width, height, 72, 72 ); int n_glyphs = (*face)->num_glyphs; // set some global metrics/info alloc_field( font, val_id("family_name"), alloc_string((*face)->family_name) ); alloc_field( font, val_id("style_name"), alloc_string((*face)->style_name) ); alloc_field( font, val_id("ascender"), alloc_int((*face)->ascender) ); alloc_field( font, val_id("descender"), alloc_int((*face)->descender) ); alloc_field( font, val_id("units_per_EM"), alloc_int((*face)->units_per_EM) ); alloc_field( font, val_id("height"), alloc_int((*face)->height) ); alloc_field( font, val_id("max_advance_width"), alloc_int((*face)->max_advance_width) ); alloc_field( font, val_id("max_advance_height"), alloc_int((*face)->max_advance_height) ); alloc_field( font, val_id("underline_position"), alloc_int((*face)->underline_position) ); alloc_field( font, val_id("underline_thickness"), alloc_int((*face)->underline_thickness) ); value __f = alloc_abstract( k_ft_face, face ); val_gc( __f, _font_finalize ); alloc_field( font, val_id("__f"), __f ); //fprintf(stderr,"Load Font %p\n", face ); return font; }
static value ssl_get_verify_result( value ssl ){ int r; val_check_kind(ssl,k_ssl); r = mbedtls_ssl_get_verify_result( val_ssl(ssl) ); if( r == 0 ) return val_true; else if( r != -1 ) return val_false; val_throw(alloc_string("not available")); return val_false; }
static void zlib_error( z_stream *z, int err ) { buffer b = alloc_buffer("ZLib Error : "); if( z && z->msg ) { buffer_append(b,z->msg); buffer_append(b," ("); } val_buffer(b,alloc_int(err)); if( z && z->msg ) buffer_append_char(b,')'); val_throw(buffer_to_string(b)); }
static void finalize_result( result *r, int exc ) { r->first = 0; r->done = 1; if( r->ncols == 0 ) r->count = sqlite3_changes(r->db->db); if( sqlite3_finalize(r->r) != SQLITE_OK && exc ) val_throw(alloc_string("Could not finalize request")); r->r = NULL; r->db->last = NULL; r->db = NULL; }
// ---------------- Browser tools --------------------------------------- static value browser_launch( value url ) { #ifndef HX_LINUX int r; val_check(url, string); r=systools_browser_launch(val_string(url)); return alloc_bool(r); #else val_throw(alloc_string("this function is not available for this platform")); return val_null; #endif }