void test_map_push() { { std::map<std::string, std::string> my_map{ {"a", "1"}, {"b", "2"}, {"c", "3"}}; lua_raii L; primer::push(L, my_map); CHECK_STACK(L, 1); test_top_type(L, LUA_TTABLE, __LINE__); lua_pushnil(L); int counter = 0; while (lua_next(L, 1)) { ++counter; TEST(lua_isstring(L, 2), "expected a string key"); std::string key = lua_tostring(L, 2); TEST(lua_isstring(L, 3), "expected a string val"); std::string val = lua_tostring(L, 3); TEST_EQ(val, my_map[key]); my_map.erase(key); lua_pop(L, 1); } TEST_EQ(my_map.size(), 0); TEST_EQ(counter, 3); } { std::map<int, int> my_map{{'a', 1}, {'b', 2}, {'c', 3}}; lua_raii L; primer::push(L, my_map); CHECK_STACK(L, 1); test_top_type(L, LUA_TTABLE, __LINE__); lua_pushnil(L); int counter = 0; while (lua_next(L, 1)) { ++counter; TEST(lua_isinteger(L, 2), "expected an int key"); int key = lua_tointeger(L, 2); TEST(lua_isinteger(L, 3), "expected an int val"); int val = lua_tointeger(L, 3); TEST_EQ(val, my_map[key]); my_map.erase(key); lua_pop(L, 1); } TEST_EQ(my_map.size(), 0); TEST_EQ(counter, 3); } }
void CScriptTable::CloneTable_r( int srcTable,int trgTable ) { CHECK_STACK(L); int top = lua_gettop(L); lua_pushnil(L); // first key while (lua_next(L, srcTable) != 0) { if (lua_type(L,-1) == LUA_TTABLE) { int srct = lua_gettop(L); lua_pushvalue(L, -2); // Push again index. lua_newtable(L); // Make value. int trgt = lua_gettop(L); CloneTable_r( srct,trgt ); lua_rawset(L, trgTable); // Set new table to trgtable. } else { // `key' is at index -2 and `value' at index -1 lua_pushvalue(L, -2); // Push again index. lua_pushvalue(L, -2); // Push value. lua_rawset(L, trgTable); } lua_pop(L, 1); // pop value, leave index. } lua_settop(L, top); // Restore stack. }
bool CScriptTable::Clone( IScriptTable *pSrcTable,bool bDeepCopy, bool bCopyByReference ) { CHECK_STACK(L); int top = lua_gettop(L); PushRef(pSrcTable); PushRef(); int srcTable = top + 1; int trgTable = top + 2; if (bDeepCopy) { if ( bCopyByReference ) { ReferenceTable_r( srcTable,trgTable ); } else { CloneTable_r( srcTable,trgTable ); } } else { CloneTable( srcTable,trgTable ); } lua_settop(L, top); // Restore stack. return true; }
void ActorStackPool_::clearThread() { while (true) { { boost::unique_lock<boost::mutex> ul(_clearMutex); if (_exit) { break; } _clearWait = true; if (_clearVar.timed_wait(ul, boost::posix_time::seconds(STACK_MIN_CLEAR_CYCLE))) { break; } _clearWait = false; } size_t freeCount; goto _checkFree; do { { boost::unique_lock<boost::mutex> ul(_clearMutex); if (_exit) { break; } _clearWait = true; if (_clearVar.timed_wait(ul, boost::posix_time::millisec(100))) { break; } _clearWait = false; } _checkFree:; freeCount = 0; int extTick = get_tick_s(); for (int i = 0; i < 256; i++) { _stackPool[i]._mutex.lock(); if (!_stackPool[i]._pool.empty() && extTick - _stackPool[i]._pool.front()._tick >= STACK_MIN_CLEAR_CYCLE) { StackPck_ pck = _stackPool[i]._pool.front(); _stackPool[i]._pool.pop_front(); _stackPool[i]._mutex.unlock(); CHECK_STACK(pck); free(((char*)pck._stack.sp) - pck._stack.size); _stackCount--; _stackTotalSize -= pck._stack.size; freeCount++; } else { _stackPool[i]._mutex.unlock(); } } } while (freeCount); } }
ActorStackPool_::~ActorStackPool_() { { boost::lock_guard<boost::mutex> lg(_clearMutex); _exit = true; if (_clearWait) { _clearWait = false; _clearVar.notify_one(); } } _clearThread.join(); int ic = 0; vector<void*> tempPool; tempPool.resize(_stackCount); for (int i = 0; i < 256; i++) { boost::lock_guard<boost::mutex> lg1(_stackPool[i]._mutex); while (!_stackPool[i]._pool.empty()) { StackPck_ pck = _stackPool[i]._pool.back(); _stackPool[i]._pool.pop_back(); tempPool[ic++] = ((char*)pck._stack.sp) - pck._stack.size; CHECK_STACK(pck); _stackCount--; } } assert(0 == _stackCount); sort(tempPool.begin(), tempPool.end()); for (int j = 0; j < (int)tempPool.size(); j++) { free(tempPool[j]); } }
StackPck_ ActorStackPool_::getStack( size_t size ) { assert(size && size % 4096 == 0 && size <= 1024*1024); { stack_pool_pck& pool = _actorStackPool->_stackPool[size/4096-1]; pool._mutex.lock(); if (!pool._pool.empty()) { StackPck_ r = pool._pool.back(); pool._pool.pop_back(); pool._mutex.unlock(); r._tick = 0; CHECK_STACK(r); return r; } pool._mutex.unlock(); } _actorStackPool->_stackCount++; _actorStackPool->_stackTotalSize += size; StackPck_ r; r._tick = 0; r._stack.size = size; r._stack.sp = ((char*)malloc(size))+size; if (r._stack.sp) { return r; } throw std::shared_ptr<string>(new string("Actor栈内存不足")); }
*/ REBINT Cmp_Block(REBVAL *sval, REBVAL *tval, REBFLG is_case) /* ** Compare two blocks and return the difference of the first ** non-matching value. ** ***********************************************************************/ { REBVAL *s = VAL_BLK_DATA(sval); REBVAL *t = VAL_BLK_DATA(tval); REBINT diff; CHECK_STACK(&s); if ((VAL_SERIES(sval)==VAL_SERIES(tval))&& (VAL_INDEX(sval)==VAL_INDEX(tval))) return 0; while (!IS_END(s) && (VAL_TYPE(s) == VAL_TYPE(t) || (IS_NUMBER(s) && IS_NUMBER(t)))) { if ((diff = Cmp_Value(s, t, is_case)) != 0) return diff; s++, t++; } return VAL_TYPE(s) - VAL_TYPE(t); }
void CScriptTable::ReferenceTable_r( int srcTable,int trgTable ) { CHECK_STACK(L); int top = lua_gettop(L); lua_newtable(L); // push new meta table lua_pushlstring(L, "__index", strlen("__index")); // push __index lua_pushvalue(L, srcTable); // push src table lua_rawset(L, -3); // meta.__index==src table lua_setmetatable(L,trgTable); // set meta table lua_pushnil(L); // first key while (lua_next(L, srcTable) != 0) { if (lua_type(L,-1) == LUA_TTABLE) { int srct = lua_gettop(L); lua_pushvalue(L, -2); // Push again index. lua_newtable(L); // Make value. int trgt = lua_gettop(L); ReferenceTable_r( srct,trgt ); lua_rawset(L, trgTable); // Set new table to trgtable. } lua_pop(L, 1); // pop value, leave index. } lua_settop(L, top); // Restore stack. }
void test_userdata() { lua_raii L; // Install base library luaL_requiref(L, "", luaopen_base, 1); lua_pop(L, 1); // remove lib CHECK_STACK(L, 0); const char * const script = "" "obj = ... \n" "assert(1 == obj('asdf')) \n" "assert(2 == obj('jkl;')) \n" "assert(3 == obj('awad')) \n" "assert(4 == obj('waka')) \n" "local d = obj:dump() \n" "assert(4 == #d) \n" "assert('asdf' == d[1]) \n" "assert('jkl;' == d[2]) \n" "assert('awad' == d[3]) \n" "assert('waka' == d[4]) \n"; primer::push_udata<userdata_test>(L); TEST_EXPECTED(try_load_script(L, script)); lua_pushvalue(L, 1); CHECK_STACK(L, 3); auto result = primer::fcn_call_no_ret(L, 1); TEST_EXPECTED(result); CHECK_STACK(L, 1); TEST(primer::test_udata<userdata_test>(L, 1), "did not recover userdata from stack"); auto ref = primer::read<userdata_test &>(L, 1); TEST_EXPECTED(ref); TEST_EQ(ref->list.size(), 4); TEST_EQ(ref->list[0], "asdf"); TEST_EQ(ref->list[1], "jkl;"); TEST_EQ(ref->list[2], "awad"); TEST_EQ(ref->list[3], "waka"); }
void CScriptTable::SetAtAny( int nIndex,const ScriptAnyValue &any ) { CHECK_STACK(L); PushRef(); m_pSS->PushAny(any); lua_rawseti(L,-2,nIndex); lua_pop(L, 1); // Pop table. }
void DuktapeContext::set(JNIEnv *env, jstring name, jobject object, jobjectArray methods) { CHECK_STACK(m_context); duk_push_global_object(m_context); const JString instanceName(env, name); if (duk_has_prop_string(m_context, -1, instanceName)) { duk_pop(m_context); queueIllegalArgumentException(env, "A global object called " + instanceName.str() + " already exists"); return; } const duk_idx_t objIndex = duk_require_normalize_index(m_context, duk_push_object(m_context)); // Hook up a finalizer to decrement the refcount and clean up our JavaMethods. duk_push_c_function(m_context, javaObjectFinalizer, 1); duk_set_finalizer(m_context, objIndex); const jsize numMethods = env->GetArrayLength(methods); for (jsize i = 0; i < numMethods; ++i) { jobject method = env->GetObjectArrayElement(methods, i); const jmethodID getName = env->GetMethodID(env->GetObjectClass(method), "getName", "()Ljava/lang/String;"); const JString methodName(env, static_cast<jstring>(env->CallObjectMethod(method, getName))); std::unique_ptr<JavaMethod> javaMethod; try { javaMethod.reset(new JavaMethod(m_javaValues, env, method)); } catch (const std::invalid_argument& e) { queueIllegalArgumentException(env, "In bound method \"" + instanceName.str() + "." + methodName.str() + "\": " + e.what()); // Pop the object being bound and the duktape global object. duk_pop_2(m_context); return; } // Use VARARGS here to allow us to manually validate that the proper number of arguments are // given in the call. If we specify the actual number of arguments needed, Duktape will try to // be helpful by discarding extra or providing missing arguments. That's not quite what we want. // See http://duktape.org/api.html#duk_push_c_function for details. const duk_idx_t func = duk_push_c_function(m_context, javaMethodHandler, DUK_VARARGS); duk_push_pointer(m_context, javaMethod.release()); duk_put_prop_string(m_context, func, JAVA_METHOD_PROP_NAME); // Add this method to the bound object. duk_put_prop_string(m_context, objIndex, methodName); } // Keep a reference in JavaScript to the object being bound. duk_push_pointer(m_context, env->NewGlobalRef(object)); duk_put_prop_string(m_context, objIndex, JAVA_THIS_PROP_NAME); // Make our bound Java object a property of the Duktape global object (so it's a JS global). duk_put_prop_string(m_context, -2, instanceName); // Pop the Duktape global object off the stack. duk_pop(m_context); }
int CScriptTable::Count() { CHECK_STACK(L); PushRef(); int count = luaL_getn(L,-1); lua_pop(L, 1); return count; }
void CScriptTable::SetValueAny( const char *sKey,const ScriptAnyValue &any,bool bChain ) { CHECK_STACK(L); int top = lua_gettop(L); ScriptAnyValue oldValue; if ( lua_getmetatable( L, -1 ) ) // if there is no metatable nothing is pushed { lua_pop( L, 1 ); // pop the metatable - we only care that it exists, not about the value if ( GetValueAny( sKey, oldValue, bChain) && oldValue == any ) return; } if (!bChain) PushRef(); assert(sKey); size_t len = strlen(sKey); if (any.type == ANY_TVECTOR) { // Check if we can reuse Vec3 value already in the table. lua_pushlstring(L, sKey, len); lua_gettable(L,-2); int luatype = lua_type(L,-1); if (luatype == LUA_TTABLE) { lua_pushlstring(L,"x", 1); lua_gettable(L,-2); bool bXIsNumber = lua_isnumber(L,-1) != 0; lua_pop(L,1); // pop x value. if (bXIsNumber) { // Assume its a vector, just fill it with new vector values. lua_pushlstring(L,"x", 1); lua_pushnumber(L, any.vec3.x); lua_settable(L,-3); lua_pushlstring(L,"y", 1); lua_pushnumber(L, any.vec3.y); lua_settable(L,-3); lua_pushlstring(L,"z", 1); lua_pushnumber(L, any.vec3.z); lua_settable(L,-3); lua_settop(L,top); return; } } lua_pop(L,1); // pop key value. } lua_pushlstring(L, sKey, len); m_pSS->PushAny(any); lua_settable(L, -3); lua_settop(L,top); }
void test_std_function() { lua_raii L; //[ primer_example_std_function std::function<primer::result(lua_State * L, int x, int y)> f = [](lua_State * L, int x, int y) -> primer::result { if (y == x) { return primer::error{"bad input"}; } lua_pushinteger(L, x - y); return 1; }; primer::push_std_function(L, std::move(f)); //] CHECK_STACK(L, 1); { lua_pushvalue(L, 1); lua_pushinteger(L, 3); lua_pushinteger(L, 2); auto result = primer::fcn_call_one_ret(L, 2); CHECK_STACK(L, 1); TEST_EXPECTED(result); auto maybe_int = result->as<int>(); CHECK_STACK(L, 1); TEST_EXPECTED(maybe_int); TEST_EQ(*maybe_int, 1); } { lua_pushvalue(L, 1); lua_pushinteger(L, 4); lua_pushinteger(L, 4); auto result = primer::fcn_call_one_ret(L, 2); CHECK_STACK(L, 1); TEST(!result, "expected failure"); } }
bool CScriptTable::GetAtAny( int nIndex,ScriptAnyValue &any ) { CHECK_STACK(L); bool res = false; PushRef(); lua_rawgeti(L,-1,nIndex); res = m_pSS->PopAny(any); lua_pop(L, 1); // Pop table. return res; }
void CScriptTable::SetMetatable( IScriptTable *pMetatable ) { CHECK_STACK(L); ////////////////////////////////////////////////////////////////////////// // Set metatable for this script object. ////////////////////////////////////////////////////////////////////////// PushRef(); // -2 PushRef(pMetatable); // -1 lua_setmetatable(L,-2); lua_pop(L,1); // pop table }
void kthread_start(void (*func)(void*), void* arg) { extern long _etext, _stext; CHECK_STACK(); if ( ((unsigned long)func > (unsigned long)&_etext) || ((unsigned long)func < (unsigned long)&_stext) ) { panic("XXX: bad kthread addr: %p\n", func); } func(arg); }
bool CScriptTable::GetValueAny( const char *sKey,ScriptAnyValue &any,bool bChain ) { CHECK_STACK(L); int top = lua_gettop(L); if (!bChain) PushRef(); bool res = false; lua_pushstring(L, sKey); lua_gettable(L, -2); res = m_pSS->PopAny(any); lua_settop(L,top); return res; }
void test_userdata_two() { lua_raii L; // Install base library luaL_requiref(L, "", luaopen_base, 1); lua_pop(L, 1); // remove lib // Install vec2 ctor lua_pushcfunction(L, PRIMER_ADAPT(&vec2_ctor)); lua_setglobal(L, "vec2"); CHECK_STACK(L, 0); const char * const script = "" "local v1 = vec2(1, 1) \n" "_ = v1 + vec2(3, 4) \n" "local x,y = v1:dump() \n" "assert(x == 4) \n" "assert(y == 5) \n" "assert(v1:norm() == 41) \n" "_ = v1 + - vec2(3, 4) \n" "assert(v1:norm() == 2) \n" "_ = v1 - vec2(3, 3) \n" "assert(v1:norm() == 8) \n" "assert(v1 < vec2(5, 5)) \n"; TEST_EXPECTED(try_load_script(L, script)); CHECK_STACK(L, 1); auto result = primer::fcn_call_no_ret(L, 0); TEST_EXPECTED(result); CHECK_STACK(L, 0); }
void CScriptTable::Delegate( IScriptTable *pMetatable ) { if (!pMetatable) return; CHECK_STACK(L); PushRef(pMetatable); lua_pushstring(L,"__index"); // push key. PushRef(pMetatable); lua_rawset(L,-3); // sets metatable.__index = metatable lua_pop(L,1); // pop metatable from stack. SetMetatable( pMetatable ); }
void CScriptTable::CloneTable( int srcTable,int trgTable ) { CHECK_STACK(L); int top = lua_gettop(L); lua_pushnil(L); // first key while (lua_next(L, srcTable) != 0) { // `key' is at index -2 and `value' at index -1 lua_pushvalue(L, -2); // Push again index. lua_pushvalue(L, -2); // Push value. lua_rawset(L, trgTable); lua_pop(L, 1); // pop value, leave index. } lua_settop(L, top); // Restore stack. }
bool CScriptTable::AddFunction( const SUserFunctionDesc &fd ) { CHECK_STACK(L); assert( fd.pFunctor || fd.pUserDataFunc != 0 ); // Make function signature. char sFuncSignature[256]; if (fd.sGlobalName[0] != 0) sprintf( sFuncSignature,"%s.%s(%s)",fd.sGlobalName,fd.sFunctionName,fd.sFunctionParams ); else sprintf( sFuncSignature,"%s.%s(%s)",fd.sGlobalName,fd.sFunctionName,fd.sFunctionParams ); PushRef(); lua_pushstring(L, fd.sFunctionName); int8 nParamIdOffset = fd.nParamIdOffset; if (fd.pFunctor) { int nDataSize = sizeof(fd.pFunctor) + strlen(sFuncSignature) + 1 + 1; // Store functor in first upvalue. unsigned char *pBuffer = (unsigned char*)lua_newuserdata(L, nDataSize); memcpy( pBuffer, &fd.pFunctor, sizeof(fd.pFunctor)); memcpy( pBuffer+sizeof(fd.pFunctor), &nParamIdOffset, 1 ); memcpy( pBuffer+sizeof(fd.pFunctor)+1, sFuncSignature, strlen(sFuncSignature)+1 ); lua_pushcclosure( L,StdCFunction,1 ); } else { assert( fd.pDataBuffer != NULL && fd.nDataSize > 0 ); UserDataFunction function = fd.pUserDataFunc; int nSize = fd.nDataSize; int nTotalSize = sizeof(function) + sizeof(int) + nSize + strlen(sFuncSignature) + 1 + 1; // Store functor in first upvalue. unsigned char *pBuffer = (unsigned char*)lua_newuserdata(L, nTotalSize ); memcpy( pBuffer, &function, sizeof(function) ); memcpy( pBuffer+sizeof(function), &nSize, sizeof(nSize) ); memcpy( pBuffer+sizeof(function)+sizeof(nSize), fd.pDataBuffer, nSize ); memcpy( pBuffer+sizeof(function)+sizeof(nSize)+nSize, &nParamIdOffset, 1 ); memcpy( pBuffer+sizeof(function)+sizeof(nSize)+nSize+1, sFuncSignature, strlen(sFuncSignature)+1 ); lua_pushcclosure( L,StdCUserDataFunction,1 ); } lua_rawset(L, -3); lua_pop(L,1); // pop table. return true; }
void CScriptTable::Clear() { CHECK_STACK(L); PushRef(); int trgTable = lua_gettop(L); lua_pushnil(L); // first key while (lua_next(L, trgTable) != 0) { lua_pop(L, 1); // pop value, leave index. lua_pushvalue(L, -1); // Push again index. lua_pushnil(L); lua_rawset(L,trgTable); } assert(lua_istable(L,-1)); lua_pop(L, 1); }
jobject JavaScriptObject::call(JNIEnv* env, jobject method, jobjectArray args) const { CHECK_STACK(m_context); if (m_instance == nullptr) { queueDuktapeException(env, "JavaScript object " + m_name + " has been garbage collected"); return nullptr; } const auto methodIter = m_methods.find(env->FromReflectedMethod(method)); if (methodIter != m_methods.end()) { return methodIter->second(env, m_context, m_instance, args); } // Failed to find the method in our map - should be impossible! const jclass methodClass = env->GetObjectClass(method); const jmethodID getName = env->GetMethodID(methodClass, "getName", "()Ljava/lang/String;"); const JString methodName(env, static_cast<jstring>(env->CallObjectMethod(method, getName))); queueDuktapeException(env, "Could not find method " + m_name + "." + methodName.str()); return nullptr; }
void test_set_push() { lua_raii L; std::set<std::string> s{"a", "k", "q", "j"}; primer::push(L, s); CHECK_STACK(L, 1); test_top_type(L, LUA_TTABLE, __LINE__); lua_getfield(L, 1, "a"); test_top_type(L, LUA_TBOOLEAN, __LINE__); TEST_EQ(true, lua_toboolean(L, 2)); lua_pop(L, 1); lua_getfield(L, 1, "k"); test_top_type(L, LUA_TBOOLEAN, __LINE__); TEST_EQ(true, lua_toboolean(L, 2)); lua_pop(L, 1); lua_getfield(L, 1, "q"); test_top_type(L, LUA_TBOOLEAN, __LINE__); TEST_EQ(true, lua_toboolean(L, 2)); lua_pop(L, 1); lua_getfield(L, 1, "j"); test_top_type(L, LUA_TBOOLEAN, __LINE__); TEST_EQ(true, lua_toboolean(L, 2)); lua_pop(L, 1); lua_getfield(L, 1, "p"); test_top_type(L, LUA_TNIL, __LINE__); lua_pop(L, 1); lua_getfield(L, 1, "b"); test_top_type(L, LUA_TNIL, __LINE__); lua_pop(L, 1); lua_getfield(L, 1, "c"); test_top_type(L, LUA_TNIL, __LINE__); lua_pop(L, 1); }
jobject DuktapeContext::evaluate(JNIEnv* env, jstring code, jstring fname) const { CHECK_STACK(m_context); const JString sourceCode(env, code); const JString fileName(env, fname); if (eval_string_with_filename(m_context, sourceCode, fileName) != DUK_EXEC_SUCCESS) { queueJavaExceptionForDuktapeError(env, m_context); return nullptr; } const int supportedTypeMask = DUK_TYPE_MASK_BOOLEAN | DUK_TYPE_MASK_NUMBER | DUK_TYPE_MASK_STRING; if (duk_check_type_mask(m_context, -1, supportedTypeMask)) { // The result is a supported scalar type - return it. return m_objectType->pop(m_context, env, false).l; } else if (duk_is_array(m_context, -1)) { return m_objectType->popArray(m_context, env, 1, false, false); } else { // The result is an unsupported type, undefined, or null. duk_pop(m_context); return nullptr; } }
ScriptVarType CScriptTable::GetAtType(int nIdx) { CHECK_STACK(L); ScriptVarType svtRetVal=svtNull; PushRef(); if (luaL_getn(L, -1) < nIdx) { lua_pop(L, 1); return svtNull; } lua_rawgeti(L, -1, nIdx); switch (lua_type(L, -1)) { case LUA_TNIL: svtRetVal=svtNull; break; case LUA_TBOOLEAN: svtRetVal=svtBool; break; case LUA_TNUMBER: svtRetVal=svtNumber; break; case LUA_TSTRING: svtRetVal=svtString; break; case LUA_TTABLE: svtRetVal=svtObject; break; case LUA_TFUNCTION: svtRetVal=svtFunction; break; } lua_pop(L, 2); return svtRetVal; }
void test_array_push() { lua_raii L; std::array<int, 4> arr{{5, 6, 7, 8}}; primer::push(L, arr); CHECK_STACK(L, 1); test_top_type(L, LUA_TTABLE, __LINE__); std::size_t n = lua_rawlen(L, -1); TEST_EQ(n, arr.size()); lua_rawgeti(L, 1, 1); TEST(lua_isinteger(L, -1), "not an integer"); TEST_EQ(lua_tointeger(L, -1), 5); lua_pop(L, 1); lua_rawgeti(L, 1, 2); TEST(lua_isinteger(L, -1), "not an integer"); TEST_EQ(lua_tointeger(L, -1), 6); lua_pop(L, 1); lua_rawgeti(L, 1, 3); TEST(lua_isinteger(L, -1), "not an integer"); TEST_EQ(lua_tointeger(L, -1), 7); lua_pop(L, 1); lua_rawgeti(L, 1, 4); TEST(lua_isinteger(L, -1), "not an integer"); TEST_EQ(lua_tointeger(L, -1), 8); lua_pop(L, 1); lua_rawgeti(L, 1, 5); TEST(lua_isnil(L, -1), "expected nil"); lua_pop(L, 1); }
ScriptVarType CScriptTable::GetValueType( const char *sKey ) { CHECK_STACK(L); ScriptVarType type=svtNull; PushRef(); lua_pushstring(L, sKey); lua_gettable(L, -2); int luatype = lua_type(L,-1); switch (luatype) { case LUA_TNIL: type = svtNull; break; case LUA_TBOOLEAN: type = svtBool; break; case LUA_TNUMBER: type = svtNumber; break; case LUA_TSTRING: type = svtString; break; case LUA_TFUNCTION: type = svtFunction; break; case LUA_TLIGHTUSERDATA: type = svtPointer; break; case LUA_TTABLE: type = svtObject; break; } lua_pop(L, 2); // Pop value and table. return type; }
int main(int argc, char **argv) { grpc_test_init(argc, argv); grpc_init(); int errors = 0; // tests with a minimal stack grpc_arg minimal_stack_arg = {.type = GRPC_ARG_INTEGER, .key = GRPC_ARG_MINIMAL_STACK, .value.integer = 1}; grpc_channel_args minimal_stack_args = {.num_args = 1, .args = &minimal_stack_arg}; errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_CLIENT_DIRECT_CHANNEL, "connected", NULL); errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL, "connected", NULL); errors += CHECK_STACK("unknown", &minimal_stack_args, GRPC_SERVER_CHANNEL, "server", "connected", NULL); errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_DIRECT_CHANNEL, "http-client", "connected", NULL); errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_CLIENT_SUBCHANNEL, "http-client", "connected", NULL); errors += CHECK_STACK("chttp2", &minimal_stack_args, GRPC_SERVER_CHANNEL, "server", "http-server", "connected", NULL); errors += CHECK_STACK(NULL, &minimal_stack_args, GRPC_CLIENT_CHANNEL, "client-channel", NULL); // tests with a default stack errors += CHECK_STACK("unknown", NULL, GRPC_CLIENT_DIRECT_CHANNEL, "message_size", "deadline", "connected", NULL); errors += CHECK_STACK("unknown", NULL, GRPC_CLIENT_SUBCHANNEL, "message_size", "connected", NULL); errors += CHECK_STACK("unknown", NULL, GRPC_SERVER_CHANNEL, "server", "message_size", "deadline", "connected", NULL); errors += CHECK_STACK("chttp2", NULL, GRPC_CLIENT_DIRECT_CHANNEL, "message_size", "deadline", "http-client", "compress", "connected", NULL); errors += CHECK_STACK("chttp2", NULL, GRPC_CLIENT_SUBCHANNEL, "message_size", "http-client", "compress", "connected", NULL); errors += CHECK_STACK("chttp2", NULL, GRPC_SERVER_CHANNEL, "server", "message_size", "deadline", "http-server", "compress", "connected", NULL); errors += CHECK_STACK(NULL, NULL, GRPC_CLIENT_CHANNEL, "client-channel", NULL); GPR_ASSERT(errors == 0); grpc_shutdown(); return 0; } /******************************************************************************* * End of tests definitions, start of test infrastructure */ static int check_stack(const char *file, int line, const char *transport_name, grpc_channel_args *init_args, grpc_channel_stack_type channel_stack_type, ...) { // create dummy channel stack grpc_channel_stack_builder *builder = grpc_channel_stack_builder_create(); grpc_transport_vtable fake_transport_vtable = {.name = transport_name}; grpc_transport fake_transport = {.vtable = &fake_transport_vtable}; grpc_channel_stack_builder_set_target(builder, "foo.test.google.fr"); grpc_channel_args *channel_args = grpc_channel_args_copy(init_args); if (transport_name != NULL) { grpc_channel_stack_builder_set_transport(builder, &fake_transport); } { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_stack_builder_set_channel_arguments(&exec_ctx, builder, channel_args); GPR_ASSERT( grpc_channel_init_create_stack(&exec_ctx, builder, channel_stack_type)); grpc_exec_ctx_finish(&exec_ctx); } // build up our expectation list gpr_strvec v; gpr_strvec_init(&v); va_list args; va_start(args, channel_stack_type); for (;;) { char *a = va_arg(args, char *); if (a == NULL) break; if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", ")); gpr_strvec_add(&v, gpr_strdup(a)); } va_end(args); char *expect = gpr_strvec_flatten(&v, NULL); gpr_strvec_destroy(&v); // build up our "got" list gpr_strvec_init(&v); grpc_channel_stack_builder_iterator *it = grpc_channel_stack_builder_create_iterator_at_first(builder); while (grpc_channel_stack_builder_move_next(it)) { const char *name = grpc_channel_stack_builder_iterator_filter_name(it); if (name == NULL) continue; if (v.count != 0) gpr_strvec_add(&v, gpr_strdup(", ")); gpr_strvec_add(&v, gpr_strdup(name)); } char *got = gpr_strvec_flatten(&v, NULL); gpr_strvec_destroy(&v); grpc_channel_stack_builder_iterator_destroy(it); // figure out result, log if there's an error int result = 0; if (0 != strcmp(got, expect)) { gpr_strvec_init(&v); gpr_strvec_add(&v, gpr_strdup("{")); for (size_t i = 0; i < channel_args->num_args; i++) { if (i > 0) gpr_strvec_add(&v, gpr_strdup(", ")); gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].key)); gpr_strvec_add(&v, gpr_strdup("=")); switch (channel_args->args[i].type) { case GRPC_ARG_INTEGER: { char *tmp; gpr_asprintf(&tmp, "%d", channel_args->args[i].value.integer); gpr_strvec_add(&v, tmp); break; } case GRPC_ARG_STRING: gpr_strvec_add(&v, gpr_strdup(channel_args->args[i].value.string)); break; case GRPC_ARG_POINTER: { char *tmp; gpr_asprintf(&tmp, "%p", channel_args->args[i].value.pointer.p); gpr_strvec_add(&v, tmp); break; } } } gpr_strvec_add(&v, gpr_strdup("}")); char *args_str = gpr_strvec_flatten(&v, NULL); gpr_strvec_destroy(&v); gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "**************************************************"); gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "FAILED transport=%s; stack_type=%s; channel_args=%s:", transport_name, grpc_channel_stack_type_string(channel_stack_type), args_str); gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "EXPECTED: %s", expect); gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "GOT: %s", got); result = 1; gpr_free(args_str); } gpr_free(got); gpr_free(expect); { grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT; grpc_channel_stack_builder_destroy(&exec_ctx, builder); grpc_channel_args_destroy(&exec_ctx, channel_args); grpc_exec_ctx_finish(&exec_ctx); } return result; }