a key-value pair container in runtime
a memory database
a data-driven pattern data structure
entity component system adapter
- Create a New Table
- Add New elements into Table
- Get Stuffs from Table
- Travel Table
- Internal Special Data Type
- Serialization
- Data Trigger/Delegate/Observer
- TQL(Table Query Language)
- TOP(Table Oriented Programming)
KVTableBasicDemo gives you more details
#include "itable.h" // kvtable interface header file
Schema::Table tab = Schema::CreateTable(); // create an empty table
KVTableBasicDemo gives you more details
// Note that all keys stored in tables are in string pool, thus you need to put them into pool by call 'cstr' interface, see icstr.h
// But table interface also provides a convenise way to index by instant 'const char*', that is functions with 'c' version like gets/sets
// NOTE that although 'c' version's functions are very fast, but if you use table in some core codes, make sure to manually maintance c_str with your own way, it's OK in most cases
tab.setc("integer", 0); // add a new pair key = "integer", value = 0
tab.set(cstr("unsigned int"), 1u);
tab.setc("integer64", 0xfffffffffi64);
tab.set(cstr("unsigned int64"), 0xffffffffffffffffui64);
Schema::Table tabReal = tab.set(cstr("real"));
tabReal.setc("float", 3.14f);
tabReal.setc("double", 3.14159265783);
Schema::Table tabStr = tab.setc("string");
c_str strString = cstr_string("string");
c_str strCStr = cstr_string("cstr");
tabStr.setStr(strString, "i'm a string");
tabStr.setCstr(strCStr, cstr("i'm a const string in string pool"));
KVTableBasicDemo gives you more details
tab.getc("integer", 0);
tab.get(cstr("unsigned int"), 0u);
tab.getInt64(cstr("integer64"));
tab.getcUint64("unsigned int64");
tabReal = tab.getc("real");
tabReal.getFloat(cstr("float"));
tabReal.getcDouble("double");
tabStr = tab.get(cstr("string"));
tabStr.getStr(strString);
tabStr.getCstr(strCStr);
KVTableTravelDemo gives you more details
int Travel(Schema::Table tab)
{
for (Schema::Iterator it = tab.begin(); it != tab.end(); it = tab.next(it))
{
printf("key = %s, value = ", it.key());
etvaltype typ = it.type();
switch (typ)
{
case etvt_reserved: printf("null\n"); break;
case etvt_ptr: printf("0x%I64x\n", (uint64)(ULONG_PTR)it.getPtr()); break;
case etvt_int: printf("%d\n", it.getInteger()); break;
case etvt_uint: printf("%u\n", it.getUint()); break;
case etvt_int64: printf("%lld\n", it.getInt64()); break;
case etvt_uint64: printf("%I64u\n", it.getUint64()); break;
case etvt_float: printf("%f\n", it.getFloat()); break;
case etvt_double: printf("%lf\n", it.getDouble()); break;
case etvt_float2:
case etvt_float3:
case etvt_float4: break;
case etvt_cstr: printf("%s\n", it.getCstr()); break;
case etvt_reference: break;
case etvt_table: Travel(it.getTable()); break;
case etvt_string: printf("%s\n", it.getString()); break;
case etvt_float4x4: break;
case etvt_userdata: break;
}
}
return true;
}
KVTableBasicDemo gives you more details
Schema::Table tabMath = tab.setc("math");
Schema::float2 f2(0, 3.14f);
Schema::float3 f3(1.f, 2.f, 3.f);
Schema::float4 f4(0, 0, 0, 1.f);
Schema::float4x4 f4x4;
tabMath.setc("float2", f2);
tabMath.setc("float3", f3);
tabMath.setc("float4", f4);
tabMath.setc("float4x4", f4x4);
tabMath.getc("float2", f2);
tabMath.getc("float3", f3);
tabMath.getc("float4", f4);
tabMath.getc("float4x4", f4x4);
struct _st { int a; float b; };
_st st = { 1, 3.14f };
Schema::Table tabUserdata = tab.setc("userdata");
tabUserdata.setcUserdata("userdata", &st, sizeof(_st));
st.a = 2; st.b = 0;
tabUserdata.setcUserdata("userdata2", &st, sizeof(_st));
tabUserdata.getcUserdata("userdata", &st, sizeof(_st));
tabUserdata.getcUserdata("userdata2", &st, sizeof(_st));
KVTableSerialiseDemo gives you more details
tab.save("tab_text.tab.txt", etft_text, false); // save as readable text file
tab.save("tab_text_pretty.tab.txt", etft_text, true); // save as readable text file with mutilple lines and indent
tab.save("tab_bin.tab", etft_binary, 0); // save as a binary file with 'zlib' compress
Schema::DestroyTable(tab);
tab = Schema::OpenTableFile("tab_text.tab.txt");
Schema::DestroyTable(tab);
tab = Schema::OpenTableFile("tab_text_pretty.tab.txt");
Schema::DestroyTable(tab);
tab = Schema::OpenTableFile("tab_bin.tab");
Schema::DestroyTable(tab);
KVTableDataTriggerDemo gives you more details
Data trigger feature is the first important fundamental function in 'Data-Driven' model.
In KVTable you can register one or more callback(s) for table or specified element in table in case any modification occured, those callbacks will be called.
Callbacks can be global functions, member functions in class or vitual functions.
int OnTableChanged(etopstatus ops, Schema::Table tab, c_str name); // global callback
struct ITrigger
{
virtual int OnVirtualTrigger(etopstatus ops, Schema::Table tab, c_str name) = 0; // vitual callback
};
class Trigger : public ITrigger
{
virtual int OnVirtualTrigger(etopstatus ops, Schema::Table tab, c_str name); // vitual callback
int OnClassTrigger(etopstatus ops, Schema::Table tab, c_str name); // member callback
};
:TODO As 'SQL', you can use TQL to query/modify data from any existed processes which use KVTable and expose any tables
TOP is a kind of programming pattern which absolutely sperates data and functions, like entity component system, there is no objects like 'Actor', 'Bullet', there is only data(KVTable, no functions) and system(class, no data).