diff --git a/cinera/cinera.c b/cinera/cinera.c index 4775790..618a654 100644 --- a/cinera/cinera.c +++ b/cinera/cinera.c @@ -23,7 +23,7 @@ typedef struct version CINERA_APP_VERSION = { .Major = 0, .Minor = 10, - .Patch = 13 + .Patch = 14 }; #define __USE_XOPEN2K8 // NOTE(matt): O_NOFOLLOW @@ -224,31 +224,31 @@ GetUsage(void) // #if DEBUG_MEMORY_LEAKAGE int DebugMemoryIndentLevel = 0; -#define MEM_TEST_TOP(String) int MemTestInitialValue = GetUsage(); int MemTestRunningValue = MemTestInitialValue;\ +#define MEM_TEST_TOP() int MemTestInitialValue = GetUsage(); int MemTestRunningValue = MemTestInitialValue;\ /*\ Colourise(CS_BLACK_BOLD);\ fprintf(stderr, "[%5i]", __LINE__);\ Colourise(CS_GREEN);\ fprintf(stderr, " ");\ Indent(DebugMemoryIndentLevel);\ - fprintf(stderr, "%s starts at %i kb\n", String, MemTestInitialValue);\ + fprintf(stderr, "%s() starts at %i kb\n", __func__, MemTestInitialValue);\ Colourise(CS_END);\ */\ ++DebugMemoryIndentLevel; -#define MEM_TEST_MID(String) if(GetUsage() > MemTestRunningValue)\ +#define MEM_TEST_MID() if(GetUsage() > MemTestRunningValue)\ {\ Colourise(CS_BLACK_BOLD);\ fprintf(stderr, "[%5i]", __LINE__);\ Colourise(CS_YELLOW);\ fprintf(stderr, " ");\ Indent(DebugMemoryIndentLevel - 1);\ - fprintf(stderr, "%s is now at %i kb (+%i)\n", String, GetUsage(), GetUsage() - MemTestInitialValue);\ + fprintf(stderr, "%s() is now at %i kb (+%i)\n", __func__, GetUsage(), GetUsage() - MemTestInitialValue);\ Colourise(CS_END);\ MemTestRunningValue = GetUsage();\ WaitForInput();\ } -#define MEM_TEST_END(String) MemTestRunningValue = GetUsage();\ +#define MEM_TEST_END() MemTestRunningValue = GetUsage();\ --DebugMemoryIndentLevel;\ if(MemTestRunningValue > MemTestInitialValue)\ {\ @@ -257,14 +257,14 @@ int DebugMemoryIndentLevel = 0; Colourise(CS_RED);\ fprintf(stderr, " ");\ Indent(DebugMemoryIndentLevel);\ - fprintf(stderr, "%s ends at %i kb (+%i)\n", String, MemTestRunningValue, MemTestRunningValue - MemTestInitialValue);\ + fprintf(stderr, "%s() ends at %i kb (+%i)\n", __func__, MemTestRunningValue, MemTestRunningValue - MemTestInitialValue);\ Colourise(CS_END);\ WaitForInput();\ } #else -#define MEM_TEST_TOP(String) -#define MEM_TEST_MID(String) -#define MEM_TEST_END(String) +#define MEM_TEST_TOP() +#define MEM_TEST_MID() +#define MEM_TEST_END() #endif // //// @@ -2182,14 +2182,14 @@ void WaitForInput(void); // NOTE(matt): Forward declared void FreeBuffer(buffer *Buffer) { - /* */ MEM_TEST_TOP("FreeBuffer"); + /* */ MEM_TEST_TOP(); /* +MEM */ Free(Buffer->Location); - /* */ MEM_TEST_MID("FreeBuffer"); + /* */ MEM_TEST_MID(); Buffer->Ptr = 0; Buffer->Size = 0; //Buffer->ID = 0; Buffer->IndentLevel = 0; - MEM_TEST_END("FreeBuffer"); + MEM_TEST_END(); } char *AssetTypeNames[] = @@ -2606,9 +2606,11 @@ typedef struct typedef struct { - unsigned int PrevStart, NextStart; - unsigned short int PrevEnd, NextEnd; -} link_insertion_offsets; // NOTE(matt): PrevStart is Absolute (or relative to start of file), the others are Relative to PrevStart + // NOTE(matt): PrevStart is Absolute (or relative to start of file), + // the others are Relative to PrevStart + unsigned int PrevStart, NextStart; // 8 + unsigned short int PrevEnd, NextEnd; // 4 +} link_insertion_offsets; // 12 typedef struct { @@ -2781,7 +2783,12 @@ typedef struct typedef struct { db_project_index5 Project; - int32_t EntryIndex; + int32_t Entry; +} db_project_and_entry_index5; + +typedef struct +{ + db_project_and_entry_index5 Index; uint32_t Position; } db_landmark5; @@ -2815,8 +2822,597 @@ typedef struct #define db_project_index db_project_index5 #define db_landmark db_landmark5 #define database database5 + +typedef enum +{ + B_ASET, + B_PROJ, +} block_id; + +uint32_t +GetFourFromBlockID(block_id ID) +{ + uint32_t Result = 0; + switch(ID) + { + case B_ASET: Result = FOURCC("ASET"); break; + case B_PROJ: Result = FOURCC("PROJ"); break; + } + return Result; +} // TODO(matt): Increment CINERA_DB_VERSION! +typedef enum +{ + DBS_BLOCK, + DBS_ENTRY, + DBS_HEADERED_SECTION, + DBS_INDEXER_FIELD, +} db_structure_item_type; + +typedef enum +{ + IDX_SINGLE, + IDX_COMPOUND, +} db_structure_indexer_type; + +typedef struct +{ + db_structure_item_type Type; + void *Item; +} db_structure_item; + +typedef struct +{ + string Name; + uint32_t Offset; + uint32_t SizeOf; + db_structure_item Parent; +} db_structure_field; + +typedef struct +{ + db_structure_indexer_type Type; + db_structure_field Field; +} db_structure_indexer; + +db_structure_field +PackDBStructureField(string Name, uint32_t Offset, uint32_t SizeOf) +{ + db_structure_field Result = { .Name = Name, .Offset = Offset, .SizeOf = SizeOf }; + return Result; +} + +typedef enum +{ + DST_SELF, + DST_CHUNK, +} db_structure_sort_type; + +typedef struct +{ + db_structure_field Field; + db_structure_sort_type Type; +} db_structure_sorting_field; + +typedef struct +{ + string Name; + uint32_t SizeOf; + _memory_book(db_structure_indexer) IndexerFields; + db_structure_item Parent; +} db_structure_datatype; + +typedef struct +{ + db_structure_datatype Self; + db_structure_sorting_field SortingField; + db_structure_field EntryCount; + _memory_book(db_structure_item) IndexedIntoBy; + db_structure_datatype Entry; + db_structure_field ChildCount; + + db_structure_item Parent; +} db_structure_headered_section; + +typedef struct +{ + db_structure_headered_section HeaderedSection; + db_structure_field Count; + _memory_book(db_structure_item) IndexedIntoBy; + uint32_t ID; + string PrintableName; + uint32_t SizeOf; + db_structure_datatype Entry; +} db_structure_block; + +typedef struct +{ + uint32_t HexSignature; + uint32_t SizeOf; + db_structure_field BlockCount; +} db_structure_header; + +typedef struct +{ + _memory_book(db_structure_block) Blocks; + db_structure_header Header; + uint32_t Version; +} db_structure; + +typedef struct +{ + _memory_book(db_structure) Structure; + memory_book Strings; +} db_structures; + +db_structures DBStructures; +db_structure *CurrentDBStructure; +db_structure *PreviousDBStructure; + +db_structure_block * +InitDBStructureBlock(db_structure *S, memory_book *Strings, + char *ID, uint32_t SizeOf, + char *CountName, uint32_t CountOffset, uint32_t CountSizeOf, + char *EntryDataTypeName, uint32_t EntrySizeOf) +{ + db_structure_block *Result = MakeSpaceInBook(&S->Blocks); + Result->ID = FOURCC(ID); + Result->PrintableName = WriteStringInBook(Strings, Wrap0(ID)); + Result->SizeOf = SizeOf; + Result->Count = PackDBStructureField(WriteStringInBook(Strings, Wrap0(CountName)), + CountOffset, + CountSizeOf); + + if(EntrySizeOf) + { + Result->Entry.Name = WriteStringInBook(Strings, Wrap0(EntryDataTypeName)); + Result->Entry.SizeOf = EntrySizeOf; + + Result->Entry.Parent.Type = DBS_BLOCK; + Result->Entry.Parent.Item = Result; + + Result->Entry.IndexerFields = InitBook(sizeof(db_structure_indexer), 4); + } + + Result->IndexedIntoBy = InitBook(sizeof(db_structure_item), 4); + return Result; +} + +db_structure_headered_section * +InitDBHeaderedSection(db_structure_block *B, memory_book *Strings, + char *Name, uint32_t SizeOf, + char *EntryCountName, uint32_t EntryCountOffset, uint32_t EntryCountSizeOf, + char *ChildCountName, uint32_t ChildCountOffset, uint32_t ChildCountSizeOf, + char *EntryDataTypeName, uint32_t EntrySizeOf) +{ + db_structure_headered_section *Result = &B->HeaderedSection; + Result->Self.Name = WriteStringInBook(Strings, Wrap0(Name)); + Result->Self.SizeOf = SizeOf; + + if(EntryCountSizeOf) + { + Result->EntryCount = PackDBStructureField(WriteStringInBook(Strings, Wrap0(EntryCountName)), + EntryCountOffset, EntryCountSizeOf); + Result->Entry.Name = WriteStringInBook(Strings, Wrap0(EntryDataTypeName)); + Result->Entry.SizeOf = EntrySizeOf; + + Result->Entry.Parent.Type = DBS_HEADERED_SECTION; + Result->Entry.Parent.Item = Result; + + Result->Entry.IndexerFields = InitBook(sizeof(db_structure_indexer), 4); + } + + if(ChildCountSizeOf) + { + Result->ChildCount = PackDBStructureField(WriteStringInBook(Strings, Wrap0(ChildCountName)), + ChildCountOffset, ChildCountSizeOf); + } + + Result->IndexedIntoBy = InitBook(sizeof(db_structure_item), 4); + Result->Self.IndexerFields = InitBook(sizeof(db_structure_indexer), 4); + Result->Parent.Type = DBS_BLOCK; + Result->Parent.Item = B; + return Result; +} + +db_structure_indexer * +DBStructureAddIndexerField(db_structure_datatype *D, memory_book *Strings, + db_structure_item_type ParentType, + char *Name, uint32_t Offset, uint32_t SizeOf, db_structure_indexer_type Type) +{ + db_structure_indexer *Result = MakeSpaceInBook(&D->IndexerFields); + Result->Field.Name = WriteStringInBook(Strings, Wrap0(Name)); + Result->Field.Offset = Offset; + Result->Field.SizeOf = SizeOf; + Result->Type = Type; + Result->Field.Parent.Type = ParentType; + Result->Field.Parent.Item = D; + return Result; +} + +void +BlockIsIndexedIntoBy(db_structure_block *B, db_structure_item_type Type, void *Indexer) +{ + db_structure_item *New = MakeSpaceInBook(&B->IndexedIntoBy); + New->Type = Type; + New->Item = Indexer; +} + +void +HeaderedSectionIsIndexedIntoBy(db_structure_headered_section *H, db_structure_item_type Type, void *Indexer) +{ + db_structure_item *New = MakeSpaceInBook(&H->IndexedIntoBy); + New->Type = Type; + New->Item = Indexer; +} + +void +InitDBStructure4(void) +{ + db_structure *S = MakeSpaceInBook(&DBStructures.Structure); + memory_book *Strings = &DBStructures.Strings; + + S->Version = 4; + S->Header.HexSignature = FOURCC("CNRA"); + S->Header.SizeOf = sizeof(db_header4); + db_header4 db_header4_; + S->Header.BlockCount = PackDBStructureField( + WriteStringInBook(Strings, Wrap0("BlockCount")), + offsetof(db_header4, BlockCount), + sizeof(db_header4_.BlockCount)); + + S->Blocks = InitBook(sizeof(db_structure_block), 4); + + db_header_entries4 db_header_entries4_; + db_structure_block *BlockNTRY = InitDBStructureBlock(S, Strings, + "NTRY", sizeof(db_header_entries4_), + "Count", offsetof(db_header_entries4, Count), sizeof(db_header_entries4_.Count), + "db_entry4", sizeof(db_entry4)); + + db_header_assets4 db_header_assets4_; + db_structure_block *BlockASET = InitDBStructureBlock(S, Strings, + "ASET", sizeof(db_header_assets4_), + "Count", offsetof(db_header_assets4, Count), sizeof(db_header_assets4_.Count), + 0, 0); + + db_asset4 db_asset4_; + db_structure_headered_section *HeaderAssets = InitDBHeaderedSection(BlockASET, Strings, + "db_asset4", sizeof(db_asset4_), + "LandmarkCount", offsetof(db_asset4, LandmarkCount), sizeof(db_asset4_.LandmarkCount), + 0, 0, 0, + "db_landmark4", sizeof(db_landmark4)); + + BlockIsIndexedIntoBy(BlockNTRY, DBS_ENTRY, &HeaderAssets->Entry); +} + +db_structure * +InitDBStructure5(void) +{ + db_structure *S = MakeSpaceInBook(&DBStructures.Structure); + memory_book *Strings = &DBStructures.Strings; + + S->Version = 5; + S->Header.HexSignature = FOURCC("CNRA"); + S->Header.SizeOf = sizeof(db_header5); + db_header5 db_header5_; + S->Header.BlockCount = PackDBStructureField( + WriteStringInBook(Strings, Wrap0("BlockCount")), + offsetof(db_header5, BlockCount), + sizeof(db_header5_.BlockCount)); + + S->Blocks = InitBook(sizeof(db_structure_block), 4); + + db_block_projects5 db_block_projects5_; + db_structure_block *BlockPROJ = InitDBStructureBlock(S, Strings, + "PROJ", sizeof(db_block_projects5_), + "Count", offsetof(db_block_projects5, Count), sizeof(db_block_projects5_.Count), + 0, 0); + + db_header_project5 db_header_project5_; + db_structure_headered_section *HeaderProjects = InitDBHeaderedSection(BlockPROJ, Strings, + "db_header_project5", sizeof(db_header_project5_), + "EntryCount", offsetof(db_header_project5, EntryCount), sizeof(db_header_project5_.EntryCount), + "ChildCount", offsetof(db_header_project5, ChildCount), sizeof(db_header_project5_.ChildCount), + "db_entry5", sizeof(db_entry5)); + + db_structure_indexer *ProjectsArtIndex = DBStructureAddIndexerField(&HeaderProjects->Self, Strings, + DBS_HEADERED_SECTION, + "ArtIndex", offsetof(db_header_project5, ArtIndex), sizeof(db_header_project5_.ArtIndex), + IDX_SINGLE); + + db_structure_indexer *ProjectsIconIndex = DBStructureAddIndexerField(&HeaderProjects->Self, Strings, + DBS_HEADERED_SECTION, + "IconIndex", offsetof(db_header_project5, IconIndex), sizeof(db_header_project5_.IconIndex), + IDX_SINGLE); + + db_entry5 db_entry5_; + db_structure_indexer *EntryArtIndex = DBStructureAddIndexerField(&HeaderProjects->Entry, Strings, + DBS_ENTRY, + "ArtIndex", offsetof(db_entry5, ArtIndex), sizeof(db_entry5_.ArtIndex), + IDX_SINGLE); + + + db_block_assets5 db_block_assets5_; + db_structure_block *BlockASET = InitDBStructureBlock(S, Strings, + "ASET", sizeof(db_block_assets5_), + "Count", offsetof(db_block_assets5, Count), sizeof(db_block_assets5_.Count), + 0, 0); + + db_asset5 db_asset5_; + db_structure_headered_section *HeaderAssets = InitDBHeaderedSection(BlockASET, Strings, + "db_asset5", sizeof(db_asset5_), + "LandmarkCount", offsetof(db_asset5, LandmarkCount), sizeof(db_asset5_.LandmarkCount), + 0, 0, 0, + "db_landmark5", sizeof(db_landmark5)); + + db_landmark5 db_landmark5_; + db_structure_indexer *LandmarkProjectAndEntryIndex = DBStructureAddIndexerField(&HeaderAssets->Entry, Strings, + DBS_ENTRY, + "Index", offsetof(db_landmark5, Index), sizeof(db_landmark5_.Index), + IDX_COMPOUND); + + BlockIsIndexedIntoBy(BlockPROJ, DBS_INDEXER_FIELD, LandmarkProjectAndEntryIndex); + HeaderedSectionIsIndexedIntoBy(HeaderProjects, DBS_INDEXER_FIELD, LandmarkProjectAndEntryIndex); + + BlockIsIndexedIntoBy(BlockASET, DBS_INDEXER_FIELD, ProjectsArtIndex); + BlockIsIndexedIntoBy(BlockASET, DBS_INDEXER_FIELD, ProjectsIconIndex); + BlockIsIndexedIntoBy(BlockASET, DBS_INDEXER_FIELD, EntryArtIndex); + return S; +} + +void +InitDBStructures(void) +{ + DBStructures.Structure = InitBook(sizeof(db_structure), 4); + DBStructures.Strings = InitBookOfStrings(Kilobytes(4)); + + InitDBStructure4(); + CurrentDBStructure = InitDBStructure5(); +} + +uint64_t +ReadDBField(void *ParentInDB, db_structure_field F) +{ + uint64_t Result = 0; + char *Ptr = ParentInDB; + Ptr += F.Offset; + memcpy(&Result, Ptr, F.SizeOf); + return Result; +} + +db_structure_block * +GetDBStructureBlock(uint32_t BlockID) +{ + // NOTE(matt): Usage: To use an older database version, temporarily set CurrentDBStructure before calling this function + db_structure_block *Result = 0; + for(int i = 0; i < CurrentDBStructure->Blocks.ItemCount; ++i) + { + db_structure_block *This = GetPlaceInBook(&CurrentDBStructure->Blocks, i); + if(This->ID == BlockID) + { + Result = This; + break; + } + } + return Result; +} + +db_structure_headered_section * +GetDBStructureHeaderedSection(block_id BlockID) +{ + // NOTE(matt): Usage: To use an older database version, temporarily set CurrentDBStructure before calling this function + return &GetDBStructureBlock(GetFourFromBlockID(BlockID))->HeaderedSection; +} + +void +PrintFour(FILE *Dest, uint32_t Four) +{ + Colourise(CS_YELLOW); + fprintf(Dest, "%c%c%c%c", Four, Four >> 8, Four >> 16, Four >> 24); + Colourise(CS_END); +} + +void +PrintDBStructureDataType(FILE *Dest, db_structure_datatype DataType) +{ + fprintf(Dest, "%s%.*s%s (%s%u%s byte%s)", + ColourStrings[CS_MAGENTA], (int)DataType.Name.Length, DataType.Name.Base, ColourStrings[CS_END], + ColourStrings[CS_BLUE_BOLD], DataType.SizeOf, ColourStrings[CS_END], + DataType.SizeOf == 1 ? "" : "s"); +} + +void +TypesetDBStructureField(FILE *Dest, int IndentLevel, db_structure_field Field) +{ + if(Field.SizeOf) + { + IndentedCarriageReturn(IndentLevel); + fprintf(Dest, "%s%.*s%s: %s%u%s byte%s wide @ %s%u%s-byte offset", + ColourStrings[CS_GREEN], (int)Field.Name.Length, Field.Name.Base, ColourStrings[CS_END], + ColourStrings[CS_BLUE_BOLD], Field.SizeOf, ColourStrings[CS_END], + Field.SizeOf == 1 ? "" : "s", + ColourStrings[CS_BLUE_BOLD], Field.Offset, ColourStrings[CS_END]); + } +} + +void +PrintDBBlockIDandSize(FILE *Dest, int IndentLevel, uint32_t ID, uint32_t SizeOf) +{ + PrintFour(Dest, ID); + fprintf(Dest, " (%s%u%s bytes)", ColourStrings[CS_BLUE_BOLD], SizeOf, ColourStrings[CS_END]); +} + +void +PrintDBStructureHeader(FILE *Dest, int IndentLevel, db_structure_header *Header) +{ + IndentedCarriageReturn(IndentLevel); + PrintDBBlockIDandSize(Dest, IndentLevel, Header->HexSignature, Header->SizeOf); + + ++IndentLevel; + TypesetDBStructureField(Dest, IndentLevel, Header->BlockCount); + + --IndentLevel; +} + +typedef struct +{ + string *Name; + db_structure_item_type StructuralItemType; + db_structure_indexer_type IndexerType; +} db_indexer_name_and_type; + +void +PrintDBStructureItemLineage(FILE *Dest, db_structure_item *Item) +{ + db_structure_item *This = Item; + memory_book Lineage = InitBook(sizeof(db_indexer_name_and_type), 4); + while(This) + { + db_indexer_name_and_type *New = MakeSpaceInBook(&Lineage); + New->StructuralItemType = This->Type; + switch(This->Type) + { + case DBS_BLOCK: + { + db_structure_block *It = (db_structure_block *)This->Item; + New->Name = &It->PrintableName; + This = 0; + } break; + case DBS_ENTRY: + { + db_structure_datatype *It = (db_structure_datatype *)This->Item; + New->Name = &It->Name; + This = &It->Parent; + } break; + case DBS_HEADERED_SECTION: + { + db_structure_headered_section *It = (db_structure_headered_section *)This->Item; + New->Name = &It->Self.Name; + This = &It->Parent; + } break; + case DBS_INDEXER_FIELD: + { + db_structure_indexer *It = (db_structure_indexer *)This->Item; + New->Name = &It->Field.Name; + New->IndexerType = It->Type; + This = &It->Field.Parent; + } break; + } + } + + + db_indexer_name_and_type *Cursor = GetPlaceInBook(&Lineage, Lineage.ItemCount - 1); + PrintString(*Cursor->Name); + for(int i = Lineage.ItemCount - 2; i >= 0; --i) + { + Cursor = GetPlaceInBook(&Lineage, i); + fprintf(Dest, "%s", Cursor->StructuralItemType == DBS_INDEXER_FIELD ? "." : "/"); + PrintString(*Cursor->Name); + if(Cursor->IndexerType == IDX_COMPOUND) + { + fprintf(Dest, " [compound]"); + } + } + + FreeBook(&Lineage); +} + +void +TypesetIndexers(FILE *Dest, int IndentLevel, memory_book *IndexedIntoBy) +{ + if(IndexedIntoBy->ItemCount) + { + IndentedCarriageReturn(IndentLevel); + Colourise(CS_YELLOW_BOLD); + fprintf(Dest, "╿ is indexed into by:"); + for(int i = 0; i < IndexedIntoBy->ItemCount - 1; ++i) + { + IndentedCarriageReturn(IndentLevel); + db_structure_item *This = GetPlaceInBook(IndexedIntoBy, i); + fprintf(Dest, "├── "); + PrintDBStructureItemLineage(Dest, This); + } + + IndentedCarriageReturn(IndentLevel); + db_structure_item *This = GetPlaceInBook(IndexedIntoBy, IndexedIntoBy->ItemCount - 1); + fprintf(Dest, "└── "); + PrintDBStructureItemLineage(Dest, This); + Colourise(CS_END); + } +} + +void +PrintDBStructureHeaderedSection(FILE *Dest, int IndentLevel, db_structure_headered_section *H) +{ + IndentedCarriageReturn(IndentLevel); + PrintDBStructureDataType(Dest, H->Self); + + ++IndentLevel; + + TypesetDBStructureField(Dest, IndentLevel, H->EntryCount); + TypesetIndexers(Dest, IndentLevel, &H->IndexedIntoBy); + TypesetDBStructureField(Dest, IndentLevel, H->ChildCount); + + IndentedCarriageReturn(IndentLevel); + PrintDBStructureDataType(Dest, H->Entry); + + --IndentLevel; +} + +void +PrintDBStructureBlock(FILE *Dest, int IndentLevel, db_structure_block *Block) +{ + IndentedCarriageReturn(IndentLevel); + PrintFour(Dest, Block->ID); + fprintf(Dest, " (%s%u%s bytes)", ColourStrings[CS_BLUE_BOLD], Block->SizeOf, ColourStrings[CS_END]); + + ++IndentLevel; + TypesetDBStructureField(Dest, IndentLevel, Block->Count); + TypesetIndexers(Dest, IndentLevel, &Block->IndexedIntoBy); + + if(Block->HeaderedSection.Self.SizeOf) + { + PrintDBStructureHeaderedSection(Dest, IndentLevel, &Block->HeaderedSection); + } + + if(Block->Entry.SizeOf) + { + IndentedCarriageReturn(IndentLevel); + PrintDBStructureDataType(Dest, Block->Entry); + } + + --IndentLevel; +} + +void +PrintDBStructure(FILE *Dest, int IndentLevel, db_structure *S) +{ + IndentedCarriageReturn(IndentLevel); + fprintf(Dest, "Version %s%u%s", ColourStrings[CS_MAGENTA_BOLD], S->Version, ColourStrings[CS_END]); + PrintDBStructureHeader(Dest, IndentLevel, &S->Header); + + ++IndentLevel; + for(int i = 0; i < S->Blocks.ItemCount; ++i) + { + db_structure_block *Block = GetPlaceInBook(&S->Blocks, i); + PrintDBStructureBlock(Dest, IndentLevel, Block); + } + --IndentLevel; +} + +void +PrintDBStructures(FILE *Dest) +{ + int IndentLevel = 0; + for(int i = 0; i < DBStructures.Structure.ItemCount; ++i) + { + db_structure *S = GetPlaceInBook(&DBStructures.Structure, i); + PrintDBStructure(Dest, IndentLevel, S); + } + fprintf(Dest, "\n"); +} + typedef struct { buffer_id BufferID; @@ -3445,8 +4041,8 @@ ClaimBuffer(buffer *Buffer, buffer_id ID, int Size) Buffer->Ptr = Buffer->Location; #if DEBUG float PercentageUsed = (float)(MemoryArena.Ptr - MemoryArena.Location) / MemoryArena.Size * 100; - printf(" ClaimBuffer(%s): %d\n" - " Total ClaimedMemory: %ld (%.2f%%, leaving %ld free)\n\n", Buffer->ID, Buffer->Size, MemoryArena.Ptr - MemoryArena.Location, PercentageUsed, MemoryArena.Size - (MemoryArena.Ptr - MemoryArena.Location)); + printf(" ClaimBuffer(%s): %ld\n" + " Total ClaimedMemory: %ld (%.2f%%, leaving %ld free)\n\n", BufferIDStrings[Buffer->ID], Buffer->Size, MemoryArena.Ptr - MemoryArena.Location, PercentageUsed, MemoryArena.Size - (MemoryArena.Ptr - MemoryArena.Location)); #endif return RC_SUCCESS; } @@ -3459,10 +4055,10 @@ DeclaimBuffer(buffer *Buffer) float PercentageUsed = (float)(Buffer->Ptr - Buffer->Location) / Buffer->Size * 100; #if DEBUG printf("DeclaimBuffer(%s)\n" - " Used: %ld / %d (%.2f%%)\n" + " Used: %li / %ld (%.2f%%)\n" "\n" " Total ClaimedMemory: %ld\n\n", - Buffer->ID, + BufferIDStrings[Buffer->ID], Buffer->Ptr - Buffer->Location, Buffer->Size, PercentageUsed, @@ -3499,8 +4095,8 @@ RewindBuffer(buffer *Buffer) #if DEBUG float PercentageUsed = (float)(Buffer->Ptr - Buffer->Location) / Buffer->Size * 100; printf("Rewinding %s\n" - " Used: %ld / %d (%.2f%%)\n\n", - Buffer->ID, + " Used: %ld / %ld (%.2f%%)\n\n", + BufferIDStrings[Buffer->ID], Buffer->Ptr - Buffer->Location, Buffer->Size, PercentageUsed); @@ -4675,7 +5271,7 @@ GetIndexRangeLength(db_asset *A, landmark_range ProjectRange, uint64_t LandmarkI uint32_t Result = 0; db_landmark *FirstLandmarkOfRange = LocateLandmark(A, LandmarkIndex); db_landmark *Landmark = FirstLandmarkOfRange; - while(LandmarkIndex < (ProjectRange.First + ProjectRange.Length) && ProjectIndicesMatch(FirstLandmarkOfRange->Project, Landmark->Project) && FirstLandmarkOfRange->EntryIndex == Landmark->EntryIndex) + while(LandmarkIndex < (ProjectRange.First + ProjectRange.Length) && ProjectIndicesMatch(FirstLandmarkOfRange->Index.Project, Landmark->Index.Project) && FirstLandmarkOfRange->Index.Entry == Landmark->Index.Entry) { ++Result; ++LandmarkIndex; @@ -4693,13 +5289,13 @@ GetIndexRange(db_asset *A, landmark_range ProjectRange, uint64_t LandmarkIndex) db_landmark *LandmarkInRange = LocateLandmark(A, LandmarkIndex); db_landmark *Landmark = LandmarkInRange; - while(Result.First > ProjectRange.First && ProjectIndicesMatch(LandmarkInRange->Project, Landmark->Project) && LandmarkInRange->EntryIndex == Landmark->EntryIndex) + while(Result.First > ProjectRange.First && ProjectIndicesMatch(LandmarkInRange->Index.Project, Landmark->Index.Project) && LandmarkInRange->Index.Entry == Landmark->Index.Entry) { --Result.First; --Landmark; } - if(LandmarkInRange->EntryIndex != Landmark->EntryIndex) + if(LandmarkInRange->Index.Entry != Landmark->Index.Entry) { ++Result.First; } @@ -4739,7 +5335,7 @@ BinarySearchForMetadataLandmark(db_asset *Asset, landmark_range ProjectRange, in uint64_t Upper = Lower + ProjectRange.Length - 1; db_landmark *UpperLandmark = FirstLandmark + Upper; - if(EntryIndex < LowerLandmark->EntryIndex) + if(EntryIndex < LowerLandmark->Index.Entry) { Result.First = Lower; Result.Length = 0; @@ -4747,7 +5343,7 @@ BinarySearchForMetadataLandmark(db_asset *Asset, landmark_range ProjectRange, in } // TODO(matt): Is there a slicker way of doing this? - if(EntryIndex > UpperLandmark->EntryIndex) + if(EntryIndex > UpperLandmark->Index.Entry) { Result.First = Upper + 1; Result.Length = 0; @@ -4762,22 +5358,22 @@ BinarySearchForMetadataLandmark(db_asset *Asset, landmark_range ProjectRange, in PivotLandmark = FirstLandmark + Pivot; UpperLandmark = FirstLandmark + Upper; - if(EntryIndex == LowerLandmark->EntryIndex) + if(EntryIndex == LowerLandmark->Index.Entry) { return GetIndexRange(Asset, ProjectRange, Lower); } - if(EntryIndex == PivotLandmark->EntryIndex) + if(EntryIndex == PivotLandmark->Index.Entry) { return GetIndexRange(Asset, ProjectRange, Pivot); } - if(EntryIndex == UpperLandmark->EntryIndex) + if(EntryIndex == UpperLandmark->Index.Entry) { return GetIndexRange(Asset, ProjectRange, Upper); } - if(EntryIndex < PivotLandmark->EntryIndex) { Upper = Pivot; } + if(EntryIndex < PivotLandmark->Index.Entry) { Upper = Pivot; } else { Lower = Pivot; } Pivot = Upper - ((Upper - Lower) >> 1); } while(Upper > Pivot); @@ -4805,7 +5401,7 @@ PrintLandmark(db_landmark *L, uint16_t *Index) fprintf(stderr, "[%4u] ", *Index); Colourise(CS_END); } - PrintEntryIndex(L->Project, L->EntryIndex); + PrintEntryIndex(L->Index.Project, L->Index.Entry); fprintf(stderr, " %6u", L->Position); } @@ -4894,24 +5490,23 @@ SnipeChecksumAndCloseFile(file *HTMLFile, db_asset *Asset, int LandmarksInFile, FreeFile(HTMLFile, NA); } -// TODO(matt): Bounds-check the Metadata.File.Buffer void * -SkipAsset(db_asset *Asset) +SkipHeaderedSection(void *LocationInDB, db_structure_headered_section *Structure) { - char *Ptr = (char *)Asset; - Ptr += sizeof(db_asset) + sizeof(db_landmark) * Asset->LandmarkCount; + char *Ptr = LocationInDB; + uint64_t Count = ReadDBField(LocationInDB, Structure->EntryCount); + Ptr += Structure->Self.SizeOf + Structure->Entry.SizeOf * Count; return Ptr; } void * -SkipAssetsBlock(db_block_assets *Block) +SkipHeaderedSectionRecursively(void *LocationInDB, db_structure_headered_section *Structure) { - char *Ptr = (char *)Block; - Ptr += sizeof(db_block_assets); - for(int i = 0; i < Block->Count; ++i) + uint64_t ChildCount = ReadDBField(LocationInDB, Structure->ChildCount); + char *Ptr = SkipHeaderedSection(LocationInDB, Structure); + for(int i = 0; i < ChildCount; ++i) { - db_asset *Asset = (db_asset *)Ptr; - Ptr = SkipAsset(Asset); + Ptr = SkipHeaderedSectionRecursively(Ptr, Structure); } return Ptr; } @@ -4971,70 +5566,29 @@ PrintGenerations(project_generations *G, bool IndicateCurrentGeneration) } } -void * -SkipProject(db_header_project *Project) -{ - char *Ptr = (char *)Project; - Ptr += sizeof(db_header_project) + sizeof(db_entry) * Project->EntryCount; - return Ptr; -} - -void * -SkipProjectAndChildren(db_header_project *Project) -{ - db_header_project *Ptr = SkipProject(Project); - for(int i = 0; i < Project->ChildCount; ++i) - { - Ptr = SkipProjectAndChildren(Ptr); - } - return Ptr; -} - -void * -SkipProjectsBlock(db_block_projects *Block) -{ - char *Ptr = (char *)Block; - Ptr += sizeof(db_block_projects); - for(int i = 0; i < Block->Count; ++i) - { - db_header_project *Project = (db_header_project *)Ptr; - Ptr = SkipProjectAndChildren(Project); - } - return Ptr; -} - -typedef enum -{ - B_ASET, - B_PROJ, -} block_id; - -uint32_t -GetFourFromBlockID(block_id ID) -{ - switch(ID) - { - case B_ASET: return FOURCC("ASET"); - case B_PROJ: return FOURCC("PROJ"); - } - return 0; -} - void * SkipBlock(void *Block) { void *Result = 0; uint32_t FirstInt = *(uint32_t *)Block; - if(FirstInt == GetFourFromBlockID(B_PROJ)) + db_structure_block *BlockStructure = GetDBStructureBlock(FirstInt); + Assert(BlockStructure); + + Result = (char *)Block; + Result += BlockStructure->SizeOf; + uint64_t Count = ReadDBField(Block, BlockStructure->Count); + if(BlockStructure->Entry.SizeOf) { - Result = SkipProjectsBlock(Block); + Result += BlockStructure->Entry.SizeOf * Count; } - else if(FirstInt == GetFourFromBlockID(B_ASET)) + else { - Result = SkipAssetsBlock(Block); + for(int i = 0; i < Count; ++i) + { + Result = SkipHeaderedSectionRecursively(Result, &BlockStructure->HeaderedSection); + } } - Assert(Result); return Result; } @@ -5081,6 +5635,7 @@ LocateFirstChildProject(db_header_project *P) db_header_project * LocateProjectRecursively(db_header_project *Header, db_project_index *DesiredProject, db_project_index *Accumulator) { + db_header_project *Result = 0; db_header_project *Child = LocateFirstChildProject(Header); for(int i = 0; i < Header->ChildCount; ++i) @@ -5089,7 +5644,8 @@ LocateProjectRecursively(db_header_project *Header, db_project_index *DesiredPro { if(Accumulator->Index == DesiredProject->Index) { - return Child; + Result = Child; + break; } else { @@ -5101,17 +5657,35 @@ LocateProjectRecursively(db_header_project *Header, db_project_index *DesiredPro db_header_project *Test = LocateProjectRecursively(Child, DesiredProject, Accumulator); if(Test) { - return Test; + Result = Test; + break; } --Accumulator->Generation; - Child = SkipProjectAndChildren(Child); + Child = SkipHeaderedSectionRecursively(Child, GetDBStructureHeaderedSection(B_PROJ)); } - return 0; + return Result; +} + +db_structure * +GetDBStructure(uint32_t Version) +{ + db_structure *Result = 0; + for(int i = 0; i < DBStructures.Structure.ItemCount; ++i) + { + db_structure *This = GetPlaceInBook(&DBStructures.Structure, i); + if(This->Version == Version) + { + Result = This; + break; + } + } + return Result; } db_header_project * LocateProject(db_project_index Project) { + db_header_project *Result = 0; if(Project.Generation != -1) { db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr ? DB.Metadata.Signposts.ProjectsBlock.Ptr : LocateBlock(B_PROJ); @@ -5120,15 +5694,17 @@ LocateProject(db_project_index Project) db_project_index Accumulator = {}; if(ProjectsBlock) { + db_structure_headered_section *DBStructureProjects = GetDBStructureHeaderedSection(B_PROJ); if(Project.Generation == Accumulator.Generation) { for(int i = 0; i < ProjectsBlock->Count; ++i) { if(Project.Index == Accumulator.Index) { - return Child; + Result = Child; + break; } - Child = SkipProjectAndChildren(Child); + Child = SkipHeaderedSectionRecursively(Child, DBStructureProjects); ++Accumulator.Index; } } @@ -5140,15 +5716,16 @@ LocateProject(db_project_index Project) db_header_project *Test = LocateProjectRecursively(Child, &Project, &Accumulator); if(Test) { - return Test; + Result = Test; + break; } - Child = SkipProjectAndChildren(Child); + Child = SkipHeaderedSectionRecursively(Child, DBStructureProjects); } --Accumulator.Generation; } } } - return 0; + return Result; } db_entry * @@ -5258,7 +5835,7 @@ PrintAssetsBlock_(db_block_assets *B, int LineNumber) for(uint16_t i = 0; i < B->Count; ++i) { PrintAssetAndLandmarks(A, &i); - A = SkipAsset(A); + A = SkipHeaderedSectionRecursively(A, GetDBStructureHeaderedSection(B_ASET)); } return A; } @@ -5303,11 +5880,19 @@ ReadSearchPageIntoBuffer(file *File, string *BaseDir, string *SearchLocation) return ReadFileIntoBuffer(File); } +string +GetGlobalSearchPageLocation(void) +{ + string Result = {}; + db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr ? DB.Metadata.Signposts.ProjectsBlock.Ptr : LocateBlock(B_PROJ); + Result = Wrap0i(ProjectsBlock->GlobalSearchDir); + return Result; +} + rc ReadGlobalSearchPageIntoBuffer(file *File) { - db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr ? DB.Metadata.Signposts.ProjectsBlock.Ptr : LocateBlock(B_PROJ); - string SearchLocationL = Wrap0i(ProjectsBlock->GlobalSearchDir); + string SearchLocationL = GetGlobalSearchPageLocation(); File->Path = ConstructHTMLIndexFilePath(0, &SearchLocationL, 0); return ReadFileIntoBuffer(File); } @@ -5330,13 +5915,13 @@ SnipeChecksumIntoHTML(db_asset *Asset, asset_hash Checksum) { db_landmark *Landmark = FirstLandmark + RunningLandmarkIndex; // TODO(matt): Do the Next vs Current Project check to see whether we even need to do LocateProject() - db_header_project *P = LocateProject(Landmark->Project); + db_header_project *P = LocateProject(Landmark->Index.Project); file HTML = {}; rc FileReadRC = RC_INIT; - if(Landmark->EntryIndex >= 0) + if(Landmark->Index.Entry >= 0) { - db_entry *Entry = LocateEntry(Landmark->Project, Landmark->EntryIndex); + db_entry *Entry = LocateEntry(Landmark->Index.Project, Landmark->Index.Entry); if(Entry) { string BaseDir = Wrap0i(P->BaseDir); @@ -5355,7 +5940,7 @@ SnipeChecksumIntoHTML(db_asset *Asset, asset_hash Checksum) } else { - switch(Landmark->EntryIndex) + switch(Landmark->Index.Entry) { case SP_SEARCH: { @@ -5373,7 +5958,7 @@ SnipeChecksumIntoHTML(db_asset *Asset, asset_hash Checksum) default: { Colourise(CS_RED); - fprintf(stderr, "SnipeChecksumIntoHTML() does not know about special page with index %i\n", Landmark->EntryIndex); + fprintf(stderr, "SnipeChecksumIntoHTML() does not know about special page with index %i\n", Landmark->Index.Entry); Colourise(CS_END); Assert(0); } break; @@ -5842,7 +6427,7 @@ LocateAsset(db_block_assets *Block, asset *Asset, int *Index) Result = StoredAsset; break; } - Ptr = SkipAsset(StoredAsset); + Ptr = SkipHeaderedSectionRecursively(StoredAsset, GetDBStructureHeaderedSection(B_ASET)); } return Result; } @@ -5883,7 +6468,7 @@ WriteEntireDatabase(neighbourhood *N) int UpdateAssetInDB(asset *Asset) { - MEM_TEST_TOP("UpdateAssetInDB"); + MEM_TEST_TOP(); int AssetIndexInDB = SAI_UNSET; if(Config->QueryString.Length > 0) { @@ -5899,23 +6484,30 @@ UpdateAssetInDB(asset *Asset) if(StoredAsset) { - StoredAsset->Associated = Asset->Associated; - StoredAsset->Variants = Asset->Variants; - StoredAsset->Width = Asset->Dimensions.Width; - StoredAsset->Height = Asset->Dimensions.Height; + if(StoredAsset->Associated != Asset->Associated || + StoredAsset->Variants != Asset->Variants || + StoredAsset->Width != Asset->Dimensions.Width || + StoredAsset->Height != Asset->Dimensions.Height) + { + StoredAsset->Associated = Asset->Associated; + StoredAsset->Variants = Asset->Variants; + StoredAsset->Width = Asset->Dimensions.Width; + StoredAsset->Height = Asset->Dimensions.Height; + } if(StoredAsset->Hash != Asset->Hash) { + // NOTE(matt): Extra-db code start char OldChecksum[16]; ClearCopyString(OldChecksum, sizeof(OldChecksum), "%08x", StoredAsset->Hash); char NewChecksum[16]; ClearCopyString(NewChecksum, sizeof(NewChecksum), "%08x", Asset->Hash); + // NOTE(matt): Extra-db code end StoredAsset->Hash = Asset->Hash; - char *Ptr = (char *)Asset; - Ptr += sizeof(*Asset); + // NOTE(matt): Extra-db code start file AssetFile = {}; AssetFile.Path = ConstructAssetPath(&AssetFile, Wrap0i(StoredAsset->Filename), StoredAsset->Type); ResolvePath(&AssetFile.Path); @@ -5938,14 +6530,15 @@ UpdateAssetInDB(asset *Asset) } FreeString(&Message); + // NOTE(matt): Extra-db code end OpenFileForWriting(&DB.Metadata.File); fwrite(DB.Metadata.File.Buffer.Location, DB.Metadata.File.Buffer.Size, 1, DB.Metadata.File.Handle); SetFileEditPosition(&DB.Metadata); CycleSignpostedFile(&DB.Metadata); - Asset->DeferredUpdate = FALSE; } + Asset->DeferredUpdate = FALSE; } else { @@ -5984,7 +6577,7 @@ UpdateAssetInDB(asset *Asset) Asset->Known = TRUE; } } - MEM_TEST_END("UpdateAssetInDB"); + MEM_TEST_END(); return AssetIndexInDB; } @@ -6223,7 +6816,7 @@ InitAssets(void) for(int i = 0; i < AssetsBlock->Count; ++i) { PushAsset(Wrap0i(Asset->Filename), Asset->Type, Asset->Variants, Asset->Associated); - Asset = SkipAsset(Asset); + Asset = SkipHeaderedSectionRecursively(Asset, GetDBStructureHeaderedSection(B_ASET)); } } } @@ -6466,7 +7059,7 @@ ConfirmAssociationsOfProject(db_header_project *Project, asset *Asset, db_asset Child = ConfirmAssociationsOfProject(Child, Asset, AssetInDB, Index); } - return SkipProjectAndChildren(Project); + return SkipHeaderedSectionRecursively(Child, GetDBStructureHeaderedSection(B_PROJ)); } void @@ -6496,7 +7089,7 @@ LocateAssetByIndex(uint16_t Index) Result = This; break; } - This = SkipAsset(This); + This = SkipHeaderedSectionRecursively(This, GetDBStructureHeaderedSection(B_ASET)); } return Result; } @@ -7379,7 +7972,7 @@ CurlIntoBuffer(char *InPtr, size_t CharLength, size_t Chars, char **OutputPtr) CURLcode CurlQuotes(buffer *QuoteStaging, char *QuotesURL) { - MEM_TEST_TOP("CurlQuotes()"); + MEM_TEST_TOP(); fprintf(stderr, "%sFetching%s quotes: %s\n", ColourStrings[CS_ONGOING], ColourStrings[CS_END], QuotesURL); CURLcode Result = CURLE_FAILED_INIT; @@ -7388,9 +7981,9 @@ CurlQuotes(buffer *QuoteStaging, char *QuotesURL) curl_easy_setopt(curl, CURLOPT_WRITEDATA, &QuoteStaging->Ptr); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlIntoBuffer); curl_easy_setopt(curl, CURLOPT_URL, QuotesURL); - /* */ MEM_TEST_MID("CurlQuotes()"); + /* */ MEM_TEST_MID(); /* +MEM */ Result = curl_easy_perform(curl); - /* */ MEM_TEST_MID("CurlQuotes()"); + /* */ MEM_TEST_MID(); if(Result) { fprintf(stderr, "%s\n", curl_easy_strerror(Result)); @@ -7398,7 +7991,7 @@ CurlQuotes(buffer *QuoteStaging, char *QuotesURL) curl_easy_cleanup(curl); curl = 0; } - MEM_TEST_END("CurlQuotes()"); + MEM_TEST_END(); return Result; } @@ -7482,7 +8075,7 @@ SearchQuotes(memory_book *Strings, buffer *QuoteStaging, int CacheSize, quote_in rc BuildQuote(memory_book *Strings, quote_info *Info, string Speaker, int ID, bool ShouldFetchQuotes) { - MEM_TEST_TOP("BuildQuote()"); + MEM_TEST_TOP(); rc Result = RC_SUCCESS; // TODO(matt): Suss out the Speaker more sensibly if(Speaker.Length > 0) @@ -7562,9 +8155,9 @@ BuildQuote(memory_book *Strings, quote_info *Info, string Speaker, int ID, bool if(ShouldFetchQuotes) { QuoteStaging.Ptr = QuoteStaging.Location; - /* */ MEM_TEST_MID("BuildQuote()"); + /* */ MEM_TEST_MID(); /* +MEM */ CURLcode CurlQuotesResult = CurlQuotes(&QuoteStaging, QuotesURL); - /* */ MEM_TEST_MID("BuildQuote()"); + /* */ MEM_TEST_MID(); if(CurlQuotesResult == CURLE_OK) { LastQuoteFetch = time(0); @@ -7591,7 +8184,7 @@ BuildQuote(memory_book *Strings, quote_info *Info, string Speaker, int ID, bool if(CacheAvailable) { fclose(QuoteCache); } } - MEM_TEST_END("BuildQuote()"); + MEM_TEST_END(); } return Result; } @@ -7862,8 +8455,9 @@ enable syntax highlighting:")); fprintf(stderr, "\n"); } +#define PrintHelp() PrintHelp_(Args[0], ConfigPath) void -PrintHelp(char *BinaryLocation, char *DefaultConfigPath) +PrintHelp_(char *BinaryLocation, char *DefaultConfigPath) { // Options fprintf(stderr, @@ -7886,7 +8480,7 @@ PrintHelp(char *BinaryLocation, char *DefaultConfigPath) } void -PrintHelp_(char *BinaryLocation) +PrintHelp_Old(char *BinaryLocation) { #if AFE fprintf(stderr, @@ -8742,10 +9336,10 @@ typedef struct } neighbours; void -ExamineDB1(file File) +ExamineDB1(file *File) { database1 LocalDB; - LocalDB.Header = *(db_header1 *)File.Buffer.Location; + LocalDB.Header = *(db_header1 *)File->Buffer.Location; printf("Current:\n" "\tDBVersion: %d\n" "\tAppVersion: %d.%d.%d\n" @@ -8759,23 +9353,23 @@ ExamineDB1(file File) LocalDB.Header.EntryCount); - File.Buffer.Ptr = File.Buffer.Location + sizeof(LocalDB.Header); + File->Buffer.Ptr = File->Buffer.Location + sizeof(LocalDB.Header); for(int EntryIndex = 0; EntryIndex < LocalDB.Header.EntryCount; ++EntryIndex) { - LocalDB.Entry = *(db_entry1 *)File.Buffer.Ptr; + LocalDB.Entry = *(db_entry1 *)File->Buffer.Ptr; printf(" %3d\t%s%sSize: %4d\n", EntryIndex + 1, LocalDB.Entry.BaseFilename, StringLength(LocalDB.Entry.BaseFilename) > 8 ? "\t" : "\t\t", // NOTE(matt): Janktasm LocalDB.Entry.Size); - File.Buffer.Ptr += sizeof(LocalDB.Entry); + File->Buffer.Ptr += sizeof(LocalDB.Entry); } } void -ExamineDB2(file File) +ExamineDB2(file *File) { database2 LocalDB; - LocalDB.Header = *(db_header2 *)File.Buffer.Location; + LocalDB.Header = *(db_header2 *)File->Buffer.Location; printf("Current:\n" "\tDBVersion: %d\n" "\tAppVersion: %d.%d.%d\n" @@ -8795,23 +9389,23 @@ ExamineDB2(file File) LocalDB.Header.EntryCount); - File.Buffer.Ptr = File.Buffer.Location + sizeof(LocalDB.Header); + File->Buffer.Ptr = File->Buffer.Location + sizeof(LocalDB.Header); for(int EntryIndex = 0; EntryIndex < LocalDB.Header.EntryCount; ++EntryIndex) { - LocalDB.Entry = *(db_entry2 *)File.Buffer.Ptr; + LocalDB.Entry = *(db_entry2 *)File->Buffer.Ptr; printf(" %3d\t%s%sSize: %4d\n", EntryIndex + 1, LocalDB.Entry.BaseFilename, StringLength(LocalDB.Entry.BaseFilename) > 8 ? "\t" : "\t\t", // NOTE(matt): Janktasm LocalDB.Entry.Size); - File.Buffer.Ptr += sizeof(LocalDB.Entry); + File->Buffer.Ptr += sizeof(LocalDB.Entry); } } void -ExamineDB3(file File) +ExamineDB3(file *File) { database3 LocalDB; - LocalDB.Header = *(db_header3 *)File.Buffer.Location; + LocalDB.Header = *(db_header3 *)File->Buffer.Location; printf("Current:\n" "\tDBVersion: %d\n" "\tAppVersion: %d.%d.%d\n" @@ -8850,10 +9444,10 @@ ExamineDB3(file File) LocalDB.Header.EntryCount); - File.Buffer.Ptr = File.Buffer.Location + sizeof(LocalDB.Header); + File->Buffer.Ptr = File->Buffer.Location + sizeof(LocalDB.Header); for(int EntryIndex = 0; EntryIndex < LocalDB.Header.EntryCount; ++EntryIndex) { - LocalDB.Entry = *(db_entry3 *)File.Buffer.Ptr; + LocalDB.Entry = *(db_entry3 *)File->Buffer.Ptr; printf(" %3d\t%s%sSize: %4d\t%d\t%d\t%d\t%d\n" "\t %s\n", EntryIndex + 1, LocalDB.Entry.BaseFilename, @@ -8864,18 +9458,18 @@ ExamineDB3(file File) LocalDB.Entry.LinkOffsets.NextStart, LocalDB.Entry.LinkOffsets.NextEnd, LocalDB.Entry.Title); - File.Buffer.Ptr += sizeof(LocalDB.Entry); + File->Buffer.Ptr += sizeof(LocalDB.Entry); } } void -ExamineDB4(file File) +ExamineDB4(file *File) { #if AFE database4 LocalDB; - LocalDB.Header = *(db_header4 *)File.Buffer.Location; + LocalDB.Header = *(db_header4 *)File->Buffer.Location; - LocalDB.EntriesHeader = *(db_header_entries4 *)(File.Buffer.Location + sizeof(LocalDB.Header)); + LocalDB.EntriesHeader = *(db_header_entries4 *)(File->Buffer.Location + sizeof(LocalDB.Header)); printf("Current:\n" "\tDBVersion: %d\n" "\tAppVersion: %d.%d.%d\n" @@ -8920,10 +9514,10 @@ ExamineDB4(file File) LocalDB.EntriesHeader.Count); - File.Buffer.Ptr = File.Buffer.Location + sizeof(LocalDB.Header) + sizeof(LocalDB.EntriesHeader); + File->Buffer.Ptr = File->Buffer.Location + sizeof(LocalDB.Header) + sizeof(LocalDB.EntriesHeader); for(int EntryIndex = 0; EntryIndex < LocalDB.EntriesHeader.Count; ++EntryIndex) { - LocalDB.Entry = *(db_entry4 *)File.Buffer.Ptr; + LocalDB.Entry = *(db_entry4 *)File->Buffer.Ptr; printf(" %3d\t%s%sSize: %4d\t%d\t%d\t%d\t%d\n" "\t %s\n", EntryIndex, LocalDB.Entry.BaseFilename, @@ -8934,11 +9528,11 @@ ExamineDB4(file File) LocalDB.Entry.LinkOffsets.NextStart, LocalDB.Entry.LinkOffsets.NextEnd, LocalDB.Entry.Title); - File.Buffer.Ptr += sizeof(LocalDB.Entry); + File->Buffer.Ptr += sizeof(LocalDB.Entry); } - LocalDB.AssetsHeader = *(db_header_assets4 *)File.Buffer.Ptr; - File.Buffer.Ptr += sizeof(LocalDB.AssetsHeader); + LocalDB.AssetsHeader = *(db_header_assets4 *)File->Buffer.Ptr; + File->Buffer.Ptr += sizeof(LocalDB.AssetsHeader); printf( "\n" "Asset Root Directory: %s\n" "Asset Root URL: %s\n" @@ -8962,7 +9556,7 @@ ExamineDB4(file File) for(int AssetIndex = 0; AssetIndex < LocalDB.AssetsHeader.Count; ++AssetIndex) { - LocalDB.Asset = *(db_asset4*)File.Buffer.Ptr; + LocalDB.Asset = *(db_asset4*)File->Buffer.Ptr; printf("\n" "%s\n" "Type: %s\n" @@ -8973,12 +9567,12 @@ ExamineDB4(file File) LocalDB.Asset.Hash, LocalDB.Asset.LandmarkCount); - File.Buffer.Ptr += sizeof(LocalDB.Asset); + File->Buffer.Ptr += sizeof(LocalDB.Asset); for(int LandmarkIndex = 0; LandmarkIndex < LocalDB.Asset.LandmarkCount; ++LandmarkIndex) { - LocalDB.Landmark = *(db_landmark *)File.Buffer.Ptr; - File.Buffer.Ptr += sizeof(LocalDB.Landmark); - printf(" %d•%s%d%s", LocalDB.Landmark.EntryIndex, ColourStrings[CS_MAGENTA], LocalDB.Landmark.Position, ColourStrings[CS_END]); + LocalDB.Landmark = *(db_landmark *)File->Buffer.Ptr; + File->Buffer.Ptr += sizeof(LocalDB.Landmark); + printf(" %d•%s%d%s", LocalDB.Landmark.Entry, ColourStrings[CS_MAGENTA], LocalDB.Landmark.Position, ColourStrings[CS_END]); } printf("\n"); } @@ -9141,14 +9735,14 @@ PrintProjectsBlock(db_block_projects *B) } void -ExamineDB5(file File) +ExamineDB5(file *File) { - File.Buffer.Ptr = File.Buffer.Location; + File->Buffer.Ptr = File->Buffer.Location; database5 LocalDB; - if(File.Buffer.Size >= sizeof(LocalDB.Header)) + if(File->Buffer.Size >= sizeof(LocalDB.Header)) { - LocalDB.Header = *(db_header5 *)File.Buffer.Ptr; + LocalDB.Header = *(db_header5 *)File->Buffer.Ptr; fprintf(stderr, "\n"); PrintC(CS_BLUE_BOLD, "Versions"); fprintf(stderr, @@ -9170,24 +9764,30 @@ ExamineDB5(file File) LocalDB.Header.InitialAppVersion.Major, LocalDB.Header.InitialAppVersion.Minor, LocalDB.Header.InitialAppVersion.Patch, LocalDB.Header.InitialDBVersion, LocalDB.Header.InitialHMMLVersion.Major, LocalDB.Header.InitialHMMLVersion.Minor, LocalDB.Header.InitialHMMLVersion.Patch); - File.Buffer.Ptr += sizeof(db_header5); + File->Buffer.Ptr += sizeof(db_header5); for(int i = 0; i < LocalDB.Header.BlockCount; ++i) { - int Four = *(int *)File.Buffer.Ptr; + int Four = *(int *)File->Buffer.Ptr; if(Four == FOURCC("ASET")) { - db_block_assets *AssetsBlock = (db_block_assets *)File.Buffer.Ptr; - File.Buffer.Ptr = PrintAssetsBlock(AssetsBlock); + db_block_assets *AssetsBlock = (db_block_assets *)File->Buffer.Ptr; + File->Buffer.Ptr = PrintAssetsBlock(AssetsBlock); } else if(Four == FOURCC("PROJ")) { - db_block_projects *ProjectsBlock = (db_block_projects *)File.Buffer.Ptr; - File.Buffer.Ptr = PrintProjectsBlock(ProjectsBlock); + db_block_projects *ProjectsBlock = (db_block_projects *)File->Buffer.Ptr; + File->Buffer.Ptr = PrintProjectsBlock(ProjectsBlock); + // TODO(matt): REMOVE + // + Config->SuppressingPrompts = FALSE; + WaitForInput(); + // + //// } else { fprintf(stderr, "\n" - "Invalid database file: %s", File.Path); + "Invalid database file: %s", File->Path); break; } } @@ -9197,41 +9797,36 @@ ExamineDB5(file File) } void -ExamineDB(void) +ExamineDB(file *DB) { - DB.Metadata.File.Buffer.ID = BID_DATABASE; - DB.Metadata.File = InitFile(0, &Config->DatabaseLocation, EXT_NULL, TRUE); - ReadFileIntoBuffer(&DB.Metadata.File); // NOTE(matt): Could we actually catch errors (permissions?) here and bail? - - if(DB.Metadata.File.Buffer.Location) + if(DB->Buffer.Location) { - uint32_t FirstInt = *(uint32_t *)DB.Metadata.File.Buffer.Location; + uint32_t FirstInt = *(uint32_t *)DB->Buffer.Location; if(FirstInt != FOURCC("CNRA")) { switch(FirstInt) { - case 1: ExamineDB1(DB.Metadata.File); break; - case 2: ExamineDB2(DB.Metadata.File); break; - case 3: ExamineDB3(DB.Metadata.File); break; - default: printf("Invalid database file: %s\n", DB.Metadata.File.Path); break; + case 1: ExamineDB1(DB); break; + case 2: ExamineDB2(DB); break; + case 3: ExamineDB3(DB); break; + default: printf("Invalid database file: %s\n", DB->Path); break; } } else { - uint32_t SecondInt = *(uint32_t *)(DB.Metadata.File.Buffer.Location + sizeof(uint32_t)); + uint32_t SecondInt = *(uint32_t *)(DB->Buffer.Location + sizeof(uint32_t)); switch(SecondInt) { - case 4: ExamineDB4(DB.Metadata.File); break; - case 5: ExamineDB5(DB.Metadata.File); break; - default: printf("Invalid database file: %s\n", DB.Metadata.File.Path); break; + case 4: ExamineDB4(DB); break; + case 5: ExamineDB5(DB); break; + default: printf("Invalid database file: %s\n", DB->Path); break; } } } else { - fprintf(stderr, "Unable to open database file %s: %s\n", DB.Metadata.File.Path, strerror(errno)); + fprintf(stderr, "Unable to open database file %s: %s\n", DB->Path, strerror(errno)); } - FreeFile(&DB.Metadata.File, TRUE); } #define HMMLCleanup() \ @@ -9752,7 +10347,7 @@ ProcessTimestamp(buffers *CollationBuffers, neighbourhood *N, string Filepath, m _memory_book(category_info) *Topics, _memory_book(category_info) *Media, HMML_Timestamp *Timestamp, v3 *PreviousTimecode) { - MEM_TEST_TOP("ProcessTimestamp"); + MEM_TEST_TOP(); // TODO(matt): Introduce and use a SystemError() in here rc Result = RC_SUCCESS; @@ -10004,10 +10599,10 @@ ProcessTimestamp(buffers *CollationBuffers, neighbourhood *N, string Filepath, m QuoteUsername = Author; } - /* */ MEM_TEST_MID("ProcessTimestamp()"); + /* */ MEM_TEST_MID(); /* +MEM */ Result = BuildQuote(Strings, &QuoteInfo, QuoteUsername, Timestamp->quote.id, ShouldFetchQuotes); - /* */ MEM_TEST_MID("ProcessTimestamp()"); + /* */ MEM_TEST_MID(); if(Result == RC_SUCCESS) { CopyStringToBuffer(&MenuBuffers->Quote, @@ -10173,7 +10768,7 @@ ProcessTimestamp(buffers *CollationBuffers, neighbourhood *N, string Filepath, m IndexingChronologyError(&Filepath, Timestamp->line, Timecode, *PreviousTimecode); Result = RC_ERROR_HMML; } - MEM_TEST_END("ProcessTimestamp"); + MEM_TEST_END(); return Result; } @@ -10285,7 +10880,7 @@ FieldClashes_String(db_header_project *Header, uint32_t FieldOffset, uint32_t Fi rc HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseFilename, neighbourhood *N, uint64_t EntryCount) { - MEM_TEST_TOP("HMMLToBuffers"); + MEM_TEST_TOP(); rc Result = RC_SUCCESS; RewindCollationBuffers(CollationBuffers); @@ -10577,9 +11172,9 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF #if DEBUG printf( "================================================================================\n" - "%s\n" + "%.*s\n" "================================================================================\n", - Filename); + (int)BaseFilename.Length, BaseFilename.Base); #endif // NOTE(matt): Tree structure of "global" buffer dependencies // Master @@ -10717,7 +11312,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF string Author = {}; if(Timestamp->author) { Author = Wrap0(Timestamp->author); } - /* */ MEM_TEST_MID("HMMLToBuffers"); + /* */ MEM_TEST_MID(); /* +MEM */ Result = ProcessTimestamp(CollationBuffers, N, Wrap0(Filepath), &Strings, /* */ &MenuBuffers, &IndexBuffers, &PlayerBuffers, /* */ DefaultMedium, &Speakers, Author, &ReferencesArray, @@ -10725,7 +11320,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF /* */ &QuoteIdentifier, &RefIdentifier, /* */ &Topics, &Media, /* */ Timestamp, &PreviousTimecode); - /* */ MEM_TEST_MID("HMMLToBuffers"); + /* */ MEM_TEST_MID(); if(Result != RC_SUCCESS) { break; @@ -11302,7 +11897,7 @@ HMMLToBuffers(buffers *CollationBuffers, template *BespokeTemplate, string BaseF Result = RC_ERROR_FILE; } - MEM_TEST_END("HMMLToBuffers"); + MEM_TEST_END(); return Result; } @@ -11601,10 +12196,10 @@ rc BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template *Template, char *OutputPath, page_type PageType, bool GlobalSearch, unsigned int *PlayerOffset) { rc Result = RC_SUCCESS; - MEM_TEST_TOP("BuffersToHTML()"); + MEM_TEST_TOP(); #if DEBUG printf("\n\n --- Buffer Collation ---\n" - " %s\n\n\n", OutputPath ? OutputPath : Project->OutLocation); + " %s\n\n\n", OutputPath); #endif #if DEBUG_MEM @@ -11696,9 +12291,9 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template * case TAG_VOD_PLATFORM: CopyStringToBufferNoFormat(&Master, Wrap0(VODPlatformStrings[CollationBuffers->VODPlatform])); break; case TAG_SEARCH: { - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); /* +MEM */ CopyLandmarkedBuffer(&Master, &CollationBuffers->Search, 0, PageType); - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); } break; case TAG_INCLUDES: if(PageType == PAGE_PLAYER) @@ -11712,9 +12307,9 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template * break; case TAG_PLAYER: { - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); /* +MEM */ CopyLandmarkedBuffer(&Master, &CollationBuffers->Player, PlayerOffset, PageType); - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); } break; case TAG_ASSET: { @@ -11810,9 +12405,9 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template * fwrite(Master.Location, Master.Ptr - Master.Location, 1, OutFile); fclose(OutFile); - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); /* +MEM */ FreeBuffer(&Master); - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); #if DEBUG_MEM MemLog = fopen("/home/matt/cinera_mem", "a+"); @@ -11856,16 +12451,16 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template * " "); if(PageType == PAGE_PLAYER) { - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); /* +MEM */ CopyLandmarkedBuffer(&Master, &CollationBuffers->Player, PlayerOffset, PageType); - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); CopyStringToBuffer(&Master, "\n"); } else { - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); /* +MEM */ CopyLandmarkedBuffer(&Master, &CollationBuffers->Search, 0, PageType); - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); } CopyStringToBuffer(&Master, @@ -11883,14 +12478,14 @@ BuffersToHTML(config *C, project *Project, buffers *CollationBuffers, template * fwrite(Master.Location, Master.Ptr - Master.Location, 1, OutFile); fclose(OutFile); OutFile = 0; - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); /* +MEM */ FreeBuffer(&Master); - /* */ MEM_TEST_MID("BuffersToHTML()"); + /* */ MEM_TEST_MID(); Result = RC_SUCCESS; } End: SortLandmarks(&Assets); - MEM_TEST_END("BuffersToHTML()"); + MEM_TEST_END(); return Result; } @@ -12334,7 +12929,7 @@ RenumberEntries(neighbourhood *N, db_header_project *P, int64_t IndexOfFirstEntr db_entry * InsertIntoDB(neighbourhood *N, buffers *CollationBuffers, template *BespokeTemplate, string BaseFilename, bool RecheckingPrivacy, bool *Reinserting) { - MEM_TEST_TOP("InsertIntoDB()"); + MEM_TEST_TOP(); db_entry *Result = 0; ResetNeighbourhood(N); edit_type_id EditType = EDIT_APPEND; @@ -12377,9 +12972,9 @@ InsertIntoDB(neighbourhood *N, buffers *CollationBuffers, template *BespokeTempl bool VideoIsPrivate = FALSE; - /* */ MEM_TEST_MID("InsertIntoDB()"); + /* */ MEM_TEST_MID(); /* +MEM */ rc HMMLToBuffersReturn = HMMLToBuffers(CollationBuffers, BespokeTemplate, BaseFilename, N, N->Project->EntryCount + (EditType != EDIT_REINSERTION)); - /* */ MEM_TEST_MID("InsertIntoDB()"); + /* */ MEM_TEST_MID(); if(HMMLToBuffersReturn == RC_SUCCESS || HMMLToBuffersReturn == RC_PRIVATE_VIDEO) { if(HMMLToBuffersReturn == RC_PRIVATE_VIDEO) @@ -12393,9 +12988,9 @@ InsertIntoDB(neighbourhood *N, buffers *CollationBuffers, template *BespokeTempl if(!DB.File.Buffer.Location) { - /* */ MEM_TEST_MID("InsertIntoDB()"); + /* */ MEM_TEST_MID(); /* +MEM */ InitIndexFile(CurrentProject); - /* */ MEM_TEST_MID("InsertIntoDB()"); + /* */ MEM_TEST_MID(); } // TODO(matt): CollationBuffers->SearchEntry may, I believe, now contain data. We must not write it to file by mistake @@ -12472,7 +13067,7 @@ InsertIntoDB(neighbourhood *N, buffers *CollationBuffers, template *BespokeTempl Result = N->This; } } - MEM_TEST_END("InsertIntoDB()"); + MEM_TEST_END(); return Result; } @@ -12506,7 +13101,7 @@ ProcessPrevLandmarks(neighbourhood *N, db_asset *Asset, landmark_range ProjectRa for(int j = 0; j < FormerTarget.Length; ++j, ++*RunningIndex) { db_landmark *Landmark = FirstLandmark + *RunningIndex; - if(Landmark->EntryIndex >= 0 && Landmark->Position >= N->PreLinkPrevOffsetTotal) + if(Landmark->Index.Entry >= 0 && Landmark->Position >= N->PreLinkPrevOffsetTotal) { Landmark->Position += N->PrevOffsetModifier; } @@ -12546,8 +13141,8 @@ ProcessNextLandmarks(neighbourhood *N, db_asset *Asset, landmark_range ProjectRa db_landmark *Landmark = FirstLandmark + *RunningIndex; switch(EditType) { - case EDIT_DELETION: --Landmark->EntryIndex; break; - case EDIT_ADDITION: ++Landmark->EntryIndex; break; + case EDIT_DELETION: --Landmark->Index.Entry; break; + case EDIT_ADDITION: ++Landmark->Index.Entry; break; default: break; } fwrite(Landmark, sizeof(db_landmark), 1, DB.Metadata.File.Handle); @@ -12606,7 +13201,7 @@ OffsetAssociatedIndicesOfProject(db_header_project *Project, asset_index_and_loc Child = OffsetAssociatedIndicesOfProject(Child, AssetDeletionRecords, AssetDeletionRecordCount); } - return SkipProjectAndChildren(Project); + return SkipHeaderedSectionRecursively(Project, GetDBStructureHeaderedSection(B_PROJ)); } void @@ -12623,7 +13218,7 @@ OffsetAssociatedIndices(asset_index_and_location *AssetDeletionRecords, int Asse void DeleteStaleAssets(void) { - MEM_TEST_TOP("DeleteStaleAssets"); + MEM_TEST_TOP(); int AssetDeletionCount = 0; DB.Metadata.Signposts.AssetsBlock.Ptr = LocateBlock(B_ASET); db_block_assets *AssetsBlock = DB.Metadata.Signposts.AssetsBlock.Ptr; @@ -12641,7 +13236,7 @@ DeleteStaleAssets(void) ++AssetDeletionCount; --AssetsBlock->Count; } - Asset = SkipAsset(Asset); + Asset = SkipHeaderedSectionRecursively(Asset, GetDBStructureHeaderedSection(B_ASET)); } if(AssetDeletionCount > 0) @@ -12665,7 +13260,7 @@ DeleteStaleAssets(void) WriteFromByteToEnd(&DB.Metadata.File, BytesIntoFile); CycleSignpostedFile(&DB.Metadata); } - MEM_TEST_END("DeleteStaleAssets"); + MEM_TEST_END(); } void @@ -12709,7 +13304,7 @@ DetermineProjectLandmarksRange(db_asset *A, db_project_index I) db_landmark *Landmark = LocateFirstLandmark(A); for(; Result.First < A->LandmarkCount; ++Result.First, ++Landmark) { - if(!(ProjectIndicesDiffer(I, Landmark->Project) > 0)) + if(!(ProjectIndicesDiffer(I, Landmark->Index.Project) > 0)) { break; } @@ -12717,7 +13312,7 @@ DetermineProjectLandmarksRange(db_asset *A, db_project_index I) for(; Result.First + Result.Length < A->LandmarkCount; ++Landmark, ++Result.Length) { - if(ProjectIndicesDiffer(I, Landmark->Project)) + if(ProjectIndicesDiffer(I, Landmark->Index.Project)) { break; } @@ -12817,8 +13412,8 @@ AddLandmarks(neighbourhood *N, project *P, edit_type_id EditType) { landmark *ThisLandmark = GetPlaceInBook(&AssetInMemory->Player, j); db_landmark Landmark = {}; - Landmark.Project = P->Index; - Landmark.EntryIndex = N->ThisIndex; + Landmark.Index.Project = P->Index; + Landmark.Index.Entry = N->ThisIndex; Landmark.Position = ThisLandmark->Offset; fwrite(&Landmark, sizeof(Landmark), 1, DB.Metadata.File.Handle); } @@ -12937,8 +13532,8 @@ VerifyLandmarks_(neighbourhood *N, int LineNumber) { db_landmark *Next = Landmark + 1; if((ProjectIndicesDiffer(Next->Project, Landmark->Project) < 0) || - (ProjectIndicesMatch(Next->Project, Landmark->Project) && Next->EntryIndex < Landmark->EntryIndex) || - (ProjectIndicesMatch(Next->Project, Landmark->Project) && Next->EntryIndex == Landmark->EntryIndex && Next->Position < Landmark->Position)) + (ProjectIndicesMatch(Next->Project, Landmark->Project) && Next->Entry < Landmark->Entry) || + (ProjectIndicesMatch(Next->Project, Landmark->Project) && Next->Entry == Landmark->Entry && Next->Position < Landmark->Position)) { if(!Titled) { @@ -13123,8 +13718,8 @@ UpdateLandmarksForSearch(neighbourhood *N, db_project_index ProjectIndex) { landmark *ThisLandmark = GetPlaceInBook(&This->Search, j); db_landmark Landmark = {}; - Landmark.Project = ProjectIndex; - Landmark.EntryIndex = SP_SEARCH; + Landmark.Index.Project = ProjectIndex; + Landmark.Index.Entry = SP_SEARCH; Landmark.Position = ThisLandmark->Offset; fwrite(&Landmark, sizeof(Landmark), 1, DB.Metadata.File.Handle); //AccumulateFileEditSize(&DB.Metadata, sizeof(db_landmark)); @@ -13137,7 +13732,7 @@ UpdateLandmarksForSearch(neighbourhood *N, db_project_index ProjectIndex) break; } } - Asset = SkipAsset(Asset); + Asset = SkipHeaderedSectionRecursively(Asset, GetDBStructureHeaderedSection(B_ASET)); } CycleSignpostedFile(&DB.Metadata); UpdateNeighbourhoodPointers(N, &DB.Metadata.Signposts); @@ -13174,7 +13769,7 @@ rc InsertNeighbourLink(db_header_project *P, db_entry *From, db_entry *To, enum8(link_directions) LinkDirection, bool FromHasOneNeighbour) { rc Result = RC_SUCCESS; - MEM_TEST_TOP("InsertNeighbourLink()"); file HTML = {}; ReadPlayerPageIntoBuffer(&HTML, Wrap0i(P->BaseDir), Wrap0i(P->PlayerLocation), Wrap0i(From->OutputLocation)); + MEM_TEST_TOP(); file HTML = {}; ReadPlayerPageIntoBuffer(&HTML, Wrap0i(P->BaseDir), Wrap0i(P->PlayerLocation), Wrap0i(From->OutputLocation)); if(HTML.Buffer.Location) { if(!(HTML.Handle = fopen(HTML.Path, "w"))) { Result = RC_ERROR_FILE; }; @@ -13288,7 +13883,7 @@ InsertNeighbourLink(db_header_project *P, db_entry *From, db_entry *To, enum8(li Result = RC_ERROR_FILE; } FreeFile(&HTML, NA); - MEM_TEST_END("InsertNeighbourLink()"); + MEM_TEST_END(); return Result; } @@ -13351,7 +13946,7 @@ DeleteNeighbourLinks(neighbourhood *N) void LinkToNewEntry(neighbourhood *N) { - MEM_TEST_TOP("LinkToNewEntry()"); + MEM_TEST_TOP(); N->PreLinkThisOffsetTotal = N->This->LinkOffsets.PrevEnd + N->This->LinkOffsets.NextStart + N->This->LinkOffsets.NextEnd; @@ -13383,7 +13978,7 @@ LinkToNewEntry(neighbourhood *N) + N->Next->LinkOffsets.NextEnd - N->PreLinkNextOffsetTotal; } - MEM_TEST_END("LinkToNewEntry()"); + MEM_TEST_END(); } void @@ -13685,7 +14280,7 @@ GenerateFilterOfProjectAndChildren(buffer *Filter, db_header_project *StoredP, p { project *Child = GetPlaceInBook(&P->Child, ChildIndex); GenerateFilterOfProjectAndChildren(Filter, StoredChild, Child, SearchRequired, FALSE, RequiresCineraJS); - StoredChild = SkipProjectAndChildren(StoredChild); + StoredChild = SkipHeaderedSectionRecursively(StoredChild, GetDBStructureHeaderedSection(B_PROJ)); } if(!TopLevel || StoredP->EntryCount > 0) @@ -13785,7 +14380,7 @@ GenerateIndexOfProjectAndChildren(buffer *Index, db_header_project *StoredP, pro { project *Child = GetPlaceInBook(&P->Child, ChildIndex); GenerateIndexOfProjectAndChildren(Index, StoredChild, Child, SearchRequired, FALSE, RequiresCineraJS); - StoredChild = SkipProjectAndChildren(StoredChild); + StoredChild = SkipHeaderedSectionRecursively(StoredChild, GetDBStructureHeaderedSection(B_PROJ)); } if(!TopLevel || StoredP->EntryCount > 0) @@ -13812,7 +14407,7 @@ CountOfProjectOrDescendantsWithPublicEntries(db_header_project *P, uint8_t *Coun for(int ChildIndex = 0; ChildIndex < P->ChildCount; ++ChildIndex) { CountOfProjectOrDescendantsWithPublicEntries(Child, Count); - Child = SkipProjectAndChildren(Child); + Child = SkipHeaderedSectionRecursively(Child, GetDBStructureHeaderedSection(B_PROJ)); } } @@ -13829,7 +14424,7 @@ ProjectsHavePublicEntries() { return TRUE; } - Child = SkipProjectAndChildren(Child); + Child = SkipHeaderedSectionRecursively(Child, GetDBStructureHeaderedSection(B_PROJ)); } return Count; } @@ -13847,7 +14442,7 @@ AtLeastNProjectsHavePublicEntries(uint8_t N) { return TRUE; } - Child = SkipProjectAndChildren(Child); + Child = SkipHeaderedSectionRecursively(Child, GetDBStructureHeaderedSection(B_PROJ)); } return FALSE; } @@ -14160,7 +14755,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P GenerateFilterOfProjectAndChildren(&Filter, StoredP, Child, &SearchRequired, FALSE, &RequiresCineraJS); } GenerateIndexOfProjectAndChildren(&Index, StoredP, Child, &SearchRequired, FALSE, &RequiresCineraJS); - StoredP = SkipProjectAndChildren(StoredP); + StoredP = SkipHeaderedSectionRecursively(StoredP, GetDBStructureHeaderedSection(B_PROJ)); } } if(FilterRequired) @@ -14294,28 +14889,28 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("q"), TRUE); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("a"), TRUE); AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("z"), TRUE); - CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); + CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("2"), TRUE); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("w"), TRUE); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("s"), TRUE); AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("x"), TRUE); - CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); + CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("3"), TRUE); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("e"), TRUE); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("d"), TRUE); AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("c"), TRUE); - CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); + CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); OpenNodeCNewLine(B, &IndentationLevel, NODE_DIV, 0); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("4"), TRUE); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("r"), TRUE); AppendHelpKeyToBufferNewLine(B, &IndentationLevel, Wrap0("f"), TRUE); AppendHelpKeyToBuffer(B, &IndentationLevel, Wrap0("v"), TRUE); - CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); + CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); CloseNodeNewLine(B, &IndentationLevel, NODE_DIV); // key_block @@ -14405,7 +15000,7 @@ SearchToBuffer(buffers *CollationBuffers, db_header_project *StoredP, project *P int GeneratePlayerPage(neighbourhood *N, buffers *CollationBuffers, template *PlayerTemplate, string OutputLocation, bool Reinserting) { - MEM_TEST_TOP("GeneratePlayerPage()"); + MEM_TEST_TOP(); string BaseDir = Wrap0i(N->Project->BaseDir); string PlayerLocation = Wrap0i(N->Project->PlayerLocation); char *PlayerPath = ConstructDirectoryPath(&BaseDir, &PlayerLocation, &OutputLocation); @@ -14437,9 +15032,9 @@ GeneratePlayerPage(neighbourhood *N, buffers *CollationBuffers, template *Player break; } } - /* */ MEM_TEST_MID("GeneratePlayerPage()"); + /* */ MEM_TEST_MID(); /* +MEM */ BuffersToHTML(0, CurrentProject, CollationBuffers, PlayerTemplate, PlayerPath, PAGE_PLAYER, FALSE, &N->This->LinkOffsets.PrevStart); - /* */ MEM_TEST_MID("GeneratePlayerPage()"); + /* */ MEM_TEST_MID(); Free(PlayerPath); // NOTE(matt): A previous InsertNeighbourLink() call will have done SnipeEntryIntoMetadataBuffer(), but we must do it here now // that PrevStart has been adjusted by BuffersToHTML() @@ -14450,14 +15045,14 @@ GeneratePlayerPage(neighbourhood *N, buffers *CollationBuffers, template *Player FreeBuffer(&CollationBuffers->Search); } ResetAssetLandmarks(); - MEM_TEST_END("GeneratePlayerPage()"); + MEM_TEST_END(); return RC_SUCCESS; } rc GenerateSearchPage(neighbourhood *N, buffers *CollationBuffers, db_header_project *StoredP, project *P) { - MEM_TEST_TOP("GenerateSearchPage()"); + MEM_TEST_TOP(); string BaseDir = Wrap0i(N->Project->BaseDir); string SearchLocation = Wrap0i(N->Project->SearchLocation); char *SearchPath = ConstructDirectoryPath(&BaseDir, &SearchLocation, 0); @@ -14496,14 +15091,14 @@ GenerateSearchPage(neighbourhood *N, buffers *CollationBuffers, db_header_projec Free(SearchPath); FreeBuffer(&CollationBuffers->Search); ResetAssetLandmarks(); - MEM_TEST_END("GenerateSearchPage()"); + MEM_TEST_END(); return RC_SUCCESS; } rc GenerateGlobalSearchPage(neighbourhood *N, buffers *CollationBuffers) { - MEM_TEST_TOP("GenerateGlobalSearchPage()"); + MEM_TEST_TOP(); db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr; string SearchLocationL = Wrap0i(ProjectsBlock->GlobalSearchDir); char *SearchPath = MakeString0("l", &SearchLocationL); @@ -14525,9 +15120,9 @@ GenerateGlobalSearchPage(neighbourhood *N, buffers *CollationBuffers) { case RC_SUCCESS: { - /* */ MEM_TEST_MID("GenerateGlobalSearchPage()"); + /* */ MEM_TEST_MID(); /* +MEM */ BuffersToHTML(Config, 0, CollationBuffers, &Config->SearchTemplate, SearchPath, PAGE_SEARCH, TRUE, 0); - /* */ MEM_TEST_MID("GenerateGlobalSearchPage()"); + /* */ MEM_TEST_MID(); UpdateLandmarksForSearch(N, GLOBAL_SEARCH_PAGE_INDEX); break; } @@ -14545,14 +15140,14 @@ GenerateGlobalSearchPage(neighbourhood *N, buffers *CollationBuffers) Free(SearchPath); FreeBuffer(&CollationBuffers->Search); ResetAssetLandmarks(); - MEM_TEST_END("GenerateGlobalSearchPage()"); + MEM_TEST_END(); return RC_SUCCESS; } int GenerateSearchPages(neighbourhood *N, buffers *CollationBuffers) { - MEM_TEST_TOP("GenerateSearchPages()"); + MEM_TEST_TOP(); PrintFunctionName("GenerateSearchPage()"); project *This = CurrentProject; //PrintLineage(This->Lineage, TRUE); @@ -14572,13 +15167,13 @@ GenerateSearchPages(neighbourhood *N, buffers *CollationBuffers) { // TODO(matt): Fully determine whether UpdateNeighbourhoodPointers() must happen here UpdateNeighbourhoodPointers(N, &DB.Metadata.Signposts); - /* */ MEM_TEST_MID("GenerateSearchPages()"); + /* */ MEM_TEST_MID(); /* +MEM */ GenerateGlobalSearchPage(N, CollationBuffers); - /* */ MEM_TEST_MID("GenerateSearchPages()"); + /* */ MEM_TEST_MID(); } //sleep(1); - MEM_TEST_END("GenerateSearchPages()"); + MEM_TEST_END(); return RC_SUCCESS; } @@ -14607,33 +15202,33 @@ rc InsertEntry(neighbourhood *N, buffers *CollationBuffers, template *BespokeTemplate, string BaseFilename, bool RecheckingPrivacy) { rc Result = RC_SUCCESS; - MEM_TEST_TOP("InsertEntry()"); + MEM_TEST_TOP(); bool Reinserting = FALSE; - /* */ MEM_TEST_MID("InsertEntry()"); + /* */ MEM_TEST_MID(); /* +MEM */ db_entry *Entry = InsertIntoDB(N, CollationBuffers, BespokeTemplate, BaseFilename, RecheckingPrivacy, &Reinserting); - /* */ MEM_TEST_MID("InsertEntry()"); + /* */ MEM_TEST_MID(); if(Entry) { LinkNeighbours(N, LINK_INCLUDE); if(BespokeTemplate->File.Buffer.Location) { - /* */ MEM_TEST_MID("InsertEntry()"); + /* */ MEM_TEST_MID(); /* +MEM (inferred) */ GeneratePlayerPage(N, CollationBuffers, BespokeTemplate, Wrap0i(Entry->OutputLocation), Reinserting); - /* */ MEM_TEST_MID("InsertEntry()"); + /* */ MEM_TEST_MID(); FreeTemplate(BespokeTemplate); } else { - /* */ MEM_TEST_MID("InsertEntry()"); + /* */ MEM_TEST_MID(); /* +MEM */ GeneratePlayerPage(N, CollationBuffers, &CurrentProject->PlayerTemplate, Wrap0i(Entry->OutputLocation), Reinserting); - /* */ MEM_TEST_MID("InsertEntry()"); + /* */ MEM_TEST_MID(); } } else { Result = RC_NOOP; } - MEM_TEST_END("InsertEntry()"); + MEM_TEST_END(); return Result; } @@ -15012,7 +15607,7 @@ rc SyncDBWithInput(neighbourhood *N, buffers *CollationBuffers, template *BespokeTemplate) { rc Result = RC_SUCCESS; - MEM_TEST_TOP("SyncDBWithInput()"); + MEM_TEST_TOP(); if(DB.Metadata.File.Buffer.Size > 0 && Config->QueryString.Length == 0) { DeleteAllLandmarksAndAssets(); @@ -15067,9 +15662,9 @@ SyncDBWithInput(neighbourhood *N, buffers *CollationBuffers, template *BespokeTe if(ExtensionMatches(Filename, EXT_HMML)) { ResetNeighbourhood(N); - /* */ MEM_TEST_MID("SyncDBWithInput()"); + /* */ MEM_TEST_MID(); /* +MEM */ Inserted |= (InsertEntry(N, CollationBuffers, BespokeTemplate, GetBaseFilename(Filename, EXT_HMML), 0) == RC_SUCCESS); - /* */ MEM_TEST_MID("SyncDBWithInput()"); + /* */ MEM_TEST_MID(); VerifyLandmarks(N); } } @@ -15090,9 +15685,9 @@ SyncDBWithInput(neighbourhood *N, buffers *CollationBuffers, template *BespokeTe // Of note: We seem to be producing the asset landmark for Generation -1 just fine. The problem is that // we're not getting the index.html file - /* */ MEM_TEST_MID("SyncDBWithInput()"); + /* */ MEM_TEST_MID(); /* +MEM */ GenerateSearchPages(N, CollationBuffers); - /* */ MEM_TEST_MID("SyncDBWithInput()"); + /* */ MEM_TEST_MID(); DeleteStaleAssets(); UpdateNeighbourhoodPointers(N, &DB.Metadata.Signposts); VerifyLandmarks(N); @@ -15104,7 +15699,7 @@ SyncDBWithInput(neighbourhood *N, buffers *CollationBuffers, template *BespokeTe fprintf(stderr, "Unable to scan project directory %.*s: %s\n", (int)CurrentProject->HMMLDir.Length, CurrentProject->HMMLDir.Base, strerror(errno)); Result = RC_ERROR_DIRECTORY; } - MEM_TEST_END("SyncDBWithInput()"); + MEM_TEST_END(); return Result; } @@ -15131,7 +15726,7 @@ AccumulateProjectIndices(project_generations *A, db_header_project *P) for(int i = 0; i < P->ChildCount; ++i) { AccumulateProjectIndices(A, Child); - Child = SkipProjectAndChildren(Child); + Child = SkipHeaderedSectionRecursively(Child, GetDBStructureHeaderedSection(B_PROJ)); } DecrementCurrentGeneration(A); } @@ -15429,7 +16024,7 @@ OffsetAssetLandmarks(db_asset *A, uint64_t *BytesThroughFile, project_generation db_landmark *Landmark = LocateFirstLandmark(A); WriteFromByteToPointer(&DB.Metadata.File, BytesThroughFile, Landmark); int i = 0; - while(i < A->LandmarkCount && Landmark->Project.Generation == -1) + while(i < A->LandmarkCount && Landmark->Index.Project.Generation == -1) { fwrite(Landmark, sizeof(db_landmark), 1, DB.Metadata.File.Handle); *BytesThroughFile += sizeof(db_landmark); @@ -15443,15 +16038,15 @@ OffsetAssetLandmarks(db_asset *A, uint64_t *BytesThroughFile, project_generation uint32_t OldEntriesInGeneration = 0 ; if(OldAcc->EntriesInGeneration.ItemCount > 0) { - OldEntriesInGeneration = *(uint32_t *)GetPlaceInBook(&OldAcc->EntriesInGeneration, NewLandmark.Project.Generation); + OldEntriesInGeneration = *(uint32_t *)GetPlaceInBook(&OldAcc->EntriesInGeneration, NewLandmark.Index.Project.Generation); } - if(NewLandmark.Project.Index >= OldEntriesInGeneration) + if(NewLandmark.Index.Project.Index >= OldEntriesInGeneration) { - NewLandmark.Project.Index += - (NewLandmark.Project.Generation < NewAcc->EntriesInGeneration.ItemCount ? *(uint32_t *)GetPlaceInBook(&NewAcc->EntriesInGeneration, NewLandmark.Project.Generation) : 0) + NewLandmark.Index.Project.Index += + (NewLandmark.Index.Project.Generation < NewAcc->EntriesInGeneration.ItemCount ? *(uint32_t *)GetPlaceInBook(&NewAcc->EntriesInGeneration, NewLandmark.Index.Project.Generation) : 0) - - (NewLandmark.Project.Generation < OldAcc->EntriesInGeneration.ItemCount ? OldEntriesInGeneration : 0); + (NewLandmark.Index.Project.Generation < OldAcc->EntriesInGeneration.ItemCount ? OldEntriesInGeneration : 0); } fwrite(&NewLandmark, sizeof(db_landmark), 1, DB.Metadata.File.Handle); *BytesThroughFile += sizeof(db_landmark); @@ -15470,7 +16065,7 @@ InitProjectInDBPostamble(project_generations *OldAcc, project_generations *NewAc for(int i = 0; i < AssetsBlock->Count; ++i) { OffsetAssetLandmarks(Asset, &Byte, OldAcc, NewAcc); - Asset = SkipAsset(Asset); + Asset = SkipHeaderedSectionRecursively(Asset, GetDBStructureHeaderedSection(B_ASET)); } WriteFromByteToEnd(&DB.Metadata.File, Byte); @@ -15480,50 +16075,54 @@ InitProjectInDBPostamble(project_generations *OldAcc, project_generations *NewAc } void -InsertProjectIntoDB_TopLevel(project_generations *G, db_block_projects **Block, db_header_project **Child, project *P) +InsertProjectIntoDB(project_generations *G, db_block_projects **Block, db_header_project **Parent, db_header_project **Child, project *P) { + bool GotBlock = Block ? TRUE : FALSE; + bool GotParent = Parent ? TRUE : FALSE; + Assert(GotBlock ^ GotParent); + uint64_t Byte = 0; OpenFileForWriting(&DB.Metadata.File); WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Block); - db_block_projects NewBlock = **Block; - ++NewBlock.Count; - fwrite(&NewBlock, sizeof(db_block_projects), 1, DB.Metadata.File.Handle); - Byte += sizeof(db_block_projects); + uint64_t PPos; + if(GotBlock) + { + PPos = (char *)*Block - DB.Metadata.File.Buffer.Location; + WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Block); + + db_block_projects NewBlock = **Block; + ++NewBlock.Count; + fwrite(&NewBlock, sizeof(db_block_projects), 1, DB.Metadata.File.Handle); + Byte += sizeof(db_block_projects); + } + else + { + PPos = (char *)*Parent - DB.Metadata.File.Buffer.Location; + WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Parent); + + db_header_project NewParent = **Parent; + ++NewParent.ChildCount; + fwrite(&NewParent, sizeof(db_header_project), 1, DB.Metadata.File.Handle); + Byte += sizeof(db_header_project); + } WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Child); SetFileEditPosition(&DB.Metadata); project_generations OldG = CopyAccumulator(G); InitProjectInDBRecursively(G, P); - uint64_t BlockPos = (char *)*Block - DB.Metadata.File.Buffer.Location; + *Child = InitProjectInDBPostamble(&OldG, G); - *Block = (db_block_projects *)(DB.Metadata.File.Buffer.Location + BlockPos); - FreeBook(&OldG.EntriesInGeneration); -} - -void -InsertProjectIntoDB(project_generations *G, db_header_project **Parent, db_header_project **Child, project *P) -{ - uint64_t Byte = 0; - - OpenFileForWriting(&DB.Metadata.File); - WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Parent); - - db_header_project NewParent = **Parent; - ++NewParent.ChildCount; - fwrite(&NewParent, sizeof(db_header_project), 1, DB.Metadata.File.Handle); - Byte += sizeof(db_header_project); - - WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Child); - SetFileEditPosition(&DB.Metadata); - - project_generations OldG = CopyAccumulator(G); - InitProjectInDBRecursively(G, P); - uint64_t PPos = (char *)*Parent - DB.Metadata.File.Buffer.Location; - *Child = InitProjectInDBPostamble(&OldG, G); - *Parent = (db_header_project *)(DB.Metadata.File.Buffer.Location + PPos); + if(GotBlock) + { + *Block = (db_block_projects *)(DB.Metadata.File.Buffer.Location + PPos); + } + else + { + *Parent = (db_header_project *)(DB.Metadata.File.Buffer.Location + PPos); + } FreeBook(&OldG.EntriesInGeneration); } @@ -15610,7 +16209,7 @@ DeleteLandmarksOfProjectAndChildren(db_asset *A, uint64_t *BytesThroughBuffer, p db_landmark *TailLandmark = FirstLandmark + LandmarkIndex; for(; - LandmarkIndex < A->LandmarkCount && TailLandmark->Project.Generation == GenIndex; + LandmarkIndex < A->LandmarkCount && TailLandmark->Index.Project.Generation == GenIndex; ++LandmarkIndex, ++TailLandmark) { db_landmark NewLandmark = *TailLandmark; @@ -15619,9 +16218,9 @@ DeleteLandmarksOfProjectAndChildren(db_asset *A, uint64_t *BytesThroughBuffer, p // for under / overflow, and treating them as signed permits signed comparison uint32_t LocalEntries = *(uint32_t *)GetPlaceInBook(&LocalAcc->EntriesInGeneration, GenIndex); uint32_t MainEntries = *(uint32_t *)GetPlaceInBook(&MainAcc->EntriesInGeneration, GenIndex); - if((int64_t)NewLandmark.Project.Index - (int64_t)LocalEntries >= (int64_t)MainEntries) + if((int64_t)NewLandmark.Index.Project.Index - (int64_t)LocalEntries >= (int64_t)MainEntries) { - NewLandmark.Project.Index -= *(uint32_t *)GetPlaceInBook(&LocalAcc->EntriesInGeneration, GenIndex); + NewLandmark.Index.Project.Index -= *(uint32_t *)GetPlaceInBook(&LocalAcc->EntriesInGeneration, GenIndex); } fwrite(&NewLandmark, sizeof(db_landmark), 1, DB.Metadata.File.Handle); *BytesThroughBuffer += sizeof(db_landmark); @@ -15690,7 +16289,7 @@ DeleteProjectInterior(db_header_project **Child, project_generations *G, uint64_ for(int AssetIndex = 0; AssetIndex < AssetsBlock->Count; ++AssetIndex) { DeleteLandmarksOfProjectAndChildren(Asset, BytesThroughBuffer, G, &ChildAccumulator); - Asset = SkipAsset(Asset); + Asset = SkipHeaderedSectionRecursively(Asset, GetDBStructureHeaderedSection(B_ASET)); } *BytesThroughBuffer += WriteFromByteToEnd(&DB.Metadata.File, *BytesThroughBuffer); @@ -15699,66 +16298,68 @@ DeleteProjectInterior(db_header_project **Child, project_generations *G, uint64_ } void -DeleteProject_TopLevel(db_block_projects **Parent, db_header_project **Child, project_generations *G) -{ - PrintFunctionName("DeleteProject_TopLevel()"); - // TODO(matt); Print out something sensible to inform real life users - // TODO(matt): - // - // 0:1 - // 1:4 - uint64_t PPos = (char *)*Parent - DB.Metadata.File.Buffer.Location; - uint64_t CPos = (char *)*Child - DB.Metadata.File.Buffer.Location; - - OpenFileForWriting(&DB.Metadata.File); - uint64_t Byte = 0; - - WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Parent); - - db_block_projects NewParent = **Parent; - --NewParent.Count; - - fwrite(&NewParent, sizeof(db_block_projects), 1, DB.Metadata.File.Handle); - Byte += sizeof(db_block_projects); - - DeleteProjectInterior(Child, G, &Byte); - - *Parent = (db_block_projects *)(DB.Metadata.File.Buffer.Location + PPos); - *Child = (db_header_project *)(DB.Metadata.File.Buffer.Location + CPos); -} - -void -DeleteProject(db_header_project **Parent, db_header_project **Child, project_generations *G) +DeleteProject(db_block_projects **Block, db_header_project **Parent, db_header_project **Child, project_generations *G) { PrintFunctionName("DeleteProject()"); + + bool GotBlock = Block ? TRUE : FALSE; + bool GotParent = Parent ? TRUE : FALSE; + Assert(GotBlock ^ GotParent); + // TODO(matt); Print out something sensible to inform real life users // TODO(matt): // // 0:1 // 1:4 - uint64_t PPos = (char *)*Parent - DB.Metadata.File.Buffer.Location; + uint64_t PPos; + if(GotBlock) + { + PPos = (char *)*Block - DB.Metadata.File.Buffer.Location; + } + else + { + PPos = (char *)*Parent - DB.Metadata.File.Buffer.Location; + } uint64_t CPos = (char *)*Child - DB.Metadata.File.Buffer.Location; //db_project_index Index = GetCurrentProjectIndex(G); OpenFileForWriting(&DB.Metadata.File); uint64_t Byte = 0; - WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Parent); + if(GotBlock) + { + WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Block); - db_header_project NewParent = **Parent; - --NewParent.ChildCount; + db_block_projects NewBlock = **Block; + --NewBlock.Count; + fwrite(&NewBlock, sizeof(db_block_projects), 1, DB.Metadata.File.Handle); + Byte += sizeof(db_block_projects); + } + else + { + WriteFromByteToPointer(&DB.Metadata.File, &Byte, *Parent); + + db_header_project NewParent = **Parent; + --NewParent.ChildCount; + fwrite(&NewParent, sizeof(db_header_project), 1, DB.Metadata.File.Handle); + Byte += sizeof(db_header_project); + } - fwrite(&NewParent, sizeof(db_header_project), 1, DB.Metadata.File.Handle); - Byte += sizeof(db_header_project); DeleteProjectInterior(Child, G, &Byte); - *Parent = (db_header_project *)(DB.Metadata.File.Buffer.Location + PPos); + if(GotBlock) + { + *Block = (db_block_projects *)(DB.Metadata.File.Buffer.Location + PPos); + } + else + { + *Parent = (db_header_project *)(DB.Metadata.File.Buffer.Location + PPos); + } *Child = (db_header_project *)(DB.Metadata.File.Buffer.Location + CPos); } -void SyncProjects(project_generations *G, project *C, db_header_project **SParent, db_header_project **SChild); -void SyncProjects_TopLevel(project_generations *G, project *C, db_block_projects **SParent, db_header_project **SChild); +void SyncProjects(project_generations *G, project *C, db_block_projects **Block, db_header_project **SParent, db_header_project **SChild); db_landmark * DetermineFirstLandmarkAndRangeOfProjectHierarchy(db_asset *A, @@ -15790,8 +16391,9 @@ ReorganiseProjectsInterior(project_generations *G, project *CChild, uint64_t Chi bool Result = FALSE; project_generations LocalAcc = InitAccumulator(G); AccumulateProjectIndices(&LocalAcc, SChild); + db_structure_headered_section *DBStructureProjects = GetDBStructureHeaderedSection(B_PROJ); - db_header_project *This = SkipProjectAndChildren(SChild); + db_header_project *This = SkipHeaderedSectionRecursively(SChild, DBStructureProjects); for(++ChildIndex; ChildIndex < ChildCount; ++ChildIndex) { @@ -15805,7 +16407,7 @@ ReorganiseProjectsInterior(project_generations *G, project *CChild, uint64_t Chi WriteFromByteToPointer(&DB.Metadata.File, &Byte, SChild); - char *Next = SkipProjectAndChildren(This); + char *Next = SkipHeaderedSectionRecursively(This, DBStructureProjects); db_block_assets *AssetsBlock = LocateBlock(B_ASET); db_asset *Asset = LocateFirstAsset(AssetsBlock); @@ -15840,7 +16442,7 @@ ReorganiseProjectsInterior(project_generations *G, project *CChild, uint64_t Chi db_landmark NewLandmark = *ThisLandmark; if(GenIndex < LocalAcc.EntriesInGeneration.ItemCount) { - NewLandmark.Project.Index -= *(uint32_t*)GetPlaceInBook(&LocalAcc.EntriesInGeneration, GenIndex); + NewLandmark.Index.Project.Index -= *(uint32_t*)GetPlaceInBook(&LocalAcc.EntriesInGeneration, GenIndex); } fwrite(&NewLandmark, sizeof(db_landmark), 1, DB.Metadata.File.Handle); Byte += sizeof(db_landmark); @@ -15850,13 +16452,13 @@ ReorganiseProjectsInterior(project_generations *G, project *CChild, uint64_t Chi ++LocalAccLandmarkIndex, ++RunningLandmarkIndex, ++LocalAccLandmark) { db_landmark NewLandmark = *LocalAccLandmark; - NewLandmark.Project.Index += *(uint32_t *)GetPlaceInBook(&ThisAcc.EntriesInGeneration, GenIndex); + NewLandmark.Index.Project.Index += *(uint32_t *)GetPlaceInBook(&ThisAcc.EntriesInGeneration, GenIndex); fwrite(&NewLandmark, sizeof(db_landmark), 1, DB.Metadata.File.Handle); Byte += sizeof(db_landmark); } db_landmark *TailLandmark = FirstLandmark + RunningLandmarkIndex; - for(; RunningLandmarkIndex < Asset->LandmarkCount && TailLandmark->Project.Generation == GenIndex; + for(; RunningLandmarkIndex < Asset->LandmarkCount && TailLandmark->Index.Project.Generation == GenIndex; ++RunningLandmarkIndex, ++TailLandmark) { fwrite(TailLandmark, sizeof(db_landmark), 1, DB.Metadata.File.Handle); @@ -15873,7 +16475,7 @@ ReorganiseProjectsInterior(project_generations *G, project *CChild, uint64_t Chi // Write out the landmarks for This, --ing their Project.Index by the LocalAcc[Gen].EntriesInGeneration // Write landmarks for projects in LocalAcc, ++ing their Project.Index by ThisAcc[Gen].EntriesInGeneration // Write out the remaining landmarks for this generation - Asset = SkipAsset(Asset); + Asset = SkipHeaderedSectionRecursively(Asset, GetDBStructureHeaderedSection(B_ASET)); } CycleSignpostedFile(&DB.Metadata); @@ -15885,7 +16487,7 @@ ReorganiseProjectsInterior(project_generations *G, project *CChild, uint64_t Chi { AccumulateProjectIndices(&LocalAcc, This); } - This = SkipProjectAndChildren(This); + This = SkipHeaderedSectionRecursively(This, DBStructureProjects); } FreeBook(&LocalAcc.EntriesInGeneration); @@ -15894,46 +16496,65 @@ ReorganiseProjectsInterior(project_generations *G, project *CChild, uint64_t Chi } bool -ReorganiseProjects(project_generations *G, project *CChild, db_header_project **SParent, uint64_t ChildIndex, db_header_project **SChild) +ReorganiseProjects(project_generations *G, project *CChild, + db_block_projects **Block, db_header_project **SParent, + uint64_t ChildIndex, db_header_project **SChild) { - uint64_t SParentPos = (char *)*SParent - DB.Metadata.File.Buffer.Location; - uint64_t SChildPos = (char *)*SChild - DB.Metadata.File.Buffer.Location; + bool GotBlock = Block ? TRUE : FALSE; + bool GotParent = SParent ? TRUE : FALSE; + Assert(GotBlock ^ GotParent); - bool Result = ReorganiseProjectsInterior(G, CChild, ChildIndex, (*SParent)->ChildCount, *SChild); - - if(Result == TRUE) + uint64_t ParentPos; + uint64_t ChildCount; + if(GotBlock) { - *SParent = (db_header_project *)(DB.Metadata.File.Buffer.Location + SParentPos); - *SChild = (db_header_project *)(DB.Metadata.File.Buffer.Location + SChildPos); - AddEntryToGeneration(G, CChild); - SyncProjects(G, CChild, SParent, SChild); + ParentPos = (char *)*Block - DB.Metadata.File.Buffer.Location; + ChildCount = (*Block)->Count; + } + else + { + ParentPos = (char *)*SParent - DB.Metadata.File.Buffer.Location; + ChildCount = (*SParent)->ChildCount; } - return Result; -} - -bool -ReorganiseProjects_TopLevel(project_generations *G, project *CChild, db_block_projects **SParent, uint64_t ChildIndex, db_header_project **SChild) -{ - uint64_t SParentPos = (char *)*SParent - DB.Metadata.File.Buffer.Location; uint64_t SChildPos = (char *)*SChild - DB.Metadata.File.Buffer.Location; - bool Result = ReorganiseProjectsInterior(G, CChild, ChildIndex, (*SParent)->Count, *SChild); + bool Result = ReorganiseProjectsInterior(G, CChild, ChildIndex, ChildCount, *SChild); if(Result == TRUE) { - *SParent = (db_block_projects *)(DB.Metadata.File.Buffer.Location + SParentPos); *SChild = (db_header_project *)(DB.Metadata.File.Buffer.Location + SChildPos); AddEntryToGeneration(G, CChild); - SyncProjects_TopLevel(G, CChild, SParent, SChild); + + if(GotBlock) + { + *Block = (db_block_projects *)(DB.Metadata.File.Buffer.Location + ParentPos); + } + else + { + *SParent = (db_header_project *)(DB.Metadata.File.Buffer.Location + ParentPos); + } + SyncProjects(G, CChild, Block, SParent, SChild); } return Result; } void -SyncProjects_TopLevel(project_generations *G, project *C, db_block_projects **SParent, db_header_project **SChild) +SyncProjects(project_generations *G, project *C, db_block_projects **Block, db_header_project **SParent, db_header_project **SChild) { + bool GotBlock = Block ? TRUE : FALSE; + bool GotParent = SParent ? TRUE : FALSE; + Assert(GotBlock ^ GotParent); + uint64_t SChildPos = (char *)*SChild - DB.Metadata.File.Buffer.Location; - uint64_t SParentPos = (char *)*SParent - DB.Metadata.File.Buffer.Location; + uint64_t ParentPos; + if(GotBlock) + { + ParentPos = (char *)*Block - DB.Metadata.File.Buffer.Location; + } + else + { + ParentPos = (char *)*SParent - DB.Metadata.File.Buffer.Location; + } IncrementCurrentGeneration(G); @@ -15949,83 +16570,26 @@ SyncProjects_TopLevel(project_generations *G, project *C, db_block_projects **SP { Located = TRUE; AddEntryToGeneration(G, CChild); - SyncProjects(G, CChild, SChild, &SGrandChild); + SyncProjects(G, CChild, 0, SChild, &SGrandChild); } else { - Located = ReorganiseProjects(G, CChild, SChild, ci, &SGrandChild); + Located = ReorganiseProjects(G, CChild, 0, SChild, ci, &SGrandChild); } } if(!Located) { - InsertProjectIntoDB(G, SChild, &SGrandChild, CChild); + InsertProjectIntoDB(G, 0, SChild, &SGrandChild, CChild); } - SGrandChild = SkipProjectAndChildren(SGrandChild); + SGrandChild = SkipHeaderedSectionRecursively(SGrandChild, GetDBStructureHeaderedSection(B_PROJ)); } uint64_t DeletionCount = (*SChild)->ChildCount - C->Child.ItemCount; for(int DeletionIndex = 0; DeletionIndex < DeletionCount; ++DeletionIndex) { - DeleteProject(SChild, &SGrandChild, G); - } - - if((*SChild)->ChildCount == 0 && (*SChild)->EntryCount == 0) - { - string BaseDir = Wrap0i((*SChild)->BaseDir); - string SearchLocation = Wrap0i((*SChild)->SearchLocation); - string ProjectID = Wrap0i((*SChild)->ID); - DeleteSearchPageFromFilesystem(BaseDir, SearchLocation, ProjectID); - DeleteLandmarksForSearch(C->Index); - DeleteStaleAssets(); - } - - DecrementCurrentGeneration(G); - *SParent = (db_block_projects *)(DB.Metadata.File.Buffer.Location + SParentPos); - *SChild = (db_header_project *)(DB.Metadata.File.Buffer.Location + SChildPos); -} - -void -SyncProjects(project_generations *G, project *C, db_header_project **SParent, db_header_project **SChild) -{ - uint64_t SChildPos = (char *)*SChild - DB.Metadata.File.Buffer.Location; - uint64_t SParentPos = (char *)*SParent - DB.Metadata.File.Buffer.Location; - - IncrementCurrentGeneration(G); - - db_header_project *SGrandChild = LocateFirstChildProject(*SChild); - - for(int ci = 0; ci < C->Child.ItemCount; ++ci) - { - bool Located = FALSE; - project *CChild = GetPlaceInBook(&C->Child, ci); - if(ci < (*SChild)->ChildCount) - { - if(ConfiguredAndStoredProjectIDsMatch(CChild, SGrandChild)) - { - Located = TRUE; - AddEntryToGeneration(G, CChild); - SyncProjects(G, CChild, SChild, &SGrandChild); - } - else - { - Located = ReorganiseProjects(G, CChild, SChild, ci, &SGrandChild); - } - } - - if(!Located) - { - InsertProjectIntoDB(G, SChild, &SGrandChild, CChild); - } - - SGrandChild = SkipProjectAndChildren(SGrandChild); - } - - uint64_t DeletionCount = (*SChild)->ChildCount - C->Child.ItemCount; - for(int DeletionIndex = 0; DeletionIndex < DeletionCount; ++DeletionIndex) - { - DeleteProject(SChild, &SGrandChild, G); + DeleteProject(0, SChild, &SGrandChild, G); } if((*SChild)->ChildCount == 0 && (*SChild)->EntryCount == 0) @@ -16039,7 +16603,14 @@ SyncProjects(project_generations *G, project *C, db_header_project **SParent, db } DecrementCurrentGeneration(G); - *SParent = (db_header_project *)(DB.Metadata.File.Buffer.Location + SParentPos); + if(GotBlock) + { + *Block = (db_block_projects *)(DB.Metadata.File.Buffer.Location + ParentPos); + } + else + { + *SParent = (db_header_project *)(DB.Metadata.File.Buffer.Location + ParentPos); + } *SChild = (db_header_project *)(DB.Metadata.File.Buffer.Location + SChildPos); } @@ -16070,26 +16641,26 @@ SyncDB(config *C) { Located = TRUE; AddEntryToGeneration(&Accumulator, CChild); - SyncProjects_TopLevel(&Accumulator, CChild, &SParent, &SChild); + SyncProjects(&Accumulator, CChild, &SParent, 0, &SChild); } else { - Located = ReorganiseProjects_TopLevel(&Accumulator, CChild, &SParent, ci, &SChild); + Located = ReorganiseProjects(&Accumulator, CChild, &SParent, 0, ci, &SChild); } } if(!Located) { - InsertProjectIntoDB_TopLevel(&Accumulator, &SParent, &SChild, CChild); + InsertProjectIntoDB(&Accumulator, &SParent, 0, &SChild, CChild); } - SChild = SkipProjectAndChildren(SChild); + SChild = SkipHeaderedSectionRecursively(SChild, GetDBStructureHeaderedSection(B_PROJ)); } uint64_t DeletionCount = SParent->Count - C->Project.ItemCount; for(int DeletionIndex = 0; DeletionIndex < DeletionCount; ++DeletionIndex) { - DeleteProject_TopLevel(&SParent, &SChild, &Accumulator); + DeleteProject(&SParent, 0, &SChild, &Accumulator); } DeleteStaleAssets(); @@ -16105,7 +16676,7 @@ SyncDB(config *C) void SyncGlobalPagesWithInput(neighbourhood *N, buffers *CollationBuffers) { - MEM_TEST_TOP("SyncGlobalPagesWithInput"); + MEM_TEST_TOP(); db_block_projects *ProjectsBlock = DB.Metadata.Signposts.ProjectsBlock.Ptr; string StoredGlobalSearchDir = Wrap0i(ProjectsBlock->GlobalSearchDir); string StoredGlobalSearchURL = Wrap0i(ProjectsBlock->GlobalSearchURL); @@ -16146,7 +16717,7 @@ SyncGlobalPagesWithInput(neighbourhood *N, buffers *CollationBuffers) } // TODO(matt): Come back to this! Free(StoredGlobalSearchDir0); - MEM_TEST_END("SyncGlobalPagesWithInput"); + MEM_TEST_END(); } void @@ -16258,12 +16829,12 @@ PackTemplates(neighbourhood *N) void SyncProject(project *P, neighbourhood *N, buffers *CollationBuffers, template *BespokeTemplate, bool *Titled) { - MEM_TEST_TOP("SyncProject()"); + MEM_TEST_TOP(); for(int i = 0; i < P->Child.ItemCount; ++i) { - /* */ MEM_TEST_MID("SyncProject()"); + /* */ MEM_TEST_MID(); /* +MEM */ SyncProject(GetPlaceInBook(&P->Child, i), N, CollationBuffers, BespokeTemplate, Titled); - /* */ MEM_TEST_MID("SyncProject()"); + /* */ MEM_TEST_MID(); } SetCurrentProject(P, N); @@ -16283,12 +16854,12 @@ SyncProject(project *P, neighbourhood *N, buffers *CollationBuffers, template *B PrintLineage(P->Lineage, FALSE); fprintf(stderr, " ───╼\n"); - /* */ MEM_TEST_MID("SyncProject()"); + /* */ MEM_TEST_MID(); /* +MEM */ SyncDBWithInput(N, CollationBuffers, BespokeTemplate); - /* */ MEM_TEST_MID("SyncProject()"); + /* */ MEM_TEST_MID(); PushWatchHandle(P->HMMLDir, EXT_HMML, WT_HMML, P, 0); - MEM_TEST_END("SyncProject()"); + MEM_TEST_END(); } char *inotifyEventStrings[] = @@ -16368,11 +16939,11 @@ rc InitAll(neighbourhood *Neighbourhood, buffers *CollationBuffers, template *BespokeTemplate) { rc Result = RC_SUCCESS; - MEM_TEST_TOP("InitAll()"); + MEM_TEST_TOP(); RewindCollationBuffers(CollationBuffers); - /* */ MEM_TEST_MID("InitAll()"); + /* */ MEM_TEST_MID(); /* +MEM */ Result = InitDB(); - /* */ MEM_TEST_MID("InitAll()"); + /* */ MEM_TEST_MID(); if(Result == RC_SUCCESS) { @@ -16391,9 +16962,9 @@ InitAll(neighbourhood *Neighbourhood, buffers *CollationBuffers, template *Bespo bool TitledSync = FALSE; for(int i = 0; i < Config->Project.ItemCount; ++i) { - /* */ MEM_TEST_MID("InitAll()"); + /* */ MEM_TEST_MID(); /* +MEM */ SyncProject(GetPlaceInBook(&Config->Project, i), Neighbourhood, CollationBuffers, BespokeTemplate, &TitledSync); - /* */ MEM_TEST_MID("InitAll()"); + /* */ MEM_TEST_MID(); } SyncGlobalPagesWithInput(Neighbourhood, CollationBuffers); @@ -16405,7 +16976,7 @@ InitAll(neighbourhood *Neighbourhood, buffers *CollationBuffers, template *Bespo DeleteStaleAssets(); //PrintAssetsBlock(0); - MEM_TEST_END("InitAll()"); + MEM_TEST_END(); if(GlobalRunning && inotifyInstance != -1) { @@ -16729,7 +17300,7 @@ Exit(void) { PrintC(CS_SUCCESS, "\nExiting cleanly. Thank you for indexing with Cinera\n"); } - _exit(0); + _exit(RC_SUCCESS); } void @@ -16763,7 +17334,13 @@ InitInterruptHandler(void) int main(int ArgC, char **Args) { - MEM_TEST_TOP("main()"); + InitDBStructures(); +#if 0 + PrintDBStructures(stderr); + _exit(1); +#endif + + MEM_TEST_TOP(); InitInterruptHandler(); Assert(ArrayCount(BufferIDStrings) == BID_COUNT); Assert(ArrayCount(TemplateTags) == TEMPLATE_TAG_COUNT); @@ -16782,18 +17359,17 @@ main(int ArgC, char **Args) case 'v': PrintVersions(); _exit(RC_SUCCESS); - break; case 'h': default: - PrintHelp(Args[0], ConfigPath); - return RC_SUCCESS; + PrintHelp(); + _exit(RC_SUCCESS); } } // NOTE(matt): Init MemoryArenas (they are global) - MEM_TEST_MID("main()"); + MEM_TEST_MID(); InitMemoryArena(&MemoryArena, Megabytes(4)); - MEM_TEST_MID("main()"); + MEM_TEST_MID(); ConfigPath = ExpandPath(Wrap0(ConfigPath), 0); if(ConfigPath) @@ -16846,8 +17422,13 @@ main(int ArgC, char **Args) { if(Mode & MODE_EXAMINE) { - // TODO(matt): Allow optionally passing a .db file as an argument? - ExamineDB(); + DB.Metadata.File.Buffer.ID = BID_DATABASE; + DB.Metadata.File = InitFile(0, &Config->DatabaseLocation, EXT_NULL, TRUE); + ReadFileIntoBuffer(&DB.Metadata.File); // NOTE(matt): Could we actually catch errors (permissions?) here and bail? + + ExamineDB(&DB.Metadata.File); + + FreeFile(&DB.Metadata.File, TRUE); _exit(RC_SUCCESS); } @@ -16857,16 +17438,16 @@ main(int ArgC, char **Args) } else { - /* */ MEM_TEST_MID("main()"); + /* */ MEM_TEST_MID(); /* +MEM */ InitAll(&Neighbourhood, &CollationBuffers, &BespokeTemplate); - /* */ MEM_TEST_MID("main()"); + /* */ MEM_TEST_MID(); } } else if(SeekConfirmation("Print config help?", TRUE)) { if(ArgC < 2) { - PrintHelp(Args[0], ConfigPath); + PrintHelp(); } else { @@ -16902,7 +17483,11 @@ main(int ArgC, char **Args) } DiscardAllAndFreeConfig(); - MEM_TEST_END("main()"); + MEM_TEST_END(); + } + else + { + SystemError(0, 0, S_ERROR, "Config file path cannot be empty, aborting", 0); } Exit(); }