/** socket_set_timeout : 'socket -> timout:number? -> void <doc>Set the socket send and recv timeout in seconds to the given value (or null for blocking)</doc> **/ static value socket_set_timeout( value o, value t ) { #ifdef NEKO_WINDOWS int time; val_check_kind(o,k_socket); if( val_is_null(t) ) time = 0; else { val_check(t,number); time = (int)(val_number(t) * 1000); } #else struct timeval time; val_check_kind(o,k_socket); if( val_is_null(t) ) { time.tv_usec = 0; time.tv_sec = 0; } else { val_check(t,number); init_timeval(val_number(t),&time); } #endif if( setsockopt(val_sock(o),SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 ) neko_error(); if( setsockopt(val_sock(o),SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 ) neko_error(); return val_true; }
static value sys_sleep( value f ) { val_check(f,number); gc_enter_blocking(); #if defined(NEKO_WINDOWS) && !defined(KORE_CONSOLE) Sleep((DWORD)(val_number(f) * 1000)); #elif defined(EPPC) || defined(KORE_CONSOLE) //TODO: Implement sys_sleep for EPPC #else { struct timespec t; struct timespec tmp; t.tv_sec = (int)val_number(f); t.tv_nsec = (int)((val_number(f) - t.tv_sec) * 1e9); while( nanosleep(&t,&tmp) == -1 ) { if( errno != EINTR ) { gc_exit_blocking(); return alloc_null(); } t = tmp; } } #endif gc_exit_blocking(); return alloc_bool(true); }
/** socket_set_timeout : 'socket -> timout:number? -> void <doc>Set the socket send and recv timeout in seconds to the given value (or null for blocking)</doc> **/ static value socket_set_timeout( value o, value t ) { SOCKET sock = val_sock(o); #ifdef NEKO_WINDOWS int time; if( val_is_null(t) ) time = 0; else { val_check(t,number); time = (int)(val_number(t) * 1000); } #else struct timeval time; if( val_is_null(t) ) { time.tv_usec = 0; time.tv_sec = 0; } else { val_check(t,number); init_timeval(val_number(t),&time); } #endif gc_enter_blocking(); if( setsockopt(sock,SOL_SOCKET,SO_SNDTIMEO,(char*)&time,sizeof(time)) != 0 ) { gc_exit_blocking(); return alloc_null(); } if( setsockopt(sock,SOL_SOCKET,SO_RCVTIMEO,(char*)&time,sizeof(time)) != 0 ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); return alloc_bool(true); }
static value sys_sleep( value f ) { val_check(f,number); gc_enter_blocking(); #ifdef HX_WINRT if (!tlsSleepEvent) tlsSleepEvent = CreateEventEx(nullptr, nullptr, CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS); WaitForSingleObjectEx(tlsSleepEvent, (int)(val_number(f)*1000), false); #elif defined(NEKO_WINDOWS) Sleep((DWORD)(val_number(f) * 1000)); #elif defined(EPPC) //TODO: Implement sys_sleep for EPPC #else { struct timespec t; struct timespec tmp; t.tv_sec = (int)val_number(f); t.tv_nsec = (int)((val_number(f) - t.tv_sec) * 1e9); while( nanosleep(&t,&tmp) == -1 ) { if( errno != EINTR ) { gc_exit_blocking(); return alloc_null(); } t = tmp; } } #endif gc_exit_blocking(); return alloc_bool(true); }
value lime_image_data_util_flood_fill (value image, value x, value y, value color) { Image _image = Image (image); ImageDataUtil::FloodFill (&_image, val_number (x), val_number (y), val_number (color)); return alloc_null (); }
value lime_image_data_util_flood_fill (value image, value x, value y, value rg, value ba) { Image _image = Image (image); int32_t color = (val_int (rg) << 16) | val_int (ba); ImageDataUtil::FloodFill (&_image, val_number (x), val_number (y), color); return alloc_null (); }
/** socket_poll_events : 'poll -> timeout:float -> void <doc> Update the read/write flags arrays that were created with [socket_poll_prepare]. </doc> **/ static value socket_poll_events( value pdata, value timeout ) { polldata *p; # ifdef NEKO_WINDOWS unsigned int i; int k = 0; struct timeval t; val_check_kind(pdata,k_poll); p = val_poll(pdata); memcpy(p->outr,p->fdr,FDSIZE(p->fdr->fd_count)); memcpy(p->outw,p->fdw,FDSIZE(p->fdw->fd_count)); val_check(timeout,number); init_timeval(val_number(timeout),&t); gc_enter_blocking(); if( p->fdr->fd_count + p->fdw->fd_count != 0 && select(0,p->outr,p->outw,NULL,&t) == SOCKET_ERROR ) { gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); k = 0; for(i=0;i<p->fdr->fd_count;i++) if( FD_ISSET(p->fdr->fd_array[i],p->outr) ) val_array_set_i(p->ridx,k++,alloc_int(i)); val_array_set_i(p->ridx,k,alloc_int(-1)); k = 0; for(i=0;i<p->fdw->fd_count;i++) if( FD_ISSET(p->fdw->fd_array[i],p->outw) ) val_array_set_i(p->widx,k++, alloc_int(i)); val_array_set_i(p->widx,k,alloc_int(-1)); #else int i,k; int tot; val_check_kind(pdata,k_poll); val_check(timeout,number); p = val_poll(pdata); tot = p->rcount + p->wcount; gc_enter_blocking(); POSIX_LABEL(poll_events_again); if( poll(p->fds,tot,(int)(val_number(timeout) * 1000)) < 0 ) { HANDLE_EINTR(poll_events_again); gc_exit_blocking(); return alloc_null(); } gc_exit_blocking(); k = 0; for(i=0;i<p->rcount;i++) if( p->fds[i].revents & (POLLIN|POLLHUP) ) val_array_set_i(p->ridx,k++,alloc_int(i)); val_array_set_i(p->ridx,k, alloc_int(-1)); k = 0; for(;i<tot;i++) if( p->fds[i].revents & (POLLOUT|POLLHUP) ) val_array_set_i(p->widx,k++, alloc_int(i - p->rcount)); val_array_set_i(p->widx,k, alloc_int(-1)); #endif return val_null; }
/** math_pow : number -> number -> float <doc>Return power calculus</doc> **/ static value math_pow( value a, value b ) { tfloat r; val_check(a,number); val_check(b,number); r = (tfloat)pow(val_number(a),val_number(b)); if( (int)r == r && fabs(r) < (1 << 31) ) return alloc_best_int((int)r); return alloc_float(r); }
value ftRenderGlyph( value font, value _index, value _size, value _hint ) { if( !val_is_object(font) ) { ft_failure_v("not a freetype font face: ", font ); } value __f = val_field( font, val_id("__f") ); if( __f == NULL || !val_is_abstract( __f ) || !val_is_kind( __f, k_ft_face ) ) { ft_failure_v("not a freetype font face: ", font ); } FT_Face *face = val_data( __f ); val_check( _size, number ); int size = val_number(_size); FT_Set_Char_Size( *face, size, size, 72, 72 ); val_check( _hint, bool ); int hint = val_bool(_hint); val_check(_index,number); /* int index = FT_Get_Char_Index( *face, (FT_UInt) val_number(_index) ); fprintf( stderr, "char %i is glyph %i\n", (int)val_number(_index), (int)index ); int err = FT_Load_Glyph( *face, index, FT_LOAD_RENDER | FT_LOAD_NO_HINTING ); fprintf( stderr, "Load Glyph idx %i->%i/%i, sz %i, face %p: err 0x%x\n", (int)val_number(_index), index, (int)((*face)->num_glyphs), size>>6, face, err ); */ int err = FT_Load_Char( *face, (FT_ULong)val_number(_index), FT_LOAD_RENDER | (hint?0:FT_LOAD_NO_HINTING) ); if( err ) { fprintf( stderr, "Load_Char failed: %x char index %i\n", err, FT_Get_Char_Index( *face, (FT_UInt) val_number(_index) ) ); val_throw(alloc_string("Could not load requested Glyph")); // return( val_null ); } FT_GlyphSlot glyph = (*face)->glyph; /* err = FT_Render_Glyph( glyph, FT_RENDER_MODE_NORMAL ); if( err || glyph->format != ft_glyph_format_bitmap ) { val_throw(alloc_string("Could not render requested Glyph")); } */ FT_Bitmap bitmap = glyph->bitmap; value ret = alloc_object(NULL); alloc_field( ret, val_id("width"), alloc_int(bitmap.width) ); alloc_field( ret, val_id("height"), alloc_int(bitmap.rows) ); alloc_field( ret, val_id("bitmap"), copy_string( (char*)bitmap.buffer, bitmap.width*bitmap.rows ) ); alloc_field( ret, val_id("x"), alloc_int( glyph->metrics.horiBearingX ) ); alloc_field( ret, val_id("y"), alloc_int( glyph->metrics.horiBearingY ) ); alloc_field( ret, val_id("advance"), alloc_float( glyph->advance.x )); return ret; }
/** lock_wait : 'lock -> timeout:number? -> bool <doc> Waits for a lock to be released and acquire it. If [timeout] (in seconds) is not null and expires then the returned value is false </doc> **/ static value lock_wait( value lock, value timeout ) { int has_timeout = !val_is_null(timeout); val_check_kind(lock,k_lock); if( has_timeout ) val_check(timeout,number); # ifdef NEKO_WINDOWS switch( WaitForSingleObject(val_lock(lock),has_timeout?(DWORD)(val_number(timeout) * 1000.0):INFINITE) ) { case WAIT_ABANDONED: case WAIT_OBJECT_0: return val_true; case WAIT_TIMEOUT: return val_false; default: neko_error(); } # else { vlock l = val_lock(lock); pthread_mutex_lock(&l->lock); while( l->counter == 0 ) { if( has_timeout ) { struct timeval tv; struct timespec t; double delta = val_number(timeout); int idelta = (int)delta, idelta2; delta -= idelta; delta *= 1.0e9; gettimeofday(&tv,NULL); delta += tv.tv_usec * 1000.0; idelta2 = (int)(delta / 1e9); delta -= idelta2 * 1e9; t.tv_sec = tv.tv_sec + idelta + idelta2; t.tv_nsec = (long)delta; if( pthread_cond_timedwait(&l->cond,&l->lock,&t) != 0 ) { pthread_mutex_unlock(&l->lock); return val_false; } } else pthread_cond_wait(&l->cond,&l->lock); } l->counter--; if( l->counter > 0 ) pthread_cond_signal(&l->cond); pthread_mutex_unlock(&l->lock); return val_true; } # endif }
value lime_application_set_frame_rate (value application, value frameRate) { Application* app = (Application*)(intptr_t)val_float (application); app->SetFrameRate (val_number (frameRate)); return alloc_null (); }
/** socket_select : read : 'socket array -> write : 'socket array -> others : 'socket array -> timeout:number? -> 'socket array array <doc>Perform the [select] operation. Timeout is in seconds or [null] if infinite</doc> **/ static value socket_select( value rs, value ws, value es, value timeout ) { struct timeval tval; struct timeval *tt; SOCKET n = 0; fd_set rx, wx, ex; fd_set *ra, *wa, *ea; value r; POSIX_LABEL(select_again); ra = make_socket_array(rs,val_array_size(rs),&rx,&n); wa = make_socket_array(ws,val_array_size(ws),&wx,&n); ea = make_socket_array(es,val_array_size(es),&ex,&n); if( ra == &INVALID || wa == &INVALID || ea == &INVALID ) neko_error(); if( val_is_null(timeout) ) tt = NULL; else { val_check(timeout,number); tt = &tval; init_timeval(val_number(timeout),tt); } if( select((int)(n+1),ra,wa,ea,tt) == SOCKET_ERROR ) { HANDLE_EINTR(select_again); neko_error(); } r = alloc_array(3); val_array_ptr(r)[0] = make_array_result(rs,ra); val_array_ptr(r)[1] = make_array_result(ws,wa); val_array_ptr(r)[2] = make_array_result(es,ea); return r; }
value lime_image_data_util_fill_rect (value image, value rect, value color) { Image _image = Image (image); Rectangle _rect = Rectangle (rect); ImageDataUtil::FillRect (&_image, &_rect, val_number (color)); return alloc_null (); }
double api_val_field_numeric(value arg1,int arg2) { value field = val_field(arg1, arg2); if (val_is_number(field)) return val_number(field); if (val_is_bool(field)) return val_bool(field); return 0; }
/** sys_sleep : number -> void <doc>Sleep a given number of seconds</doc> **/ static value sys_sleep( value f ) { val_check(f,number); #ifdef NEKO_WINDOWS Sleep((DWORD)(val_number(f) * 1000)); #else { struct timespec t; struct timespec tmp; t.tv_sec = (int)val_number(f); t.tv_nsec = (int)((val_number(f) - t.tv_sec) * 1e9); while( nanosleep(&t,&tmp) == -1 ) { if( errno != EINTR ) neko_error(); t = tmp; } } #endif return val_true; }
/** $float : any -> float? <doc>Convert the value to the corresponding float or return [null]</doc> **/ static value builtin_float( value f ) { if( val_is_string(f) ) { char *c = val_string(f), *end; tfloat f = (tfloat)strtod(c,&end); return (c == end) ? val_null : alloc_float(f); } if( val_is_number(f) ) return alloc_float( val_number(f) ); return val_null; }
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; }
value fcFindFont( value _familyName, value _weight, value _slant, value _size ) { val_check(_familyName,string); val_check(_weight,number); val_check(_slant,number); val_check(_size,number); const char *familyName = val_string(_familyName); int weight = val_number(_weight); int slant = val_number(_slant); float size = val_number(_size); FcPattern *pattern; pattern = FcNameParse( (FcChar8*)familyName ); FcDefaultSubstitute( pattern ); FcConfigSubstitute( FcConfigGetCurrent(), pattern, FcMatchPattern ); FcResult result; FcPattern *match = FcFontMatch( 0, pattern, &result ); FcPatternDestroy( pattern ); if( !match ) val_throw(alloc_string("Could not find font")); FcChar8 *temp; int id; pattern = FcPatternDuplicate(match); if( FcPatternGetString( pattern, FC_FILE, 0, &temp ) != FcResultMatch || FcPatternGetInteger( pattern, FC_INDEX, 0, &id ) != FcResultMatch ) { val_throw(alloc_string("Could not load font")); } value ret = alloc_string((const char *)temp); FcPatternDestroy( pattern ); FcPatternDestroy( match ); return ret; }
/** float_bytes : number -> bigendian:bool -> string <doc>Returns the 4 bytes representation of the number as an IEEE 32-bit float</doc> **/ static value float_bytes( value n, value be ) { float f; val_check(n,number); val_check(be,bool); f = (float)val_number(n); if( neko_is_big_endian() != val_bool(be) ) { char *c = (char*)&f; char tmp; tmp = c[0]; c[0] = c[3]; c[3] = tmp; tmp = c[1]; c[1] = c[2]; c[2] = tmp; } return copy_string((char *)&f,4); }
/** Returns the ENetPeer that generated an event, with the Event allocated pointer in Peer->data. The returned ENetPeer must not be destroyed, since it's a copy of an existing peer pointer. Timeout is float number of seconds (0.001 == 1 ms) **/ static value udpr_poll(value h, value timeout) { //ENetPeerHandle hndPeer = enet_host_peer_to_handle(host, event->peer); ENetEvent *event; int res; if( !val_is_abstract(h) || !val_is_kind(h,k_udprhost) ) neko_error(); val_check(timeout,number); enet_uint32 tout = (enet_uint32)(val_number(timeout)*1000); event = (ENetEvent *) enet_malloc (sizeof (ENetEvent)); // Wait up to timeout milliseconds for an event. res = enet_host_service ((ENetHost *)val_data(h), event, tout); if(res <= 0) { if(res == 0) return val_null; neko_error(); } switch (event->type) { case ENET_EVENT_TYPE_NONE: //if(event->peer != NULL) //free_peer_event(event->peer); enet_free(event); return val_null; break; default: // auto frees any existing unhandled event, add this event. #ifdef ENET_DEBUG_FULL if(event->type == ENET_EVENT_TYPE_RECEIVE) fprintf(stderr, "udpr_poll: event type %s %0.*s\n", event_to_string(event->type), event->packet->dataLength, event->packet->data); else fprintf(stderr, "udpr_poll: event type %s\n", event_to_string(event->type)); #endif break; } value v = alloc_abstract(k_udprevent,event); val_gc(v, destroy_enetevent); return v; #ifdef ENET_DEBUG //fprintf(stderr, "udpr_poll: returning peer %x\n", event->peer); #endif //value v = alloc_abstract(k_udprpeer, event->peer); //return v; }
value cptr_copy( value from, value from_i, value to, value to_i, value l ) { val_check( from, string ); val_check( to, string ); val_check( from_i, number ); val_check( to_i, number ); val_check( l, number ); int from_idx = val_number(from_i); int to_idx = val_number(to_i); int length = val_number(l); if( val_strlen( from ) < from_idx+length ) { length = val_strlen(from)-(from_idx); } if( val_strlen( to ) < to_idx+length ) { length = val_strlen(to)-(to_idx); } if( length<=0 ) return val_false; memcpy( &(( char* )val_string(to))[to_idx], &(( char* )val_string(from))[from_idx], length ); return( val_true ); }
/** double_bytes : number -> bigendian:bool -> string <doc>Returns the 8 bytes representation of the number as an IEEE 64-bit float</doc> **/ static value double_bytes( value n, value be ) { double f; val_check(n,number); val_check(be,bool); f = (double)val_number(n); if( neko_is_big_endian() != val_bool(be) ) { char *c = (char*)&f; char tmp; tmp = c[0]; c[0] = c[7]; c[7] = tmp; tmp = c[1]; c[1] = c[6]; c[6] = tmp; tmp = c[2]; c[2] = c[5]; c[5] = tmp; tmp = c[3]; c[3] = c[4]; c[4] = tmp; } return copy_string((char*)&f,8); }
void lime_cairo_set_dash (value handle, value dash) { int length = val_array_size (dash); double* dashPattern = new double[length]; for (int i = 0; i < length; i++) { dashPattern[i] = val_number (val_array_i (dash, i)); } cairo_set_dash ((cairo_t*)val_data (handle), dashPattern, length, 0); delete dashPattern; }
/** socket_select : read : 'socket array -> write : 'socket array -> others : 'socket array -> timeout:number? -> 'socket array array <doc>Perform the [select] operation. Timeout is in seconds or [null] if infinite</doc> **/ static value socket_select( value rs, value ws, value es, value timeout ) { struct timeval tval; struct timeval *tt; SOCKET n = 0; fd_set rx, wx, ex; fd_set *ra, *wa, *ea; value r; POSIX_LABEL(select_again); ra = make_socket_array(rs,&rx,&n); wa = make_socket_array(ws,&wx,&n); ea = make_socket_array(es,&ex,&n); if( ra == &INVALID || wa == &INVALID || ea == &INVALID ) { val_throw( alloc_string("No valid sockets") ); return alloc_null(); } if( val_is_null(timeout) ) tt = NULL; else { val_check(timeout,number); tt = &tval; init_timeval(val_number(timeout),tt); } gc_enter_blocking(); if( select((int)(n+1),ra,wa,ea,tt) == SOCKET_ERROR ) { HANDLE_EINTR(select_again); gc_exit_blocking(); char buf[100]; sprintf(buf,"Select error %d", errno ); val_throw( alloc_string(buf) ); } gc_exit_blocking(); r = alloc_array(3); val_array_set_i(r,0,make_array_result(rs,ra)); val_array_set_i(r,1,make_array_result(ws,wa)); val_array_set_i(r,2,make_array_result(es,ea)); return r; }
value cptr_fill( value cp, value c ) { val_check( c, number ); val_check( cp, string ); memset( (( void* )val_string(cp)), (int)val_number(c), val_strlen(cp) ); return( val_null ); }
/** math_atan2 : number -> number -> float <doc>Return atan2 calculus</doc> **/ static value math_atan2( value a, value b ) { val_check(a,number); val_check(b,number); return alloc_float( atan2(val_number(a),val_number(b)) ); }
double api_val_number(value arg1) { return val_number(arg1); }
/** socket_epoll_wait : 'epoll -> int -> float -> int array <doc>Wait and return a list of socket fds with events.</doc> **/ static value socket_epoll_wait(value e, value timeout) { epolldata *ep; #ifndef HAS_EPOLL struct timeval t; SOCKET n = 0; bool indefinite; fd_set rx, wx; fd_set *ra, *wa; int i; int pos = 0; val_check_kind(e,k_epoll); ep = val_epoll(e); POSIX_LABEL(select_again); ra = ep->rcount == 0 ? NULL : make_socket_array(ep->read, ep->rcount, &rx, &n); wa = ep->wcount == 0 ? NULL : make_socket_array(ep->write, ep->wcount, &wx, &n); indefinite = val_is_null(timeout); if (!indefinite) { val_check(timeout,number); init_timeval(val_number(timeout),&t); } if( select((int)(n+1),ra,wa,NULL,indefinite ? NULL : &t) == SOCKET_ERROR ) { HANDLE_EINTR(select_again); val_throw(alloc_int(errno)); } if (ra != NULL) { for (i=0; i < ep->rcount && pos < ep->maxevents; i++) { value s = val_array_ptr(ep->read)[i]; if (FD_ISSET(val_sock(s),ra)) val_array_ptr(ep->result)[pos++] = alloc_int(val_sock(s)); } } if (wa != NULL) { for (i=0; i < ep->wcount && pos < ep->maxevents; i++) { value s = val_array_ptr(ep->write)[i]; if (FD_ISSET(val_sock(s),wa)) val_array_ptr(ep->result)[pos++] = alloc_int(val_sock(s)); } } val_set_size(ep->result,pos); return ep->result; #else int t; val_check_kind(e,k_epoll); ep = val_epoll(e); if (val_is_null(timeout)) t = -1; else { val_check(timeout,number); t = (int)(val_number(timeout)) * 1000; } int ret = epoll_wait(ep->epollfd, ep->events, ep->maxevents, t); if (ret == -1) val_throw(alloc_int(errno)); val_set_size(ep->result, ret); int i; for (i = 0; i < ret; i++) { val_array_ptr(ep->result)[i] = alloc_int(ep->events[i].data.fd); } return ep->result; #endif }