libs/EDoc/Location.cpp

Go to the documentation of this file.
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 #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    /** \brief define a small macro that is called upon a merge error.
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          // Assign merge the filename.
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    //@@@Brendon Possibly use special C++ type conversion functions.
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 

Generated on Tue Jan 20 18:26:07 2009 for EDoc-0.2.1 by  doxygen 1.5.1