00001 #ifndef __TABLE_SERIALIZER_H 00002 #define __TABLE_SERIALIZER_H 00003 00004 #include "RakMemoryOverride.h" 00005 #include "DS_Table.h" 00006 #include "Export.h" 00007 00008 namespace RakNet 00009 { 00010 class BitStream; 00011 } 00012 00013 class RAK_DLL_EXPORT TableSerializer 00014 { 00015 public: 00016 static void SerializeTable(DataStructures::Table *in, RakNet::BitStream *out); 00017 static bool DeserializeTable(unsigned char *serializedTable, unsigned int dataLength, DataStructures::Table *out); 00018 static bool DeserializeTable(RakNet::BitStream *in, DataStructures::Table *out); 00019 static void SerializeColumns(DataStructures::Table *in, RakNet::BitStream *out); 00020 static void SerializeColumns(DataStructures::Table *in, RakNet::BitStream *out, DataStructures::List<int> &skipColumnIndices); 00021 static bool DeserializeColumns(RakNet::BitStream *in, DataStructures::Table *out); 00022 static void SerializeRow(DataStructures::Table::Row *in, unsigned keyIn, const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns, RakNet::BitStream *out); 00023 static void SerializeRow(DataStructures::Table::Row *in, unsigned keyIn, const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns, RakNet::BitStream *out, DataStructures::List<int> &skipColumnIndices); 00024 static bool DeserializeRow(RakNet::BitStream *in, DataStructures::Table *out); 00025 static void SerializeCell(RakNet::BitStream *out, DataStructures::Table::Cell *cell, DataStructures::Table::ColumnType columnType); 00026 static bool DeserializeCell(RakNet::BitStream *in, DataStructures::Table::Cell *cell, DataStructures::Table::ColumnType columnType); 00027 static void SerializeFilterQuery(RakNet::BitStream *in, DataStructures::Table::FilterQuery *query); 00028 // Note that this allocates query->cell->c! 00029 static bool DeserializeFilterQuery(RakNet::BitStream *out, DataStructures::Table::FilterQuery *query); 00030 static void SerializeFilterQueryList(RakNet::BitStream *in, DataStructures::Table::FilterQuery *query, unsigned int numQueries, unsigned int maxQueries); 00031 // Note that this allocates queries, cells, and query->cell->c!. Use DeallocateQueryList to free. 00032 static bool DeserializeFilterQueryList(RakNet::BitStream *out, DataStructures::Table::FilterQuery **query, unsigned int *numQueries, unsigned int maxQueries, int allocateExtraQueries=0); 00033 static void DeallocateQueryList(DataStructures::Table::FilterQuery *query, unsigned int numQueries); 00034 }; 00035 00036 #endif 00037 00038 // Test code for the table 00039 /* 00040 #include "LightweightDatabaseServer.h" 00041 #include "LightweightDatabaseClient.h" 00042 #include "TableSerializer.h" 00043 #include "BitStream.h" 00044 #include "StringCompressor.h" 00045 #include "DS_Table.h" 00046 void main(void) 00047 { 00048 DataStructures::Table table; 00049 DataStructures::Table::Row *row; 00050 unsigned int dummydata=12345; 00051 00052 // Add columns Name (string), IP (binary), score (int), and players (int). 00053 table.AddColumn("Name", DataStructures::Table::STRING); 00054 table.AddColumn("IP", DataStructures::Table::BINARY); 00055 table.AddColumn("Score", DataStructures::Table::NUMERIC); 00056 table.AddColumn("Players", DataStructures::Table::NUMERIC); 00057 table.AddColumn("Empty Test Column", DataStructures::Table::STRING); 00058 RakAssert(table.GetColumnCount()==5); 00059 row=table.AddRow(0); 00060 RakAssert(row); 00061 row->UpdateCell(0,"Kevin Jenkins"); 00062 row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata); 00063 row->UpdateCell(2,5); 00064 row->UpdateCell(3,10); 00065 //row->UpdateCell(4,"should be unique"); 00066 00067 row=table.AddRow(1); 00068 row->UpdateCell(0,"Kevin Jenkins"); 00069 row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata); 00070 row->UpdateCell(2,5); 00071 row->UpdateCell(3,15); 00072 00073 row=table.AddRow(2); 00074 row->UpdateCell(0,"Kevin Jenkins"); 00075 row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata); 00076 row->UpdateCell(2,5); 00077 row->UpdateCell(3,20); 00078 00079 row=table.AddRow(3); 00080 RakAssert(row); 00081 row->UpdateCell(0,"Kevin Jenkins"); 00082 row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata); 00083 row->UpdateCell(2,15); 00084 row->UpdateCell(3,5); 00085 row->UpdateCell(4,"col index 4"); 00086 00087 row=table.AddRow(4); 00088 RakAssert(row); 00089 row->UpdateCell(0,"Kevin Jenkins"); 00090 row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata); 00091 //row->UpdateCell(2,25); 00092 row->UpdateCell(3,30); 00093 //row->UpdateCell(4,"should be unique"); 00094 00095 row=table.AddRow(5); 00096 RakAssert(row); 00097 row->UpdateCell(0,"Kevin Jenkins"); 00098 row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata); 00099 //row->UpdateCell(2,25); 00100 row->UpdateCell(3,5); 00101 //row->UpdateCell(4,"should be unique"); 00102 00103 row=table.AddRow(6); 00104 RakAssert(row); 00105 row->UpdateCell(0,"Kevin Jenkins"); 00106 row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata); 00107 row->UpdateCell(2,35); 00108 //row->UpdateCell(3,40); 00109 //row->UpdateCell(4,"should be unique"); 00110 00111 row=table.AddRow(7); 00112 RakAssert(row); 00113 row->UpdateCell(0,"Bob Jenkins"); 00114 00115 row=table.AddRow(8); 00116 RakAssert(row); 00117 row->UpdateCell(0,"Zack Jenkins"); 00118 00119 // Test multi-column sorting 00120 DataStructures::Table::Row *rows[30]; 00121 DataStructures::Table::SortQuery queries[4]; 00122 queries[0].columnIndex=0; 00123 queries[0].operation=DataStructures::Table::QS_INCREASING_ORDER; 00124 queries[1].columnIndex=1; 00125 queries[1].operation=DataStructures::Table::QS_INCREASING_ORDER; 00126 queries[2].columnIndex=2; 00127 queries[2].operation=DataStructures::Table::QS_INCREASING_ORDER; 00128 queries[3].columnIndex=3; 00129 queries[3].operation=DataStructures::Table::QS_DECREASING_ORDER; 00130 table.SortTable(queries, 4, rows); 00131 unsigned i; 00132 char out[256]; 00133 RAKNET_DEBUG_PRINTF("Sort: Ascending except for column index 3\n"); 00134 for (i=0; i < table.GetRowCount(); i++) 00135 { 00136 table.PrintRow(out,256,',',true, rows[i]); 00137 RAKNET_DEBUG_PRINTF("%s\n", out); 00138 } 00139 00140 // Test query: 00141 // Don't return column 3, and swap columns 0 and 2 00142 unsigned columnsToReturn[4]; 00143 columnsToReturn[0]=2; 00144 columnsToReturn[1]=1; 00145 columnsToReturn[2]=0; 00146 columnsToReturn[3]=4; 00147 DataStructures::Table resultsTable; 00148 table.QueryTable(columnsToReturn,4,0,0,&resultsTable); 00149 RAKNET_DEBUG_PRINTF("Query: Don't return column 3, and swap columns 0 and 2:\n"); 00150 for (i=0; i < resultsTable.GetRowCount(); i++) 00151 { 00152 resultsTable.PrintRow(out,256,',',true, resultsTable.GetRowByIndex(i)); 00153 RAKNET_DEBUG_PRINTF("%s\n", out); 00154 } 00155 00156 // Test filter: 00157 // Only return rows with column index 4 empty 00158 DataStructures::Table::FilterQuery inclusionFilters[3]; 00159 inclusionFilters[0].columnIndex=4; 00160 inclusionFilters[0].operation=DataStructures::Table::QF_IS_EMPTY; 00161 // inclusionFilters[0].cellValue; // Unused for IS_EMPTY 00162 table.QueryTable(0,0,inclusionFilters,1,&resultsTable); 00163 RAKNET_DEBUG_PRINTF("Filter: Only return rows with column index 4 empty:\n"); 00164 for (i=0; i < resultsTable.GetRowCount(); i++) 00165 { 00166 resultsTable.PrintRow(out,256,',',true, resultsTable.GetRowByIndex(i)); 00167 RAKNET_DEBUG_PRINTF("%s\n", out); 00168 } 00169 00170 // Column 5 empty and column 0 == Kevin Jenkins 00171 inclusionFilters[0].columnIndex=4; 00172 inclusionFilters[0].operation=DataStructures::Table::QF_IS_EMPTY; 00173 inclusionFilters[1].columnIndex=0; 00174 inclusionFilters[1].operation=DataStructures::Table::QF_EQUAL; 00175 inclusionFilters[1].cellValue.Set("Kevin Jenkins"); 00176 table.QueryTable(0,0,inclusionFilters,2,&resultsTable); 00177 RAKNET_DEBUG_PRINTF("Filter: Column 5 empty and column 0 == Kevin Jenkins:\n"); 00178 for (i=0; i < resultsTable.GetRowCount(); i++) 00179 { 00180 resultsTable.PrintRow(out,256,',',true, resultsTable.GetRowByIndex(i)); 00181 RAKNET_DEBUG_PRINTF("%s\n", out); 00182 } 00183 00184 RakNet::BitStream bs; 00185 RAKNET_DEBUG_PRINTF("PreSerialize:\n"); 00186 for (i=0; i < table.GetRowCount(); i++) 00187 { 00188 table.PrintRow(out,256,',',true, table.GetRowByIndex(i)); 00189 RAKNET_DEBUG_PRINTF("%s\n", out); 00190 } 00191 StringCompressor::AddReference(); 00192 TableSerializer::Serialize(&table, &bs); 00193 TableSerializer::Deserialize(&bs, &table); 00194 StringCompressor::RemoveReference(); 00195 RAKNET_DEBUG_PRINTF("PostDeserialize:\n"); 00196 for (i=0; i < table.GetRowCount(); i++) 00197 { 00198 table.PrintRow(out,256,',',true, table.GetRowByIndex(i)); 00199 RAKNET_DEBUG_PRINTF("%s\n", out); 00200 } 00201 int a=5; 00202 } 00203 */