00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "config.h"
00020
00021 #include "EDoc/Location.h"
00022 #include "EDoc/PersistenceIFace.h"
00023 #include "EDoc/File.h"
00024 #include "EDoc/Dictionary.h"
00025 #include "EDoc/Logger.h"
00026 #include "EDoc/exceptions.h"
00027 #include "EDoc/PStack.h"
00028 #include "EDoc/StackRef.h"
00029
00030 #include "EDoc/persistence_data.h"
00031 #include "IndexedDictionary.h"
00032
00033 namespace EDoc
00034 {
00035
00036 Location::Location(Dictionary* dict_in) :
00037 DictionarySpecific(dict_in),
00038 file(NULL),
00039 line(0)
00040 {
00041 file = dict.files.AlwaysGet("");
00042 }
00043
00044 Location::Location(const Location& right) :
00045 DictionarySpecific(&right.dict),
00046 file(right.file),
00047 line(right.line)
00048 {
00049 }
00050
00051 Location::Location(const Location& right, Dictionary& dict_in) :
00052 DictionarySpecific(&dict_in),
00053 file(NULL),
00054 line(right.line)
00055 {
00056 if (right.file)
00057 {
00058 file = dict.files.AlwaysGet(*right.file);
00059 }
00060 }
00061
00062 Location& Location::operator=(const Location& right)
00063 {
00064 if (this == &right)
00065 {
00066 return *this;
00067 }
00068
00069 file = NULL;
00070 if (right.file)
00071 {
00072 file = dict.files.AlwaysGet(*right.file);
00073 }
00074 line = right.line;
00075
00076 return *this;
00077 }
00078
00079 void Location::Read(PersistenceIFace& file, IndexedDictionary& idict)
00080 {
00081 Location::file = idict.files.AlwaysGet(
00082 file.ReadUInt32(KEY_SOURCE_FILE_NAME));
00083 line = file.ReadUInt32(KEY_SOURCE_LINE_NUMBER);
00084 }
00085
00086 void Location::Write(PersistenceIFace& file) const
00087 {
00088 file.WriteUInt32Debug(KEY_SOURCE_FILE_NAME,
00089 Location::file->GetIndex(), Location::file->name);
00090 file.WriteUInt32(KEY_SOURCE_LINE_NUMBER, line);
00091 }
00092
00093
00094
00095 #define EDOC_MERGE_ERROR(Message) \
00096 EDOC_Error(Message); \
00097 EDOC_THROW_EXCEPTION(MergeException, "Failed merging location.", Message);
00098
00099 void Location::Merge(const Location& right)
00100 {
00101 if (file->GetKeyName() == "")
00102 {
00103
00104 file = dict.files.AlwaysGet(*right.file);
00105 }
00106 else if ((right.file->GetKeyName() != "") &&
00107 (file->GetKeyName() != right.file->GetKeyName()))
00108 {
00109 EDOC_MERGE_ERROR("Unable to merge two locations with different "
00110 "file names.");
00111 }
00112
00113 if (line == 0)
00114 {
00115 line = right.line;
00116 }
00117 else if (right.line && line != right.line)
00118 {
00119 EDOC_MERGE_ERROR("Unable to merge two locations with different "
00120 "line numbers.");
00121 }
00122 }
00123
00124 bool Location::operator==(const Location& right) const
00125 {
00126 return ((line == right.line) &&
00127 file->GetName() == right.file->GetName());
00128 }
00129
00130 std::ostream& Location::Print(std::ostream& out, std::string prefix) const
00131 {
00132 out << prefix << "File: " << file->GetName() << std::endl;
00133 out << prefix << "Line: " << line << std::endl;
00134 return out;
00135 }
00136
00137 std::ostream& Location::SingleLinePrint(std::ostream& out) const
00138 {
00139 out << file->GetName() << ":" << line;
00140 return out;
00141 }
00142
00143
00144 #define EDOC_REPLACE(DataType, Data, From, To, Count) \
00145 if ((void*)Data == From) {Data = (DataType*)To; Count++;}
00146
00147 size_t Location::ReplaceReferences(PStack& stack, void* remove,
00148 void* replace)
00149 {
00150 size_t count = 0;
00151 if (!stack.Push(this))
00152 {
00153 return count;
00154 }
00155
00156 EDOC_REPLACE(File, file, remove, replace, count);
00157
00158 return count;
00159 }
00160
00161 void Location::Validate(PStack& stack, const Dictionary& dict_in) const
00162 {
00163 StackRef ref(stack, this);
00164 if (!ref)
00165 {
00166 return;
00167 }
00168
00169 EDOC_ASSERT(&dict == &dict_in, "");
00170 file->Validate(stack, dict_in);
00171 }
00172
00173 bool Location::operator<(const Location& right) const
00174 {
00175 if (line < right.line)
00176 {
00177 return true;
00178 }
00179 else if (line > right.line)
00180 {
00181 return false;
00182 }
00183
00184 return file->GetName() < right.file->GetName();
00185 }
00186
00187 }
00188