From b8f143e3502f618f773223d4d5370de307942e44 Mon Sep 17 00:00:00 2001 From: Matt Mascarenhas Date: Mon, 19 Sep 2022 17:22:19 +0100 Subject: [PATCH] cinera: Add database structure specification This commit aims to generalise database structures such that any block may be traversed without the need for specific functions for each type. Concretely, it replaces functions like SkipAsset() and SkipProject() with a generic SkipHeaderedSectionRecursively(). The change also paves the way for the plethora of new block types due in CINERA_DB_VERSION 6. --- cinera/cinera.c | 1561 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 1073 insertions(+), 488 deletions(-) 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(); }