PrimitiveTypeMapCache() { // if we create the TypeMap as a static function member, the constructor // is guarantueed to be called by only one thread (see C++11 standard sec 6.7) // while all other threads wait for completion. Thus no manual synchronization // is needed for the initialization. // create all type mappers /* convert primitive types */ #define CONVERT_NUMBER(NAME, TYPE, PRED, CONV) \ { \ func_t f = [](const Local<Value>& val) \ -> std::tuple<size_t, void*, cl_int> { \ if (!val->PRED()){ \ return std::tuple<size_t, void*,cl_int>(0, NULL, CL_INVALID_ARG_VALUE);\ } \ void* ptr_data = new TYPE; \ size_t ptr_size = sizeof(TYPE); \ *((TYPE *)ptr_data) = val->CONV(); \ return std::tuple<size_t, void*,cl_int>(ptr_size, ptr_data, 0); \ }; \ m_converters[NAME] = f; \ } CONVERT_NUMBER("char", cl_char, IsInt32, ToInt32()->Value); CONVERT_NUMBER("uchar", cl_uchar, IsInt32, ToUint32()->Value); CONVERT_NUMBER("short", cl_short, IsInt32, ToInt32()->Value); CONVERT_NUMBER("ushort", cl_ushort, IsInt32, ToUint32()->Value); CONVERT_NUMBER("int", cl_int , IsInt32, ToInt32()->Value); CONVERT_NUMBER("uint", cl_uint, IsInt32, ToUint32()->Value); CONVERT_NUMBER("long", cl_long, IsNumber, ToInteger()->Value); CONVERT_NUMBER("ulong", cl_ulong, IsNumber, ToInteger()->Value); CONVERT_NUMBER("float", cl_float, IsNumber, NumberValue); CONVERT_NUMBER("double", cl_double, IsNumber, NumberValue); CONVERT_NUMBER("half", cl_half, IsNumber, NumberValue); #undef CONVERT_NUMBER /* convert vector types (e.g. float4, int16, etc) */ #define CONVERT_VECT(NAME, TYPE, I, PRED, COND) \ { \ func_t f = [](const Local<Value>& val) \ -> std::tuple<size_t, void*, cl_int> { \ if (!val->IsArray()) { \ /*THROW_ERR(CL_INVALID_ARG_VALUE); */ \ return std::tuple<size_t,void*,cl_int>(0, NULL, CL_INVALID_ARG_VALUE);\ } \ Local<Array> arr = Local<Array>::Cast(val); \ if (arr->Length() != I) { \ /*THROW_ERR(CL_INVALID_ARG_SIZE);*/ \ return std::tuple<size_t,void*,cl_int>(0, NULL, CL_INVALID_ARG_SIZE); \ } \ TYPE * vvc = new TYPE[I]; \ size_t ptr_size = sizeof(TYPE) * I; \ void* ptr_data = vvc; \ for (unsigned int i = 0; i < I; ++ i) { \ if (!arr->Get(i)->PRED()) { \ /*THROW_ERR(CL_INVALID_ARG_VALUE);*/ \ /*THROW_ERR(CL_INVALID_ARG_VALUE);*/ \ return std::tuple<size_t,void*,cl_int>(0, NULL, CL_INVALID_ARG_VALUE);\ } \ vvc[i] = arr->Get(i)->COND(); \ } \ return std::tuple<size_t,void*,cl_int>(ptr_size, ptr_data, 0); \ }; \ m_converters["NAME ## I"] = f; \ } #define CONVERT_VECTS(NAME, TYPE, PRED, COND) \ CONVERT_VECT(NAME, TYPE, 2, PRED, COND);\ CONVERT_VECT(NAME, TYPE, 3, PRED, COND);\ CONVERT_VECT(NAME, TYPE, 4, PRED, COND);\ CONVERT_VECT(NAME, TYPE, 8, PRED, COND);\ CONVERT_VECT(MAME, TYPE, 16, PRED, COND); CONVERT_VECTS("char", cl_char, IsInt32, ToInt32()->Value); CONVERT_VECTS("uchar", cl_uchar, IsInt32, ToUint32()->Value); CONVERT_VECTS("short", cl_short, IsInt32, ToInt32()->Value); CONVERT_VECTS("ushort", cl_ushort, IsInt32, ToUint32()->Value); CONVERT_VECTS("int", cl_int, IsInt32, ToInt32()->Value); CONVERT_VECTS("uint", cl_uint, IsInt32, ToUint32()->Value); CONVERT_VECTS("long", cl_long, IsNumber, ToInteger()->Value); CONVERT_VECTS("ulong", cl_ulong, IsNumber, ToInteger()->Value); CONVERT_VECTS("float", cl_float, IsNumber, NumberValue); CONVERT_VECTS("double", cl_double, IsNumber, NumberValue); CONVERT_VECTS("half", cl_half, IsNumber, NumberValue); #undef CONVERT_VECT #undef CONVERT_VECTS // add boolean conversion m_converters["bool"] = [](const Local<Value>& val) { size_t ptr_size = sizeof(cl_bool); void* ptr_data = new cl_bool; *((cl_bool *)ptr_data) = val->BooleanValue() ? 1 : 0; return std::tuple<size_t,void*,cl_int>(ptr_size, ptr_data, 0); }; }
static int parse_item(lua_State* L, const char** p_format, va_list* p_va, int value_index, BOOL in_tablep, BOOL* p_optionalp) { const char* format = *p_format; L_RETRY: format = STRSKIP(format, WHITESPACES); switch (*format) { default: lua_pushfstring(L, "format item `%c(%d)' is not valid", SANITIZE_CHAR(*format), *format); return FAILURE; case 'n': CONVERT_NUMBER(L, *p_va, value_index, lua_Number); break; case 'b': CONVERT_NUMBER(L, *p_va, value_index, char); break; case 'h': CONVERT_NUMBER(L, *p_va, value_index, short); break; case 'i': CONVERT_NUMBER(L, *p_va, value_index, int); break; case 'l': CONVERT_NUMBER(L, *p_va, value_index, long); break; case 'B': CONVERT_NUMBER(L, *p_va, value_index, unsigned char); break; case 'H': CONVERT_NUMBER(L, *p_va, value_index, unsigned short); break; case 'I': CONVERT_NUMBER(L, *p_va, value_index, unsigned int); break; case 'L': CONVERT_NUMBER(L, *p_va, value_index, unsigned long); break; case 's': CHECK_TYPE(L, value_index, LUA_TSTRING); /* FALLTHRU */ case 'z': { const char** string; size_t* length = NULL; string = va_arg(*p_va, const char**); if (*(format+1) == '#') { length = va_arg(*p_va, size_t*); format++; } if (lua_isstring(L, value_index)) { *string = lua_tolstring(L, value_index, length); } else if (!lua_toboolean(L, value_index)) { /*nil-or-false?*/ *string = NULL; if (length != NULL) *length = 0; } else { lua_pushfstring(L, "type mismatch (expected %s/nil/false, but got %s)", lua_typename(L, LUA_TSTRING), luaL_typename(L, value_index)); return FAILURE; } } break; case 'Q': { BOOL* p_boolean; p_boolean = va_arg(*p_va, BOOL*); *p_boolean = lua_toboolean(L, value_index); } break; case 'u': /* FALLTHRU */ case 'U': { void** userdata; CHECK_TYPE(L, value_index, ((*format == 'U') ? LUA_TUSERDATA : LUA_TLIGHTUSERDATA)); userdata = va_arg(*p_va, void**); *userdata = lua_touserdata(L, value_index); } break; case 'O': { int* index; if (in_tablep) { lua_pushstring(L, "format item `O' is not available in `{...}"); return FAILURE; } if (*(format+1) == '/') { int type; switch (*(format+2)) { default: lua_pushfstring(L, "type `%c(%d)' for `O/<type>' is not valid", SANITIZE_CHAR(*(format+2)), *(format+2)); return FAILURE; case 'N': type = LUA_TNIL; break; case 'n': type = LUA_TNUMBER; break; case 's': type = LUA_TSTRING; break; case 'f': type = LUA_TFUNCTION; break; case 'Q': type = LUA_TBOOLEAN; break; case 'u': type = LUA_TLIGHTUSERDATA; break; case 'U': type = LUA_TUSERDATA; break; case 't': type = LUA_TTABLE; break; case 'T': type = LUA_TTHREAD; break; } CHECK_TYPE(L, value_index, type); format += 2; } index = va_arg(*p_va, int*); *index = value_index; } break; case '{': CHECK_TYPE(L, value_index, LUA_TTABLE); format++; if (parse_table(L, &format, p_va, value_index) != SUCCESS) return FAILURE; break; case '|': if (in_tablep) { lua_pushstring(L, "optional argument `|' is not available in `{...}"); return FAILURE; } *p_optionalp = TRUE; format++; goto L_RETRY; }