diff options
Diffstat (limited to 'Src/nde/Field.cpp')
-rw-r--r-- | Src/nde/Field.cpp | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/Src/nde/Field.cpp b/Src/nde/Field.cpp new file mode 100644 index 00000000..f57800e5 --- /dev/null +++ b/Src/nde/Field.cpp @@ -0,0 +1,281 @@ +/* --------------------------------------------------------------------------- +Nullsoft Database Engine +-------------------- +codename: Near Death Experience +--------------------------------------------------------------------------- */ + +/* --------------------------------------------------------------------------- + +Field Class + +--------------------------------------------------------------------------- */ + +#include "field.h" +#include "vfs.h" +#include "table.h" +#include "nde.h" +#include "dbutils.h" + +#ifdef WIN32 +#include <malloc.h> +#elif defined(__APPLE__) +#include <alloca.h> +#endif + +//--------------------------------------------------------------------------- +void PUT_BINARY(uint8_t *dest, const uint8_t *src, size_t size, size_t pos) +{ + if (src && dest && size > 0) + memcpy(dest+pos, src, size); +} + +//--------------------------------------------------------------------------- +void GET_BINARY(uint8_t *dest, const uint8_t *src, size_t size, size_t pos) +{ + if (dest && src && size > 0) + memcpy(dest, src+pos, size); +} + +//--------------------------------------------------------------------------- +void PUT_FLOAT(float f, uint8_t *data, size_t pos) +{ + unsigned int y = *(const unsigned int *)&f; + data[pos]=(unsigned char)(y&255); data[pos+1]=(unsigned char)((y>>8)&255); data[pos+2]=(unsigned char)((y>>16)&255); data[pos+3]=(unsigned char)((y>>24)&255); +} + +//--------------------------------------------------------------------------- +float GET_FLOAT(const uint8_t *data, size_t pos) +{ + int a = data[pos]|(data[pos+1]<<8)|(data[pos+2]<<16)|(data[pos+3]<<24); + float f = *(const float *)&a; + return f; +} + +//--------------------------------------------------------------------------- +Field::Field(int FieldPos) +{ + InitField(); + Pos = FieldPos; +} + +//--------------------------------------------------------------------------- +void Field::InitField(void) +{ + Type = FIELD_UNKNOWN; + Pos = 0; + ID = 0; + MaxSizeOnDisk = 0; +} + +//--------------------------------------------------------------------------- +Field::Field() +{ + InitField(); +} + +//--------------------------------------------------------------------------- +Field::~Field() +{ +} + +//--------------------------------------------------------------------------- +Field *Field::ReadField(Table *pTable, int pos, uint32_t *next_position) +{ + return ReadField(pTable, pos, false, next_position); +} + +//--------------------------------------------------------------------------- +Field *Field::ReadField(Table *pTable, int pos, bool Quick, uint32_t *next_position) +{ + VFILE *HTable = pTable->Handle; + int newPos = pos; + int rType = FIELD_REDIRECTOR; + unsigned char oType; + + if (!Vflock(HTable, false)) + return 0; + + while (rType == FIELD_REDIRECTOR) + { + Vfseek(HTable, Pos, SEEK_SET); + if (Vfread(&ID, sizeof(ID), HTable) != 1 || + Vfread(&oType, sizeof(oType), HTable) != 1) + { + Vfunlock(HTable, false); + return NULL; + } + if (oType == FIELD_REDIRECTOR) + { + if (Vfread(&newPos, sizeof(newPos), HTable) != 1) + { + Vfunlock(HTable, false); + return NULL; + } + Pos = newPos; + } + rType = oType; + } + if (Quick) + Vfseek(HTable, sizeof(MaxSizeOnDisk), SEEK_CUR); + else + { + if (Vfread(&MaxSizeOnDisk, sizeof(MaxSizeOnDisk), HTable) != 1) + { + Vfunlock(HTable, false); + return NULL; + } + } + uint32_t NextFieldPos = 0; + if (Vfread(&NextFieldPos, sizeof(NextFieldPos), HTable) != 1) + { + Vfunlock(HTable, false); + return NULL; + } + if (next_position) *next_position = NextFieldPos; + if (Quick) + { + Vfunlock(HTable, false); + return this; + } + + uint32_t PreviousFieldPos = 0; + if (Vfread(&PreviousFieldPos, sizeof(PreviousFieldPos), HTable) != 1) + { + Vfunlock(HTable, false); + return NULL; + } + + Field *O=NULL; + O = TranslateObject(oType, pTable); + if (O) + { + O->ID = ID; + O->Type = oType; + O->Pos = Pos; + O->MaxSizeOnDisk = MaxSizeOnDisk; + uint8_t *data = NULL; + if (HTable->cached && MaxSizeOnDisk > VFILE_INC) + { + pTable->IncErrorCount(); + MaxSizeOnDisk = (uint32_t)GetDataSize(); + O->MaxSizeOnDisk = MaxSizeOnDisk; + } + else if (HTable->cached) + { + data = HTable->data+HTable->ptr; // benski> uber-hack + Vfseek(HTable, MaxSizeOnDisk, SEEK_CUR); + } + else + { + data = (uint8_t *)_malloca(MaxSizeOnDisk); + Vfread(data, MaxSizeOnDisk, HTable); + } + + if (data) + { + O->ReadTypedData(data, MaxSizeOnDisk); + if (!HTable->cached) + { + _freea(data); + } + } + Vfunlock(HTable, false); + return O; + } + Vfunlock(HTable, false); + return NULL; +} + +//--------------------------------------------------------------------------- +void Field::WriteField(Table *pTable, Field *previous_field, Field *next_field) +{ + VFILE *HTable = pTable->Handle; + if (Pos == -1) return; + size_t data_size = GetDataSize(); + if (HTable->cached && MaxSizeOnDisk > VFILE_INC) { + pTable->IncErrorCount(); + MaxSizeOnDisk = (uint32_t)data_size; + } + + if (Pos == 0 || (uint32_t)data_size > MaxSizeOnDisk) + { + MaxSizeOnDisk = (uint32_t)data_size; + uint32_t newPos = AllocNewPos(HTable); + if (Pos != 0) + { + unsigned char v = 0; + Vfseek(HTable, Pos, SEEK_SET); + Vfwrite(&v, sizeof(v), HTable); + v = FIELD_REDIRECTOR; + Vfwrite(&v, sizeof(v), HTable); + Vfwrite(&newPos, sizeof(newPos), HTable); + } + Pos = newPos; + if (previous_field) + { + //previous_field->NextFieldPos = Pos; + if (previous_field->Pos) + { + Vfseek(HTable, previous_field->Pos+sizeof(ID)+sizeof(MaxSizeOnDisk)+sizeof(Type), SEEK_SET); + Vfwrite(&Pos, sizeof(Pos), HTable); + } + } + if (next_field) + { + if (next_field->Pos) + { + Vfseek(HTable, next_field->Pos+sizeof(ID)+sizeof(uint32_t/*NextFieldPos*/)+sizeof(Type)+sizeof(MaxSizeOnDisk), SEEK_SET); + Vfwrite(&Pos, sizeof(Pos), HTable); + } + } + } + + uint32_t PreviousFieldPos = 0, NextFieldPos = 0; + if (previous_field) PreviousFieldPos = previous_field->GetFieldPos(); else PreviousFieldPos = NULL; + if (next_field) NextFieldPos = next_field->GetFieldPos(); else NextFieldPos = NULL; + + Vfseek(HTable, Pos, SEEK_SET); + Vfwrite(&ID, sizeof(ID), HTable); + Vfwrite(&Type, sizeof(Type), HTable); + Vfwrite(&MaxSizeOnDisk, sizeof(MaxSizeOnDisk), HTable); + Vfwrite(&NextFieldPos, sizeof(NextFieldPos), HTable); + Vfwrite(&PreviousFieldPos, sizeof(PreviousFieldPos), HTable); + uint8_t *data = (unsigned char*)_malloca(MaxSizeOnDisk); + WriteTypedData(data, MaxSizeOnDisk); + Vfwrite(data, MaxSizeOnDisk, HTable); + _freea(data); +} + +//--------------------------------------------------------------------------- +uint32_t Field::GetFieldPos(void) +{ + return Pos; +} + +//--------------------------------------------------------------------------- +Field *Field::Clone(Table *pTable) +{ + Field *clone = TranslateObject(Type, pTable); + size_t size = GetDataSize(); + uint8_t *data = (unsigned char*)_malloca(size); + WriteTypedData(data, size); + clone->ReadTypedData(data, size); + if (data) _freea(data); + clone->Type = Type; + //clone->HTable = HTable; + clone->Pos = FIELD_CLONE; + clone->ID = ID; + //clone->NextFieldPos = 0; + clone->MaxSizeOnDisk=(uint32_t)size; + return clone; +} + +//--------------------------------------------------------------------------- +int Field::GetType() { + return Type; +} + +size_t Field::GetTotalSize() +{ + return GetDataSize() + sizeof(ID)+sizeof(Type)+sizeof(MaxSizeOnDisk)+sizeof(uint32_t/*NextFieldPos*/)+sizeof(uint32_t /*PreviousFieldPos*/); +}
\ No newline at end of file |