| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- /*
- * 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.
- *
- */
- #include "TableSerializer.h"
- #include "DS_Table.h"
- #include "BitStream.h"
- #include "StringCompressor.h"
- #include "RakAssert.h"
- using namespace RakNet;
- void TableSerializer::SerializeTable(DataStructures::Table *in, RakNet::BitStream *out)
- {
- DataStructures::Page<unsigned, DataStructures::Table::Row*, _TABLE_BPLUS_TREE_ORDER> *cur = in->GetRows().GetListHead();
- const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns=in->GetColumns();
- SerializeColumns(in, out);
- out->Write((unsigned)in->GetRows().Size());
- unsigned rowIndex;
- while (cur)
- {
- for (rowIndex=0; rowIndex < (unsigned)cur->size; rowIndex++)
- {
- SerializeRow(cur->data[rowIndex], cur->keys[rowIndex], columns, out);
- }
- cur=cur->next;
- }
- }
- void TableSerializer::SerializeColumns(DataStructures::Table *in, RakNet::BitStream *out)
- {
- const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns=in->GetColumns();
- out->Write((unsigned)columns.Size());
- unsigned i;
- for (i=0; i<columns.Size(); i++)
- {
- StringCompressor::Instance()->EncodeString(columns[i].columnName, _TABLE_MAX_COLUMN_NAME_LENGTH, out);
- out->Write((unsigned char)columns[i].columnType);
- }
- }
- void TableSerializer::SerializeColumns(DataStructures::Table *in, RakNet::BitStream *out, DataStructures::List<int> &skipColumnIndices)
- {
- const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns=in->GetColumns();
- out->Write((unsigned)columns.Size()-skipColumnIndices.Size());
- unsigned i;
- for (i=0; i<columns.Size(); i++)
- {
- if (skipColumnIndices.GetIndexOf(i)==(unsigned)-1)
- {
- StringCompressor::Instance()->EncodeString(columns[i].columnName, _TABLE_MAX_COLUMN_NAME_LENGTH, out);
- out->Write((unsigned char)columns[i].columnType);
- }
- }
- }
- bool TableSerializer::DeserializeTable(unsigned char *serializedTable, unsigned int dataLength, DataStructures::Table *out)
- {
- RakNet::BitStream in((unsigned char*) serializedTable, dataLength, false);
- return DeserializeTable(&in, out);
- }
- bool TableSerializer::DeserializeTable(RakNet::BitStream *in, DataStructures::Table *out)
- {
- unsigned rowSize;
- DeserializeColumns(in,out);
- if (in->Read(rowSize)==false || rowSize>100000)
- {
- RakAssert(0);
- return false; // Hacker crash prevention
- }
- unsigned rowIndex;
- for (rowIndex=0; rowIndex < rowSize; rowIndex++)
- {
- if (DeserializeRow(in, out)==false)
- return false;
- }
- return true;
- }
- bool TableSerializer::DeserializeColumns(RakNet::BitStream *in, DataStructures::Table *out)
- {
- unsigned columnSize;
- unsigned char columnType;
- char columnName[_TABLE_MAX_COLUMN_NAME_LENGTH];
- if (in->Read(columnSize)==false || columnSize > 10000)
- return false; // Hacker crash prevention
- out->Clear();
- unsigned i;
- for (i=0; i<columnSize; i++)
- {
- StringCompressor::Instance()->DecodeString(columnName, 32, in);
- in->Read(columnType);
- out->AddColumn(columnName, (DataStructures::Table::ColumnType)columnType);
- }
- return true;
- }
- void TableSerializer::SerializeRow(DataStructures::Table::Row *in, unsigned keyIn, const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns, RakNet::BitStream *out)
- {
- unsigned cellIndex;
- out->Write(keyIn);
- unsigned int columnsSize = columns.Size();
- out->Write(columnsSize);
- for (cellIndex=0; cellIndex<columns.Size(); cellIndex++)
- {
- out->Write(cellIndex);
- SerializeCell(out, in->cells[cellIndex], columns[cellIndex].columnType);
- }
- }
- void TableSerializer::SerializeRow(DataStructures::Table::Row *in, unsigned keyIn, const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns, RakNet::BitStream *out, DataStructures::List<int> &skipColumnIndices)
- {
- unsigned cellIndex;
- out->Write(keyIn);
- unsigned int numEntries=0;
- for (cellIndex=0; cellIndex<columns.Size(); cellIndex++)
- {
- if (skipColumnIndices.GetIndexOf(cellIndex)==(unsigned)-1)
- {
- numEntries++;
- }
- }
- out->Write(numEntries);
- for (cellIndex=0; cellIndex<columns.Size(); cellIndex++)
- {
- if (skipColumnIndices.GetIndexOf(cellIndex)==(unsigned)-1)
- {
- out->Write(cellIndex);
- SerializeCell(out, in->cells[cellIndex], columns[cellIndex].columnType);
- }
- }
- }
- bool TableSerializer::DeserializeRow(RakNet::BitStream *in, DataStructures::Table *out)
- {
- const DataStructures::List<DataStructures::Table::ColumnDescriptor> &columns=out->GetColumns();
- unsigned numEntries;
- DataStructures::Table::Row *row;
- unsigned key;
- if (in->Read(key)==false)
- return false;
- row=out->AddRow(key);
- unsigned int cnt;
- in->Read(numEntries);
- for (cnt=0; cnt<numEntries; cnt++)
- {
- unsigned cellIndex;
- in->Read(cellIndex);
- if (DeserializeCell(in, row->cells[cellIndex], columns[cellIndex].columnType)==false)
- {
- out->RemoveRow(key);
- return false;
- }
- }
- return true;
- }
- void TableSerializer::SerializeCell(RakNet::BitStream *out, DataStructures::Table::Cell *cell, DataStructures::Table::ColumnType columnType)
- {
- out->Write(cell->isEmpty);
- if (cell->isEmpty==false)
- {
- if (columnType==DataStructures::Table::NUMERIC)
- {
- out->Write(cell->i);
- }
- else if (columnType==DataStructures::Table::STRING)
- {
- StringCompressor::Instance()->EncodeString(cell->c, 65535, out);
- }
- else if (columnType==DataStructures::Table::POINTER)
- {
- out->Write(cell->ptr);
- }
- else
- {
- // Binary
- RakAssert(columnType==DataStructures::Table::BINARY);
- RakAssert(cell->i>0);
- unsigned binaryLength;
- binaryLength=(unsigned)cell->i;
- out->Write(binaryLength);
- out->WriteAlignedBytes((const unsigned char*) cell->c, (const unsigned int) cell->i);
- }
- }
- }
- bool TableSerializer::DeserializeCell(RakNet::BitStream *in, DataStructures::Table::Cell *cell, DataStructures::Table::ColumnType columnType)
- {
- bool isEmpty=false;
- double value;
- void *ptr;
- char tempString[65535];
- cell->Clear();
- if (in->Read(isEmpty)==false)
- return false;
- if (isEmpty==false)
- {
- if (columnType==DataStructures::Table::NUMERIC)
- {
- if (in->Read(value)==false)
- return false;
- cell->Set(value);
- }
- else if (columnType==DataStructures::Table::STRING)
- {
- if (StringCompressor::Instance()->DecodeString(tempString, 65535, in)==false)
- return false;
- cell->Set(tempString);
- }
- else if (columnType==DataStructures::Table::POINTER)
- {
- if (in->Read(ptr)==false)
- return false;
- cell->SetPtr(ptr);
- }
- else
- {
- unsigned binaryLength;
- // Binary
- RakAssert(columnType==DataStructures::Table::BINARY);
- if (in->Read(binaryLength)==false || binaryLength > 10000000)
- return false; // Sanity check to max binary cell of 10 megabytes
- in->AlignReadToByteBoundary();
- if (BITS_TO_BYTES(in->GetNumberOfUnreadBits())<(BitSize_t)binaryLength)
- return false;
- cell->Set((char*) in->GetData()+BITS_TO_BYTES(in->GetReadOffset()), (int) binaryLength);
- in->IgnoreBits(BYTES_TO_BITS((int) binaryLength));
- }
- }
- return true;
- }
- void TableSerializer::SerializeFilterQuery(RakNet::BitStream *in, DataStructures::Table::FilterQuery *query)
- {
- StringCompressor::Instance()->EncodeString(query->columnName,_TABLE_MAX_COLUMN_NAME_LENGTH,in,0);
- in->WriteCompressed(query->columnIndex);
- in->Write((unsigned char) query->operation);
- in->Write(query->cellValue->isEmpty);
- if (query->cellValue->isEmpty==false)
- {
- in->Write(query->cellValue->i);
- in->WriteAlignedBytesSafe((const char*)query->cellValue->c,(const unsigned int)query->cellValue->i,10000000); // Sanity check to max binary cell of 10 megabytes
- in->Write(query->cellValue->ptr);
- }
- }
- bool TableSerializer::DeserializeFilterQuery(RakNet::BitStream *out, DataStructures::Table::FilterQuery *query)
- {
- bool b;
- RakAssert(query->cellValue);
- StringCompressor::Instance()->DecodeString(query->columnName,_TABLE_MAX_COLUMN_NAME_LENGTH,out,0);
- out->ReadCompressed(query->columnIndex);
- unsigned char op;
- out->Read(op);
- query->operation=(DataStructures::Table::FilterQueryType) op;
- query->cellValue->Clear();
- b=out->Read(query->cellValue->isEmpty);
- if (query->cellValue->isEmpty==false)
- {
- // HACK - cellValue->i is used for integer, character, and binary data. However, for character and binary c will be 0. So use that to determine if the data was integer or not.
- out->Read(query->cellValue->i);
- unsigned int inputLength;
- out->ReadAlignedBytesSafeAlloc(&query->cellValue->c,inputLength,10000000); // Sanity check to max binary cell of 10 megabytes
- if (query->cellValue->c)
- query->cellValue->i=inputLength;
- b=out->Read(query->cellValue->ptr);
- }
- return b;
- }
- void TableSerializer::SerializeFilterQueryList(RakNet::BitStream *in, DataStructures::Table::FilterQuery *query, unsigned int numQueries, unsigned int maxQueries)
- {
- (void) maxQueries;
- in->Write((bool)(query && numQueries>0));
- if (query==0 || numQueries<=0)
- return;
- RakAssert(numQueries<=maxQueries);
- in->WriteCompressed(numQueries);
- unsigned i;
- for (i=0; i < numQueries; i++)
- {
- SerializeFilterQuery(in, query);
- }
- }
- bool TableSerializer::DeserializeFilterQueryList(RakNet::BitStream *out, DataStructures::Table::FilterQuery **query, unsigned int *numQueries, unsigned int maxQueries, int allocateExtraQueries)
- {
- bool b, anyQueries=false;
- out->Read(anyQueries);
- if (anyQueries==false)
- {
- if (allocateExtraQueries<=0)
- *query=0;
- else
- *query=new DataStructures::Table::FilterQuery[allocateExtraQueries];
- *numQueries=0;
- return true;
- }
- b=out->ReadCompressed(*numQueries);
- if (*numQueries>maxQueries)
- {
- RakAssert(0);
- *numQueries=maxQueries;
- }
- if (*numQueries==0)
- return b;
- *query=new DataStructures::Table::FilterQuery[*numQueries+allocateExtraQueries];
- DataStructures::Table::FilterQuery *queryPtr = *query;
- unsigned i;
- for (i=0; i < *numQueries; i++)
- {
- queryPtr[i].cellValue=new DataStructures::Table::Cell;
- b=DeserializeFilterQuery(out, queryPtr+i);
- }
- return b;
- }
- void TableSerializer::DeallocateQueryList(DataStructures::Table::FilterQuery *query, unsigned int numQueries)
- {
- if (query==0 || numQueries==0)
- return;
- unsigned i;
- for (i=0; i < numQueries; i++)
- RakNet::OP_DELETE(query[i].cellValue, _FILE_AND_LINE_);
- RakNet::OP_DELETE_ARRAY(query, _FILE_AND_LINE_);
- }
|