backup lua-test/devel util code
authorRobin Gareus <robin@gareus.org>
Thu, 7 Jul 2016 13:33:45 +0000 (15:33 +0200)
committerRobin Gareus <robin@gareus.org>
Thu, 7 Jul 2016 13:37:11 +0000 (15:37 +0200)
tools/luadevel/devel.cc

index 3caa0513f3c21e7ec29c881ffdd63e4ece4f4bfc..9bbe31381092d6dca514107181458418e5bbf385 100644 (file)
@@ -19,10 +19,23 @@ static void my_lua_print (std::string s) {
        std::cout << s << "\n";
 }
 
+luabridge::LuaRef::Proxy&
+luabridge::LuaRef::Proxy::clone_instance (const void* classkey, void* p) {
+  lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_tableRef);
+  lua_rawgeti (m_L, LUA_REGISTRYINDEX, m_keyRef);
+
+       luabridge::UserdataPtr::push_raw (m_L, p, classkey);
+
+  lua_rawset (m_L, -3);
+  lua_pop (m_L, 1);
+  return *this;
+}
+
+
 
 class A {
        public:
-               A() { printf ("CTOR\n"); _int = 4; for (int i = 0; i < 256; ++i) {arr[i] = i; ar2[i] = i/256.0; ar3[i] = i;} }
+               A() { printf ("CTOR %p\n", this); _int = 4; for (int i = 0; i < 256; ++i) {arr[i] = i; ar2[i] = i/256.0; ar3[i] = i;} }
                ~A() { printf ("DTOR\n"); }
 
                void set_int (int a) { _int = a; }
@@ -42,6 +55,7 @@ class A {
                std::list<std::string>& get_list () { return _sl; }
 
                uint32_t minone() { return -1; }
+               void pointer (float*f) const { printf ("PTR %p", f); }
 
                enum EN {
                        RV1 = 1, RV2, RV3
@@ -59,11 +73,262 @@ class A {
                int ar3[256];
 };
 
-int main (int argc, char **argv)
+
+class LuaTableRef {
+       public:
+               LuaTableRef () {}
+               ~LuaTableRef () {}
+
+               int get (lua_State* L) {
+                       luabridge::LuaRef rv (luabridge::newTable (L));
+                       for (std::vector<LuaTableEntry>::const_iterator i = _data.begin (); i != _data.end (); ++i) {
+                               switch ((*i).keytype) {
+                                       case LUA_TSTRING:
+                                               assign(&rv, i->k_s, *i);
+                                               break;
+                                       case LUA_TNUMBER:
+                                               assign(&rv, i->k_n, *i);
+                                               break;
+                               }
+                       }
+                       luabridge::push (L, rv);
+                       return 1;
+               }
+
+               int set (lua_State* L) {
+                       if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
+                       _data.clear ();
+
+                       lua_pushvalue (L, -1);
+                       lua_pushnil (L);
+                       while (lua_next (L, -2)) {
+                               lua_pushvalue (L, -2);
+
+                               LuaTableEntry s (lua_type(L, -1), lua_type(L, -2));
+                               switch (lua_type(L, -1)) {
+                                       case LUA_TSTRING:
+                                               s.k_s = luabridge::Stack<std::string>::get (L, -1);
+                                               break;
+                                               ;
+                                       case LUA_TNUMBER:
+                                               s.k_n = luabridge::Stack<unsigned int>::get (L, -1);
+                                               break;
+                                       default:
+                                               // invalid key
+                                               lua_pop (L, 2);
+                                               continue;
+                               }
+
+                               switch(lua_type(L, -2)) {
+                                       case LUA_TSTRING:
+                                               s.s = luabridge::Stack<std::string>::get (L, -2);
+                                               break;
+                                       case LUA_TBOOLEAN:
+                                               s.b = lua_toboolean (L, -2);
+                                               break;
+                                       case LUA_TNUMBER:
+                                               s.n = lua_tonumber (L, -2);
+                                               break;
+                                       case LUA_TUSERDATA:
+                                               {
+                                                       bool ok = false;
+                                                       lua_getmetatable (L, -2);
+                                                       lua_rawgetp (L, -1, luabridge::getIdentityKey ());
+                                                       if (lua_isboolean (L, -1)) {
+                                                               lua_pop (L, 1);
+                                                               const void* key = lua_topointer (L, -1);
+                                                               lua_pop (L, 1);
+                                                               void const* classkey = findclasskey (L, key);
+
+                                                               if (classkey) {
+                                                                       ok = true;
+                                                                       s.c = classkey;
+                                                                       s.p = luabridge::Userdata::get_ptr (L, -2);
+                                                               }
+                                                       }  else {
+                                                               lua_pop (L, 2);
+                                                       }
+
+                                                       if (ok) {
+                                                               break;
+                                                       }
+                                                       // invalid userdata -- fall through
+                                               }
+                                               // no break
+                                       case LUA_TFUNCTION: // no support -- we could... string.format("%q", string.dump(value, true))
+                                       case LUA_TTABLE: // no nested tables, sorry.
+                                       case LUA_TNIL: // fallthrough
+                                       default:
+                                               // invalid value
+                                               lua_pop (L, 2);
+                                               continue;
+                               }
+
+                               _data.push_back(s);
+                               lua_pop (L, 2);
+                       }
+                       return 0;
+               }
+
+               static void* findclasskey (lua_State *L, const void* key)
+               {
+                       lua_pushvalue(L, LUA_REGISTRYINDEX);
+                       lua_pushnil (L);
+                       while (lua_next (L, -2)) {
+                               lua_pushvalue (L, -2);
+                               if (lua_topointer(L, -2) == key) {
+                                       void* rv = lua_touserdata (L, -1);
+                                       lua_pop (L, 4);
+                                       return rv;
+                               }
+                               lua_pop (L, 2);
+                       }
+                       lua_pop (L, 1);
+                       return NULL;
+               }
+
+       private:
+               struct LuaTableEntry {
+                       LuaTableEntry (int kt, int vt)
+                               : keytype (kt)
+                               , valuetype (vt)
+                       { }
+
+                       int keytype;
+                       std::string k_s;
+                       unsigned int k_n;
+
+                       int valuetype;
+                       // LUA_TUSERDATA
+                       const void* c;
+                       void* p;
+                       // LUA_TBOOLEAN
+                       bool b;
+                       // LUA_TSTRING:
+                       std::string s;
+                       // LUA_TNUMBER:
+                       double n;
+               };
+
+               template<typename T>
+               static void assign (luabridge::LuaRef* rv, T key, const LuaTableEntry& s)
+               {
+                       switch (s.valuetype) {
+                               case LUA_TSTRING:
+                                       (*rv)[key] = s.s;
+                                       break;
+                               case LUA_TBOOLEAN:
+                                       (*rv)[key] = s.b;
+                                       break;
+                               case LUA_TNUMBER:
+                                       (*rv)[key] = s.n;
+                                       break;
+                               case LUA_TUSERDATA:
+                                       (*rv)[key].clone_instance (s.c, s.p);
+                                       break;
+                               default:
+                                       assert (0);
+                                       break;
+                       }
+               }
+
+               std::vector<LuaTableEntry> _data;
+};
+
+
+#if 0
+static void* findclasskey (lua_State *L, const void* key)
+{
+       lua_pushvalue(L, LUA_REGISTRYINDEX);
+       lua_pushnil (L);
+       while (lua_next (L, -2)) {
+               lua_pushvalue (L, -2);
+               if (lua_topointer(L, -2) == key) {
+                       void* rv = lua_touserdata (L, -1);
+                       lua_pop (L, 4);
+                       return rv;
+               }
+               lua_pop (L, 2);
+       }
+       lua_pop (L, 1);
+       return NULL;
+}
+
+static int tableSerialize (lua_State *L)
+{
+       if (!lua_istable (L, -1)) { return luaL_error (L, "argument is not a table"); }
+
+       luabridge::LuaRef rv (luabridge::newTable (L));
+       std::cout << "CLASS A KEY: " << luabridge::ClassInfo <A>::getClassKey () << "\n";
+       lua_rawgetp (L, LUA_REGISTRYINDEX, luabridge::ClassInfo <A>::getClassKey ());
+       std::cout << " CLASS A TABLE PTR=" << lua_topointer (L, -1) << "\n";
+       lua_pop (L, 1);
+       // for k,v in pairs (debug.getregistry ()) do print (k,v) end
+
+       lua_pushvalue (L, -1);
+       lua_pushnil (L);
+       while (lua_next (L, -2)) {
+               lua_pushvalue (L, -2);
+               unsigned int const i = luabridge::Stack<unsigned int>::get (L, -1);
+               int t = lua_type(L, -2);
+               switch(t) {
+                       case LUA_TSTRING:
+                               std::cout << "  " << i << ": '" << lua_tostring(L, -2) << "'\n";
+                               rv[i] = lua_tostring(L, -2);
+                               break;
+                       case LUA_TBOOLEAN:
+                               std::cout << "  " << i << ": " <<
+                                       (lua_toboolean(L, -2) ? "true" : "false") << "\n";
+                               rv[i] = lua_toboolean(L, -2);
+                               break;
+                       case LUA_TNUMBER:
+                               std::cout << "  " << i << ": " << lua_tonumber(L, -2) << "\n";
+                               rv[i] = lua_tonumber(L, -2);
+                               break;
+                       case LUA_TUSERDATA:
+                               {
+                                       lua_getmetatable (L, -2);
+                                       lua_rawgetp (L, -1, luabridge::getIdentityKey ());
+                                       if (lua_isboolean (L, -1)) {
+                                               lua_pop (L, 1);
+                                               const void* key = lua_topointer (L, -1);
+                                               lua_pop (L, 1);
+                                               void const* classkey = findclasskey (L, key);
+
+                                               if (classkey) {
+                                                       void* p = luabridge::Userdata::get_ptr (L, -2);
+                                                       rv[i].clone_instance (classkey, p);
+                                               }
+                                       }  else {
+                                               lua_pop (L, 2);
+                                       }
+                               }
+                               break;
+                       case LUA_TNIL:
+                       case LUA_TTABLE:
+                       case LUA_TFUNCTION:
+                       case LUA_TLIGHTUSERDATA:
+                       default:
+                               std::cout << "  " << i << ": TYPE=" << t << ": " << lua_topointer(L, -2)<< "\n";
+                               break;
+               }
+               lua_pop (L, 2);
+       }
+       lua_pop (L, 1);
+       lua_pop (L, 2);
+
+       luabridge::push (L, rv);
+       return 1;
+}
+#endif
+
+LuaTableRef globalref;
+
+int runone (LuaState& lua)
 {
 #if 0
-       LuaState lua;
-#else
+       LuaState lua (*new LuaState);
+#elif 0
        PBD::ReallocPool _mempool ("Devel", 1048576);
        LuaState lua (lua_newstate (&PBD::ReallocPool::lalloc, &_mempool));
 #endif
@@ -122,12 +387,28 @@ int main (int argc, char **argv)
        luabridge::getGlobalNamespace (L)
                .beginNamespace ("Test")
                .beginClass <A> ("A")
+               .addFunction ("pointer", &A::pointer)
                .addFunction ("minone", &A::minone)
                .addConst ("cologne", 4711)
                .endClass ()
                .addConst ("koln", 4711)
                .endNamespace ();
 #endif
+       luabridge::getGlobalNamespace (L)
+               .beginNamespace ("Dump")
+
+               .beginClass <LuaTableRef> ("TableRef")
+               .addCFunction ("get", &LuaTableRef::get)
+               .addCFunction ("set", &LuaTableRef::set)
+               .endClass ()
+
+               //.addCFunction ("dump", tableSerialize)
+               .endNamespace ();
+
+       luabridge::push <LuaTableRef *> (L, &globalref);
+       lua_setglobal (L, "ref");
+
+
 #if 0 // session  script test
        lua.do_command (
                        "function ArdourSession ()"
@@ -274,6 +555,7 @@ int main (int argc, char **argv)
        add_history("a = Test:A() b = 2 c = 3 d = 'a'");
        add_history("x = a:get_arg(b)  y = a:get_arg2(b, c)  z = a:get_args(d) ");
        add_history("for i,n in ipairs(y) do print (i, n); end");
+       add_history("t = {} t[2] = 7; t[3] = Test:A() t[4] = Test:A() ref:set (t);  f = ref:get()");
 
        /////////////////////////////////////////////////////////////////////////////
        char *line;
@@ -294,3 +576,12 @@ int main (int argc, char **argv)
        printf("\n");
        return 0;
 }
+
+int main (int argc, char **argv)
+{
+       LuaState lua1;
+       LuaState lua2;
+       runone (lua1);
+       printf ("=====\n");
+       runone (lua2);
+}