#include "munga.h" #pragma hdrstop #include "objstrm.h" #include "fileutil.h" #include "resource.h" #include "cstr.h" #include "namelist.h" #include "notation.h" //############################################################################# //########################## ObjectStream ############################### //############################################################################# ObjectID ObjectStream::lastObjectID = NullObjectID; // //############################################################################# // ObjectStream //############################################################################# // ObjectStream::ObjectStream() { resourceFile = NULL; macroSocket = NULL; } // //############################################################################# // ObjectStream //############################################################################# // ObjectStream::ObjectStream( void *stream_start, size_t stream_size ): DynamicMemoryStream(stream_start, stream_size) { resourceFile = NULL; macroSocket = NULL; } // //############################################################################# // ObjectStream //############################################################################# // ObjectStream::ObjectStream(ResourceDescription *resource_description): DynamicMemoryStream( resource_description->resourceAddress, resource_description->resourceSize ) { resourceFile = NULL; macroSocket = NULL; } // //############################################################################# // ~ObjectStream //############################################################################# // ObjectStream::~ObjectStream() { Verify(resourceFile == NULL); Verify(macroSocket == NULL); } // //############################################################################# // TestInstance //############################################################################# // Logical ObjectStream::TestInstance() const { DynamicMemoryStream::TestInstance(); if (resourceFile != NULL) { Check(resourceFile); } if (macroSocket != NULL) { Check(macroSocket); } return True; } // //############################################################################# // MakeUniqueObjectID //############################################################################# // ObjectID ObjectStream::MakeUniqueObjectID() { lastObjectID++; Verify(lastObjectID < ULONG_MAX); return lastObjectID; } // //############################################################################# // CreateObjects //############################################################################# // void ObjectStream::CreateObjects() { Check(this); // //-------------------------------------------------------------------------- // While the stream is not empty, read objects... //-------------------------------------------------------------------------- // while (GetBytesRemaining() > 0L) { // //----------------------------------------------------------------------- // Read the class ID and object ID //----------------------------------------------------------------------- // Enumeration class_ID; ObjectID object_ID; MemoryStream_Read(this, &class_ID); MemoryStream_Read(this, &object_ID); RewindPointer(sizeof(object_ID)); RewindPointer(sizeof(class_ID)); Verify(class_ID != RegisteredClass::NullClassID); Verify(object_ID != NullObjectID); // //----------------------------------------------------------------------- // Read the object //----------------------------------------------------------------------- // RegisteredClass *object = MakeObjectImplementation(class_ID); Register_Object(object); // //----------------------------------------------------------------------- // Perform post creation processing //----------------------------------------------------------------------- // CreatedObjectImplementation(object, object_ID); } } // //############################################################################# // MakeObject //############################################################################# // RegisteredClass* ObjectStream::MakeObjectImplementation(Enumeration class_ID) { Check(this); Verify(class_ID != RegisteredClass::NullClassID); // //----------------------------------------------------------------------- // HACK - Constructors should be referenced through registration, for // now just use a switch statement //----------------------------------------------------------------------- // RegisteredClass *object = NULL; switch (class_ID) { default: Dump(class_ID); Fail("ObjectStream::MakeObject - Unknown class ID"); break; } return object; } // //############################################################################# // CreatedObject //############################################################################# // void ObjectStream::CreatedObjectImplementation( RegisteredClass*, ObjectID ) { Check(this); // // Default behavior is to do nothing // } // //############################################################################# // BuildFromNotationFile //############################################################################# // void ObjectStream::BuildFromNotationFile( NotationFile *notation_file, ResourceFile *resource_file ) { Check(this); Check(notation_file); Check(resource_file); // // Remember resource file // Verify(resourceFile == NULL); resourceFile = resource_file; // // Make the macro socket // macroSocket = new MacroSocket(NULL, True); Register_Object(macroSocket); // // Parse... // ParseNotationFile(notation_file); // // Delete macros // { MacroIterator iterator(macroSocket); iterator.DeletePlugs(); } // // Clean up // Unregister_Object(macroSocket); delete macroSocket; macroSocket = NULL; resourceFile = NULL; } // //############################################################################# // ParseNotationFile //############################################################################# // void ObjectStream::ParseNotationFile(NotationFile *notation_file) { Check(this); Check(notation_file); Verify(DoesNotationFileExist(notation_file)); // //-------------------------------------------------------------------------- // Parse pages //-------------------------------------------------------------------------- // NameList *page_name_list; NameList::Entry *page_entry; page_name_list = notation_file->MakePageList(); Register_Object(page_name_list); page_entry = page_name_list->GetFirstEntry(); while (page_entry != NULL) { Check(page_entry); // //----------------------------------------------------------------------- // Read the page name //----------------------------------------------------------------------- // CString inculde_name_string("include"); CString macro_name_string("macro"); CString page_name_string; Check_Pointer(page_entry->GetName()); page_name_string = page_entry->GetName(); // //----------------------------------------------------------------------- // Skip "no-ops" //----------------------------------------------------------------------- // if (page_name_string.operator [](0) == '!') { page_entry = page_entry->GetNextEntry(); continue; } // //----------------------------------------------------------------------- // Make the entry list //----------------------------------------------------------------------- // NameList *entry_list = notation_file->MakeEntryList( (NotationFile::NotePage*)page_entry->GetData() ); Register_Object(entry_list); // //----------------------------------------------------------------------- // Read "included" files //----------------------------------------------------------------------- // if (page_name_string == inculde_name_string) { ReadIncludedFiles(entry_list); } // //----------------------------------------------------------------------- // Read "macros" //----------------------------------------------------------------------- // else if (page_name_string == macro_name_string) { ReadMacros(entry_list); } // //----------------------------------------------------------------------- // Read the class ID and object name //----------------------------------------------------------------------- // else { Tell(" Class " << page_name_string << "\n"); // // Get class ID and object ID // Enumeration class_ID; ObjectID object_ID; class_ID = RegisteredClass::GetClassID(page_name_string); if (class_ID == RegisteredClass::NullClassID) { Dump(page_name_string); Dump(class_ID); } Verify(class_ID != RegisteredClass::NullClassID); object_ID = MakeUniqueObjectID(); Verify(object_ID != NullObjectID); // // Get object name // const char *object_name; CString object_name_string; PerformMacroReplacement(entry_list); if ( (object_name = (const char *)entry_list->FindData("name")) != NULL ) { object_name_string = object_name; } Check(&object_name_string); // //-------------------------------------------------------------------- // Build the object stream from the page //-------------------------------------------------------------------- // BuildFromPageImplementation(entry_list, class_ID, object_ID); CleanupMacroReplacement(entry_list); // //-------------------------------------------------------------------- // Perform post build processing //-------------------------------------------------------------------- // BuiltFromPageImplementation(class_ID, object_ID, object_name_string); } Unregister_Object(entry_list); delete entry_list; page_entry = page_entry->GetNextEntry(); } Unregister_Object(page_name_list); delete page_name_list; } // //############################################################################# // ReadIncludedFiles //############################################################################# // void ObjectStream::ReadIncludedFiles(NameList *entry_list) { Check(this); NameList::Entry *entry; Check(entry_list); entry = entry_list->GetFirstEntry(); while (entry != NULL) { Check(entry); if (entry->IsName("file")) { Check_Pointer(entry->GetChar()); CString included_file_name_string; included_file_name_string = entry->GetChar(); Tell(" File " << included_file_name_string << "\n"); NotationFile included_notation_file(included_file_name_string); Check(&included_notation_file); ParseNotationFile(&included_notation_file); } entry = entry->GetNextEntry(); } } // //############################################################################# // ReadMacros //############################################################################# // void ObjectStream::ReadMacros(NameList *entry_list) { Check(this); NameList::Entry *entry; Check(entry_list); entry = entry_list->GetFirstEntry(); while (entry != NULL) { Check(entry); if (entry->GetData() != NULL) { Check_Pointer(entry->GetName()); Check_Pointer(entry->GetChar()); CString macro_name; MacroValue *macro_value; MacroValue *current_macro_value; macro_name = entry->GetName(); macro_value = new MacroValue(entry->GetChar()); Register_Object(macro_value); Check(macroSocket); if ((current_macro_value = macroSocket->Find(macro_name)) != NULL) { Unregister_Object(current_macro_value); delete current_macro_value; } macroSocket->AddValue(macro_value, macro_name); } entry = entry->GetNextEntry(); } } // //############################################################################# // PerformMacroReplacement //############################################################################# // void ObjectStream::PerformMacroReplacement(NameList *entry_list) { Check(this); NameList::Entry *entry; Check(entry_list); entry = entry_list->GetFirstEntry(); while (entry != NULL) { Check(entry); if (entry->GetData() != NULL) { CString value_string(entry->GetChar()); // // Create a replacement string by matching each token in the // value against the tokens in the macro table // CString replacement_string; CString token_string; CString delimiter_string(","); CString empty_string; int i = 0; Check(&value_string); Check(&empty_string); while ((token_string = value_string.GetNthToken(i)) != empty_string) { Check(&token_string); // // Append delimter // if (replacement_string != empty_string) { replacement_string += delimiter_string; } // // Does a macro exist for this token? If so, use it, otherwise // use the original token // #if 0 MacroValue *macro_value; Check(macroSocket); if ((macro_value = macroSocket->Find(token_string)) != NULL) { Check(macro_value); Check(&replacement_string); replacement_string += macro_value->GetItem(); } else { replacement_string += token_string; } #else replacement_string += DeriveMacroValue(token_string); #endif i++; } // // Allocate memory for the string and assign it to the entry // size_t size; char *pointer; size = replacement_string.Length() + 1; #if 0 pointer = (char*)malloc(size); #else pointer = new char[size]; #endif Register_Pointer(pointer); Str_Copy(pointer, ((const char*)replacement_string), size); entry->dataReference = pointer; } entry = entry->GetNextEntry(); } } // //############################################################################# //############################################################################# // CString ObjectStream::DeriveMacroValue(const CString &token_string) { Check(this); Check(&token_string); MacroValue *macro_value; CString replacement_string = token_string; Check(macroSocket); while ((macro_value = macroSocket->Find(replacement_string)) != NULL) { Check(macro_value); replacement_string = macro_value->GetItem(); } return replacement_string; } // //############################################################################# // CleanupMacroReplacement //############################################################################# // void ObjectStream::CleanupMacroReplacement(NameList *entry_list) { Check(this); NameList::Entry *entry; Check(entry_list); entry = entry_list->GetFirstEntry(); while (entry != NULL) { Check(entry); if (entry->GetData() != NULL) { char *replacement_string = entry->GetChar(); Unregister_Pointer(replacement_string); #if 0 free(replacement_string); #else delete[] replacement_string; #endif } entry = entry->GetNextEntry(); } } // //############################################################################# // BuildFromPage //############################################################################# // void ObjectStream::BuildFromPageImplementation( NameList*, Enumeration class_ID, ObjectID ) { Check(this); Verify(class_ID != RegisteredClass::NullClassID); // //----------------------------------------------------------------------- // HACK - Page interpreters should be referenced through registration, // for now just use a switch statement //----------------------------------------------------------------------- // switch (class_ID) { default: Dump(class_ID); Fail("ObjectStream::BuildFromPage - Unknown class ID"); break; } } // //############################################################################# // BuiltFromPage //############################################################################# // void ObjectStream::BuiltFromPageImplementation( Enumeration, ObjectID, const CString& ) { Check(this); // // Default behavior is to do nothing // } //############################################################################# //####################### PlugStreamManager ############################# //############################################################################# PlugStreamManager PlugStreamManager::plugStreamManager; #define PLUGSTREAMMANAGER_HASHSIZE (500) // //############################################################################# // PlugStreamManager //############################################################################# // PlugStreamManager::PlugStreamManager(): plugIndex(PLUGSTREAMMANAGER_HASHSIZE, NULL, True), objectIDIndex(NULL, True) { } // //############################################################################# // ~PlugStreamManager //############################################################################# // PlugStreamManager::~PlugStreamManager() { Cleanup(); } // //############################################################################# // TestInstance //############################################################################# // Logical PlugStreamManager::TestInstance() const { Node::TestInstance(); Check(&plugIndex); Check(&objectIDIndex); return True; } // //############################################################################# // Cleanup //############################################################################# // void PlugStreamManager::Cleanup() { Check(this); // // Delete static objects // { TreeIteratorOf iterator(&objectIDIndex); Check(&iterator); iterator.DeletePlugs(); } { HashIteratorOf iterator(&plugIndex); Check(&iterator); iterator.DeletePlugs(); } } // //############################################################################# // AddPlug //############################################################################# // void PlugStreamManager::AddPlug( Plug *plug, ObjectID object_ID ) { Check(plug); Check(&plugStreamManager); plugStreamManager.plugIndex.AddValue(plug, object_ID); } // //############################################################################# // FindPlug //############################################################################# // Plug* PlugStreamManager::FindPlug(ObjectID object_ID) { Check(&plugStreamManager); return plugStreamManager.plugIndex.Find(object_ID); } // //############################################################################# // AddPlugName //############################################################################# // void PlugStreamManager::AddPlugName( ObjectID object_ID, const CString &object_name_string ) { Check(&object_name_string); ObjectIDPlug *object_ID_plug = new ObjectIDPlug(object_ID); Register_Object(object_ID_plug); Check(&plugStreamManager.objectIDIndex); #if DEBUG_LEVEL>0 if (plugStreamManager.objectIDIndex.Find(object_name_string) != NULL) { Dump(object_name_string); } #endif plugStreamManager.objectIDIndex.AddValue( object_ID_plug, object_name_string ); } // //############################################################################# // FindPlugName //############################################################################# // ObjectID PlugStreamManager::FindPlugName(const CString &object_name_string) { Check(&object_name_string); Check(&plugStreamManager.objectIDIndex); ObjectIDPlug *plug = plugStreamManager.objectIDIndex.Find(object_name_string); if (plug != NULL) { Check(plug); return plug->GetItem(); } return NullObjectID; } //############################################################################# //########################### PlugStream ################################ //############################################################################# // //############################################################################# // PlugStream //############################################################################# // PlugStream::PlugStream() { localPlugIndex = NULL; localObjectIDIndex = NULL; } // //############################################################################# // PlugStream //############################################################################# // PlugStream::PlugStream( void *stream_start, size_t stream_size ): ObjectStream(stream_start, stream_size) { localPlugIndex = NULL; localObjectIDIndex = NULL; } // //############################################################################# // PlugStream //############################################################################# // PlugStream::PlugStream(ResourceDescription *resource_description): ObjectStream(resource_description) { localPlugIndex = NULL; localObjectIDIndex = NULL; } // //############################################################################# // ~PlugStream //############################################################################# // PlugStream::~PlugStream() { Verify(localPlugIndex == NULL); Verify(localObjectIDIndex == NULL); } // //############################################################################# // TestInstance //############################################################################# // Logical PlugStream::TestInstance() const { ObjectStream::TestInstance(); if (localPlugIndex != NULL) { Check(localPlugIndex); } if (localObjectIDIndex != NULL) { Check(localObjectIDIndex); } return True; } // //############################################################################# // CreateObjects //############################################################################# // void PlugStream::CreateObjects() { Check(this); // //-------------------------------------------------------------------------- // Keep local object address index //-------------------------------------------------------------------------- // LocalPlugIndex local_index(NULL, True); Check(&local_index); localPlugIndex = &local_index; // //-------------------------------------------------------------------------- // Parse object stream //-------------------------------------------------------------------------- // ObjectStream::CreateObjects(); // //-------------------------------------------------------------------------- // Forget local object address index //-------------------------------------------------------------------------- // localPlugIndex = NULL; } // //############################################################################# // CreatedObject //############################################################################# // void PlugStream::CreatedObjectImplementation( RegisteredClass *object, ObjectID object_ID ) { Check(this); AddLocalPlug(Cast_Object(Plug*, object), object_ID); } // //############################################################################# // AddLocalPlugAddress //############################################################################# // void PlugStream::AddLocalPlug( Plug *plug, ObjectID object_ID ) { Check(this); Check(localPlugIndex); localPlugIndex->AddValue(plug, object_ID); } // //############################################################################# // AddGlobalPlugAddress //############################################################################# // void PlugStream::AddGlobalPlug( Plug *plug, ObjectID object_ID ) { Check(this); #if 0 Check(&plugStreamManager); plugStreamManager.globalPlugIndex.AddValue(plug, object_ID); #else PlugStreamManager::AddPlug(plug, object_ID); #endif } // //############################################################################# // FindPlug //############################################################################# // Plug* PlugStream::FindPlug(ObjectID object_ID) { Check(this); // //-------------------------------------------------------------------------- // Search the local address index //-------------------------------------------------------------------------- // Plug *plug; Check(localPlugIndex); if ((plug = localPlugIndex->Find(object_ID)) != NULL) { Check(plug); return plug; } // //-------------------------------------------------------------------------- // Search the global address index //-------------------------------------------------------------------------- // #if 0 Check(&plugStreamManager); if ((plug = plugStreamManager.globalPlugIndex.Find(object_ID)) != NULL) { Check(plug); return plug; } return NULL; #else if ((plug = PlugStreamManager::FindPlug(object_ID)) != NULL) { Check(plug); return plug; } return NULL; #endif } // //############################################################################# // BuildFromNotationFile //############################################################################# // void PlugStream::BuildFromNotationFile( NotationFile *notation_file, ResourceFile *resource_file ) { Check(this); Check(notation_file); Check(resource_file); // //-------------------------------------------------------------------------- // Keep local object ID index //-------------------------------------------------------------------------- // LocalObjectIDIndex local_index(NULL, True); Check(&local_index); localObjectIDIndex = &local_index; // //-------------------------------------------------------------------------- // Parse notation file //-------------------------------------------------------------------------- // ObjectStream::BuildFromNotationFile(notation_file, resource_file); // //-------------------------------------------------------------------------- // Forget local object ID index //-------------------------------------------------------------------------- // { VChainIteratorOf iterator(&local_index); Check(&iterator); iterator.DeletePlugs(); } localObjectIDIndex = NULL; } // //############################################################################# // BuiltFromPage //############################################################################# // void PlugStream::BuiltFromPageImplementation( Enumeration, ObjectID object_ID, const CString &object_name_string ) { Check(this); Check(&object_name_string); AddLocalObjectID(object_ID, object_name_string); } // //############################################################################# // AddLocalObjectID //############################################################################# // void PlugStream::AddLocalObjectID( ObjectID object_ID, const CString &object_name_string ) { Check(this); Check(&object_name_string); ObjectIDPlug *object_ID_plug = new ObjectIDPlug(object_ID); Register_Object(object_ID_plug); Check(localObjectIDIndex); #if DEBUG_LEVEL>0 if (localObjectIDIndex->Find(object_name_string) != NULL) { Dump(object_name_string); } #endif localObjectIDIndex->AddValue(object_ID_plug, object_name_string); } // //############################################################################# // AddGlobalObjectID //############################################################################# // void PlugStream::AddGlobalObjectID( ObjectID object_ID, const CString &object_name_string ) { Check(this); Check(&object_name_string); PlugStreamManager::AddPlugName(object_ID, object_name_string); } // //############################################################################# // FindObjectID //############################################################################# // ObjectID PlugStream::FindObjectID(const CString &object_name_string) { Check(this); Check(&object_name_string); // //-------------------------------------------------------------------------- // Search the local object ID index //-------------------------------------------------------------------------- // ObjectIDPlug *plug; Check(localObjectIDIndex); if ((plug = localObjectIDIndex->Find(object_name_string)) != NULL) { Check(plug); return plug->GetItem(); } // //-------------------------------------------------------------------------- // Search the global address index //-------------------------------------------------------------------------- // #if 0 Check(&plugStreamManager); plug = plugStreamManager.globalObjectIDIndex.Find(object_name_string); if (plug != NULL) { Check(plug); return plug->GetItem(); } return NULL; #else return PlugStreamManager::FindPlugName(object_name_string); #endif } // //############################################################################# // PlugStream_FindEntryAndWriteObjectID //############################################################################# // void PlugStream_FindEntryAndWriteObjectID( PlugStream *stream, NameList *name_list, const CString &entry_name ) { Check(stream); Check(name_list); Check(&entry_name); void *entry_data; CString object_name; ObjectID object_ID; entry_data = name_list->FindData(entry_name); if (entry_data == NULL) { std::cout << "PlugStream_FindEntryAndWriteObjectID - entry_name == "; std::cout << entry_name << "\n"; Fail("PlugStream_FindEntryAndWriteObjectID - entry_data == NULL"); } Check_Pointer(entry_data); object_name = (const char *)entry_data; Check(stream); object_ID = stream->FindObjectID(object_name); if (object_ID == NullObjectID) { std::cout << "PlugStream_FindEntryAndWriteObjectID - object_name == "; std::cout << object_name << "\n"; Fail("PlugStream_FindEntryAndWriteObjectID - object_ID == NullObjectID"); } Verify(object_ID != NullObjectID); MemoryStream_Write(stream, &object_ID); }