1 #ifndef __TABLE_SERIALIZER_H
2 #define __TABLE_SERIALIZER_H
3 
4 #include "RakMemoryOverride.h"
5 #include "DS_Table.h"
6 #include "Export.h"
7 
8 namespace RakNet
9 {
10 	class BitStream;
11 }
12 
13 class RAK_DLL_EXPORT TableSerializer
14 {
15 public:
16 	static void SerializeTable(DataStructures::Table *in, RakNet::BitStream *out);
17 	static bool DeserializeTable(unsigned char *serializedTable, unsigned int dataLength, DataStructures::Table *out);
18 	static bool DeserializeTable(RakNet::BitStream *in, DataStructures::Table *out);
19 	static void SerializeColumns(DataStructures::Table *in, RakNet::BitStream *out);
20 	static void SerializeColumns(DataStructures::Table *in, RakNet::BitStream *out, DataStructures::List<int> &skipColumnIndices);
21 	static bool DeserializeColumns(RakNet::BitStream *in, DataStructures::Table *out);
22 	static void SerializeRow(DataStructures::Table::Row *in, unsigned keyIn, const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns, RakNet::BitStream *out);
23 	static void SerializeRow(DataStructures::Table::Row *in, unsigned keyIn, const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns, RakNet::BitStream *out, DataStructures::List<int> &skipColumnIndices);
24 	static bool DeserializeRow(RakNet::BitStream *in, DataStructures::Table *out);
25 	static void SerializeCell(RakNet::BitStream *out, DataStructures::Table::Cell *cell, DataStructures::Table::ColumnType columnType);
26 	static bool DeserializeCell(RakNet::BitStream *in, DataStructures::Table::Cell *cell, DataStructures::Table::ColumnType columnType);
27 	static void SerializeFilterQuery(RakNet::BitStream *in, DataStructures::Table::FilterQuery *query);
28 	// Note that this allocates query->cell->c!
29 	static bool DeserializeFilterQuery(RakNet::BitStream *out, DataStructures::Table::FilterQuery *query);
30 	static void SerializeFilterQueryList(RakNet::BitStream *in, DataStructures::Table::FilterQuery *query, unsigned int numQueries, unsigned int maxQueries);
31 	// Note that this allocates queries, cells, and query->cell->c!. Use DeallocateQueryList to free.
32 	static bool DeserializeFilterQueryList(RakNet::BitStream *out, DataStructures::Table::FilterQuery **query, unsigned int *numQueries, unsigned int maxQueries, int allocateExtraQueries=0);
33 	static void DeallocateQueryList(DataStructures::Table::FilterQuery *query, unsigned int numQueries);
34 };
35 
36 #endif
37 
38 // Test code for the table
39 /*
40 #include "LightweightDatabaseServer.h"
41 #include "LightweightDatabaseClient.h"
42 #include "TableSerializer.h"
43 #include "BitStream.h"
44 #include "StringCompressor.h"
45 #include "DS_Table.h"
46 void main(void)
47 {
48 	DataStructures::Table table;
49 	DataStructures::Table::Row *row;
50 	unsigned int dummydata=12345;
51 
52 	// Add columns Name (string), IP (binary), score (int), and players (int).
53 	table.AddColumn("Name", DataStructures::Table::STRING);
54 	table.AddColumn("IP", DataStructures::Table::BINARY);
55 	table.AddColumn("Score", DataStructures::Table::NUMERIC);
56 	table.AddColumn("Players", DataStructures::Table::NUMERIC);
57 	table.AddColumn("Empty Test Column", DataStructures::Table::STRING);
58 	RakAssert(table.GetColumnCount()==5);
59 	row=table.AddRow(0);
60 	RakAssert(row);
61 	row->UpdateCell(0,"Kevin Jenkins");
62 	row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
63 	row->UpdateCell(2,5);
64 	row->UpdateCell(3,10);
65 	//row->UpdateCell(4,"should be unique");
66 
67 	row=table.AddRow(1);
68 	row->UpdateCell(0,"Kevin Jenkins");
69 	row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
70 	row->UpdateCell(2,5);
71 	row->UpdateCell(3,15);
72 
73 	row=table.AddRow(2);
74 	row->UpdateCell(0,"Kevin Jenkins");
75 	row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
76 	row->UpdateCell(2,5);
77 	row->UpdateCell(3,20);
78 
79 	row=table.AddRow(3);
80 	RakAssert(row);
81 	row->UpdateCell(0,"Kevin Jenkins");
82 	row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
83 	row->UpdateCell(2,15);
84 	row->UpdateCell(3,5);
85 	row->UpdateCell(4,"col index 4");
86 
87 	row=table.AddRow(4);
88 	RakAssert(row);
89 	row->UpdateCell(0,"Kevin Jenkins");
90 	row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
91 	//row->UpdateCell(2,25);
92 	row->UpdateCell(3,30);
93 	//row->UpdateCell(4,"should be unique");
94 
95 	row=table.AddRow(5);
96 	RakAssert(row);
97 	row->UpdateCell(0,"Kevin Jenkins");
98 	row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
99 	//row->UpdateCell(2,25);
100 	row->UpdateCell(3,5);
101 	//row->UpdateCell(4,"should be unique");
102 
103 	row=table.AddRow(6);
104 	RakAssert(row);
105 	row->UpdateCell(0,"Kevin Jenkins");
106 	row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
107 	row->UpdateCell(2,35);
108 	//row->UpdateCell(3,40);
109 	//row->UpdateCell(4,"should be unique");
110 
111 	row=table.AddRow(7);
112 	RakAssert(row);
113 	row->UpdateCell(0,"Bob Jenkins");
114 
115 	row=table.AddRow(8);
116 	RakAssert(row);
117 	row->UpdateCell(0,"Zack Jenkins");
118 
119 	// Test multi-column sorting
120 	DataStructures::Table::Row *rows[30];
121 	DataStructures::Table::SortQuery queries[4];
122 	queries[0].columnIndex=0;
123 	queries[0].operation=DataStructures::Table::QS_INCREASING_ORDER;
124 	queries[1].columnIndex=1;
125 	queries[1].operation=DataStructures::Table::QS_INCREASING_ORDER;
126 	queries[2].columnIndex=2;
127 	queries[2].operation=DataStructures::Table::QS_INCREASING_ORDER;
128 	queries[3].columnIndex=3;
129 	queries[3].operation=DataStructures::Table::QS_DECREASING_ORDER;
130 	table.SortTable(queries, 4, rows);
131 	unsigned i;
132 	char out[256];
133 	RAKNET_DEBUG_PRINTF("Sort: Ascending except for column index 3\n");
134 	for (i=0; i < table.GetRowCount(); i++)
135 	{
136 		table.PrintRow(out,256,',',true, rows[i]);
137 		RAKNET_DEBUG_PRINTF("%s\n", out);
138 	}
139 
140 	// Test query:
141 	// Don't return column 3, and swap columns 0 and 2
142 	unsigned columnsToReturn[4];
143 	columnsToReturn[0]=2;
144 	columnsToReturn[1]=1;
145 	columnsToReturn[2]=0;
146 	columnsToReturn[3]=4;
147 	DataStructures::Table resultsTable;
148 	table.QueryTable(columnsToReturn,4,0,0,&resultsTable);
149 	RAKNET_DEBUG_PRINTF("Query: Don't return column 3, and swap columns 0 and 2:\n");
150 	for (i=0; i < resultsTable.GetRowCount(); i++)
151 	{
152 		resultsTable.PrintRow(out,256,',',true, resultsTable.GetRowByIndex(i));
153 		RAKNET_DEBUG_PRINTF("%s\n", out);
154 	}
155 
156 	// Test filter:
157 	// Only return rows with column index 4 empty
158 	DataStructures::Table::FilterQuery inclusionFilters[3];
159 	inclusionFilters[0].columnIndex=4;
160 	inclusionFilters[0].operation=DataStructures::Table::QF_IS_EMPTY;
161 	// inclusionFilters[0].cellValue; // Unused for IS_EMPTY
162 	table.QueryTable(0,0,inclusionFilters,1,&resultsTable);
163 	RAKNET_DEBUG_PRINTF("Filter: Only return rows with column index 4 empty:\n");
164 	for (i=0; i < resultsTable.GetRowCount(); i++)
165 	{
166 		resultsTable.PrintRow(out,256,',',true, resultsTable.GetRowByIndex(i));
167 		RAKNET_DEBUG_PRINTF("%s\n", out);
168 	}
169 
170 	// Column 5 empty and column 0 == Kevin Jenkins
171 	inclusionFilters[0].columnIndex=4;
172 	inclusionFilters[0].operation=DataStructures::Table::QF_IS_EMPTY;
173 	inclusionFilters[1].columnIndex=0;
174 	inclusionFilters[1].operation=DataStructures::Table::QF_EQUAL;
175 	inclusionFilters[1].cellValue.Set("Kevin Jenkins");
176 	table.QueryTable(0,0,inclusionFilters,2,&resultsTable);
177 	RAKNET_DEBUG_PRINTF("Filter: Column 5 empty and column 0 == Kevin Jenkins:\n");
178 	for (i=0; i < resultsTable.GetRowCount(); i++)
179 	{
180 		resultsTable.PrintRow(out,256,',',true, resultsTable.GetRowByIndex(i));
181 		RAKNET_DEBUG_PRINTF("%s\n", out);
182 	}
183 
184 	RakNet::BitStream bs;
185 	RAKNET_DEBUG_PRINTF("PreSerialize:\n");
186 	for (i=0; i < table.GetRowCount(); i++)
187 	{
188 		table.PrintRow(out,256,',',true, table.GetRowByIndex(i));
189 		RAKNET_DEBUG_PRINTF("%s\n", out);
190 	}
191 	StringCompressor::AddReference();
192 	TableSerializer::Serialize(&table, &bs);
193 	TableSerializer::Deserialize(&bs, &table);
194 	StringCompressor::RemoveReference();
195 	RAKNET_DEBUG_PRINTF("PostDeserialize:\n");
196 	for (i=0; i < table.GetRowCount(); i++)
197 	{
198 		table.PrintRow(out,256,',',true, table.GetRowByIndex(i));
199 		RAKNET_DEBUG_PRINTF("%s\n", out);
200 	}
201 	int a=5;
202 }
203 */
204