00001 /******************************************************************************* 00002 00003 Copyright (C) 2007 by Brendon Costa 00004 00005 This library is free software; you can redistribute it and/or modify 00006 it under the terms of the "LGPL Like" License defined in the file COPYING 00007 that should have been distributed along with this source. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 You should have received a copy of the "LGPL Like" License 00014 along with this library; see the file COPYING. if not, it can be 00015 obtained from the EDoc++ website: 00016 http://edoc.sourceforge.net/license.html 00017 00018 *******************************************************************************/ 00019 #ifndef EDOC_DICTIONARYSPECIFIC_H 00020 #define EDOC_DICTIONARYSPECIFIC_H 00021 00022 #include "EDoc/stdint.h" 00023 #include <string> 00024 #include <iostream> 00025 00026 00027 namespace EDoc 00028 { 00029 class Dictionary; 00030 class PStack; 00031 class ManagedObject; 00032 00033 00034 //=========================================================================== 00035 /** \brief Encapsulates functionality common to all dictionary specific 00036 * types. 00037 * 00038 * A dictionary specific type is a type/class which "belongs" to a particular 00039 * instance of the Dictionary class. Objects that belong to one dictionary 00040 * can NOT be referenced by object from another dictionary. They need to be 00041 * specially copied/merged. For this reason there is special processing that 00042 * occurs for assignment and copies of dictionary specific objects to ensure 00043 * that these rules are not violated. 00044 * 00045 * 00046 * HISTORY 00047 * 00048 * This was done because the other option was to use identifiers and lookups 00049 * or copies of all the data. Initially this was attempted but processing 00050 * time and memory usage were enormous, so the method was changed in order to 00051 * store pointers directly to members. However objects can only store 00052 * pointers to other members that belong to the same Dictionary instance. 00053 * This means that when a dictionary object is destroyed along with all 00054 * objects that "belong" to it, no other objects are invalidated. 00055 * 00056 * As a result this class was created in order to simplify management of 00057 * these objects. 00058 * 00059 * All DictionarySpecific objects have functionality to replace pointer 00060 * references and to validate themselves. 00061 * 00062 * \see See Dictionary. 00063 */ 00064 class DictionarySpecific 00065 { 00066 friend class ManagedObject; 00067 public: 00068 00069 //------------------------------------------------------------------------ 00070 /** \brief Create this dictionary specific object belonging to the given 00071 * dictionary. 00072 * 00073 * \param dict_in The dictionary that this object will belong to 00074 * if NULL then will use the dictionary that can be obtained by: 00075 * GetCurrentDictionaryAssert() 00076 */ 00077 DictionarySpecific(Dictionary* dict_in); 00078 00079 //------------------------------------------------------------------------ 00080 /** \brief Destructor. 00081 */ 00082 virtual ~DictionarySpecific() {} 00083 00084 //------------------------------------------------------------------------ 00085 /** \brief Replaces all references of pointers referencing remove with 00086 * pointers to replace. 00087 * 00088 * The replacement is used because when after Read()'ing it is possible to 00089 * have two instances of an object indexed by the same key. The contents 00090 * of them must be merged and all references to one object be changed to 00091 * reference the other. Then the now unreferenced object would be deleted. 00092 * This is a part of the loading phase and is a result of the fact that 00093 * GCC can generate multiple tree nodes for a single type. Thus when 00094 * loading we often get the same type multiple times. 00095 * 00096 * \todo As an option in the future we may choose to allow replace to be a 00097 * NULL pointer. In which case it will completely erase references to a 00098 * particular object instead of having to replace them with something 00099 * else. This works for containers, but for non-optional fixed pointers it 00100 * may cause some problems. Maybe in these cases, we should throw an 00101 * exception that indicates to the user that they cant just erase that 00102 * reference, they must at least replace it in some places with something 00103 * or first erase other nodes that reference it first. This exception 00104 * would need to include as its data a reference to the object that cant 00105 * release its reference to "remove". 00106 */ 00107 virtual size_t ReplaceReferences(PStack& stack, 00108 void* remove, void* replace) = 0; 00109 00110 //------------------------------------------------------------------------ 00111 /** \brief Print the current object to the given stream in a user readable 00112 * manner. 00113 * 00114 * \param out The stream to print to. 00115 * 00116 * \param prefix A string prefix to display at the start of every line. As 00117 * an example this can be used in order to indent the print by passing 00118 * "\t" as the string. 00119 */ 00120 virtual std::ostream& Print(std::ostream& out, 00121 std::string prefix="") const = 0; 00122 00123 //------------------------------------------------------------------------ 00124 /** \brief Returns a string representing the current object in a user 00125 * readable manner. 00126 * 00127 * This will return as a string exactly what Print() would display. This 00128 * is primarily here for use from within python and for debugging. 00129 */ 00130 std::string ToString(std::string prefix="") const; 00131 00132 //------------------------------------------------------------------------ 00133 /** \brief Performs internal valtidation on the current object and will 00134 * throw a BugException if the validation fails. 00135 * 00136 * This is primarily used to ensure that all DictionarySpecific objects 00137 * are internally consistent, not referencing dictionaries that they 00138 * actually do not belong to. It is also used for a few other validations 00139 * too that if they fail would indicate a bug in the code somewhere. 00140 */ 00141 virtual void Validate(PStack& stack, const Dictionary& dict_in) const = 0; 00142 00143 //------------------------------------------------------------------------ 00144 00145 protected: 00146 00147 //------------------------------------------------------------------------ 00148 /** \brief A reference to the dictionary this object belongs to. 00149 */ 00150 Dictionary& dict; 00151 00152 //------------------------------------------------------------------------ 00153 00154 private: 00155 00156 //------------------------------------------------------------------------ 00157 /** \brief COPY DISALLOWED. 00158 */ 00159 DictionarySpecific(const DictionarySpecific& right); 00160 00161 //------------------------------------------------------------------------ 00162 /** \brief ASSIGNMENT DISALLOWED. 00163 */ 00164 DictionarySpecific& operator=(const DictionarySpecific& right); 00165 00166 //------------------------------------------------------------------------ 00167 }; 00168 //=========================================================================== 00169 } 00170 00171 namespace std 00172 { 00173 //=========================================================================== 00174 /** \brief See DictionarySpecific::Print() 00175 */ 00176 static inline std::ostream& operator<<(std::ostream& out, 00177 const EDoc::DictionarySpecific& value) 00178 { 00179 return value.Print(out); 00180 } 00181 //=========================================================================== 00182 } 00183 00184 #endif // EDOC_DICTIONARYSPECIFIC_H