libnative-utilities/include/raknet/TableSerializer.hpp

219 lines
7.9 KiB
C++
Raw Permalink Normal View History

2024-08-15 18:40:30 +08:00
/*
* Copyright (c) 2014, Oculus VR, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#ifndef __TABLE_SERIALIZER_H
#define __TABLE_SERIALIZER_H
#include "RakMemoryOverride.hpp"
#include "DS_Table.hpp"
#include "Export.hpp"
namespace RakNet
{
class BitStream;
}
namespace RakNet
{
class RAK_DLL_EXPORT TableSerializer
{
public:
static void SerializeTable(DataStructures::Table *in, RakNet::BitStream *out);
static bool DeserializeTable(unsigned char *serializedTable, unsigned int dataLength, DataStructures::Table *out);
static bool DeserializeTable(RakNet::BitStream *in, DataStructures::Table *out);
static void SerializeColumns(DataStructures::Table *in, RakNet::BitStream *out);
static void SerializeColumns(DataStructures::Table *in, RakNet::BitStream *out, DataStructures::List<int> &skipColumnIndices);
static bool DeserializeColumns(RakNet::BitStream *in, DataStructures::Table *out);
static void SerializeRow(DataStructures::Table::Row *in, unsigned keyIn, const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns, RakNet::BitStream *out);
static void SerializeRow(DataStructures::Table::Row *in, unsigned keyIn, const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns, RakNet::BitStream *out, DataStructures::List<int> &skipColumnIndices);
static bool DeserializeRow(RakNet::BitStream *in, DataStructures::Table *out);
static void SerializeCell(RakNet::BitStream *out, DataStructures::Table::Cell *cell, DataStructures::Table::ColumnType columnType);
static bool DeserializeCell(RakNet::BitStream *in, DataStructures::Table::Cell *cell, DataStructures::Table::ColumnType columnType);
static void SerializeFilterQuery(RakNet::BitStream *in, DataStructures::Table::FilterQuery *query);
// Note that this allocates query->cell->c!
static bool DeserializeFilterQuery(RakNet::BitStream *out, DataStructures::Table::FilterQuery *query);
static void SerializeFilterQueryList(RakNet::BitStream *in, DataStructures::Table::FilterQuery *query, unsigned int numQueries, unsigned int maxQueries);
// Note that this allocates queries, cells, and query->cell->c!. Use DeallocateQueryList to free.
static bool DeserializeFilterQueryList(RakNet::BitStream *out, DataStructures::Table::FilterQuery **query, unsigned int *numQueries, unsigned int maxQueries, int allocateExtraQueries=0);
static void DeallocateQueryList(DataStructures::Table::FilterQuery *query, unsigned int numQueries);
};
} // namespace RakNet
#endif
// Test code for the table
/*
#include "LightweightDatabaseServer.hpp"
#include "LightweightDatabaseClient.hpp"
#include "TableSerializer.hpp"
#include "BitStream.hpp"
#include "StringCompressor.hpp"
#include "DS_Table.hpp"
void main(void)
{
DataStructures::Table table;
DataStructures::Table::Row *row;
unsigned int dummydata=12345;
// Add columns Name (string), IP (binary), score (int), and players (int).
table.AddColumn("Name", DataStructures::Table::STRING);
table.AddColumn("IP", DataStructures::Table::BINARY);
table.AddColumn("Score", DataStructures::Table::NUMERIC);
table.AddColumn("Players", DataStructures::Table::NUMERIC);
table.AddColumn("Empty Test Column", DataStructures::Table::STRING);
RakAssert(table.GetColumnCount()==5);
row=table.AddRow(0);
RakAssert(row);
row->UpdateCell(0,"Kevin Jenkins");
row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
row->UpdateCell(2,5);
row->UpdateCell(3,10);
//row->UpdateCell(4,"should be unique");
row=table.AddRow(1);
row->UpdateCell(0,"Kevin Jenkins");
row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
row->UpdateCell(2,5);
row->UpdateCell(3,15);
row=table.AddRow(2);
row->UpdateCell(0,"Kevin Jenkins");
row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
row->UpdateCell(2,5);
row->UpdateCell(3,20);
row=table.AddRow(3);
RakAssert(row);
row->UpdateCell(0,"Kevin Jenkins");
row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
row->UpdateCell(2,15);
row->UpdateCell(3,5);
row->UpdateCell(4,"col index 4");
row=table.AddRow(4);
RakAssert(row);
row->UpdateCell(0,"Kevin Jenkins");
row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
//row->UpdateCell(2,25);
row->UpdateCell(3,30);
//row->UpdateCell(4,"should be unique");
row=table.AddRow(5);
RakAssert(row);
row->UpdateCell(0,"Kevin Jenkins");
row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
//row->UpdateCell(2,25);
row->UpdateCell(3,5);
//row->UpdateCell(4,"should be unique");
row=table.AddRow(6);
RakAssert(row);
row->UpdateCell(0,"Kevin Jenkins");
row->UpdateCell(1,sizeof(dummydata), (char*)&dummydata);
row->UpdateCell(2,35);
//row->UpdateCell(3,40);
//row->UpdateCell(4,"should be unique");
row=table.AddRow(7);
RakAssert(row);
row->UpdateCell(0,"Bob Jenkins");
row=table.AddRow(8);
RakAssert(row);
row->UpdateCell(0,"Zack Jenkins");
// Test multi-column sorting
DataStructures::Table::Row *rows[30];
DataStructures::Table::SortQuery queries[4];
queries[0].columnIndex=0;
queries[0].operation=DataStructures::Table::QS_INCREASING_ORDER;
queries[1].columnIndex=1;
queries[1].operation=DataStructures::Table::QS_INCREASING_ORDER;
queries[2].columnIndex=2;
queries[2].operation=DataStructures::Table::QS_INCREASING_ORDER;
queries[3].columnIndex=3;
queries[3].operation=DataStructures::Table::QS_DECREASING_ORDER;
table.SortTable(queries, 4, rows);
unsigned i;
char out[256];
RAKNET_DEBUG_PRINTF("Sort: Ascending except for column index 3\n");
for (i=0; i < table.GetRowCount(); i++)
{
table.PrintRow(out,256,',',true, rows[i]);
RAKNET_DEBUG_PRINTF("%s\n", out);
}
// Test query:
// Don't return column 3, and swap columns 0 and 2
unsigned columnsToReturn[4];
columnsToReturn[0]=2;
columnsToReturn[1]=1;
columnsToReturn[2]=0;
columnsToReturn[3]=4;
DataStructures::Table resultsTable;
table.QueryTable(columnsToReturn,4,0,0,&resultsTable);
RAKNET_DEBUG_PRINTF("Query: Don't return column 3, and swap columns 0 and 2:\n");
for (i=0; i < resultsTable.GetRowCount(); i++)
{
resultsTable.PrintRow(out,256,',',true, resultsTable.GetRowByIndex(i));
RAKNET_DEBUG_PRINTF("%s\n", out);
}
// Test filter:
// Only return rows with column index 4 empty
DataStructures::Table::FilterQuery inclusionFilters[3];
inclusionFilters[0].columnIndex=4;
inclusionFilters[0].operation=DataStructures::Table::QF_IS_EMPTY;
// inclusionFilters[0].cellValue; // Unused for IS_EMPTY
table.QueryTable(0,0,inclusionFilters,1,&resultsTable);
RAKNET_DEBUG_PRINTF("Filter: Only return rows with column index 4 empty:\n");
for (i=0; i < resultsTable.GetRowCount(); i++)
{
resultsTable.PrintRow(out,256,',',true, resultsTable.GetRowByIndex(i));
RAKNET_DEBUG_PRINTF("%s\n", out);
}
// Column 5 empty and column 0 == Kevin Jenkins
inclusionFilters[0].columnIndex=4;
inclusionFilters[0].operation=DataStructures::Table::QF_IS_EMPTY;
inclusionFilters[1].columnIndex=0;
inclusionFilters[1].operation=DataStructures::Table::QF_EQUAL;
inclusionFilters[1].cellValue.Set("Kevin Jenkins");
table.QueryTable(0,0,inclusionFilters,2,&resultsTable);
RAKNET_DEBUG_PRINTF("Filter: Column 5 empty and column 0 == Kevin Jenkins:\n");
for (i=0; i < resultsTable.GetRowCount(); i++)
{
resultsTable.PrintRow(out,256,',',true, resultsTable.GetRowByIndex(i));
RAKNET_DEBUG_PRINTF("%s\n", out);
}
RakNet::BitStream bs;
RAKNET_DEBUG_PRINTF("PreSerialize:\n");
for (i=0; i < table.GetRowCount(); i++)
{
table.PrintRow(out,256,',',true, table.GetRowByIndex(i));
RAKNET_DEBUG_PRINTF("%s\n", out);
}
StringCompressor::AddReference();
TableSerializer::Serialize(&table, &bs);
TableSerializer::Deserialize(&bs, &table);
StringCompressor::RemoveReference();
RAKNET_DEBUG_PRINTF("PostDeserialize:\n");
for (i=0; i < table.GetRowCount(); i++)
{
table.PrintRow(out,256,',',true, table.GetRowByIndex(i));
RAKNET_DEBUG_PRINTF("%s\n", out);
}
int a=5;
}
*/