parser.cpp

Go to the documentation of this file.
00001 /* libobby - Network text editing library
00002  * Copyright (C) 2005 0x539 dev group
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This program 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.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public
00015  * License along with this program; if not, write to the Free
00016  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 #include <fstream>
00020 #include "common.hpp"
00021 #include "format_string.hpp"
00022 #include "serialise/error.hpp"
00023 #include "serialise/parser.hpp"
00024 
00025 obby::serialise::parser::parser()
00026 {
00027 }
00028 
00029 void obby::serialise::parser::deserialise(const std::string& file)
00030 {
00031         std::ifstream in(file.c_str() );
00032 
00033         if(!in)
00034         {
00035                 obby::format_string str(_(
00036                         "Could not open file '%0%' for reading"
00037                 ) );
00038 
00039                 str << file;
00040                 throw error(str.str(), 0);
00041         }
00042 
00043         deserialise(in);
00044 }
00045 
00046 void obby::serialise::parser::deserialise(std::istream& stream)
00047 {
00048         const unsigned int bufsize = 1024;
00049         char readbuf[bufsize];
00050         std::string result;
00051 
00052         // Initial preallocation
00053         result.reserve(bufsize << 3);
00054 
00055 #ifdef WIN32
00056         // Other effort (see below) seems not to work on WIN32, the eofflag is
00057         // set after the first 1024 Bytes have been read. Is this a bug in
00058         // mingw?
00059         std::string line;
00060         while(std::getline(stream, line) )
00061         {
00062                 // More preallocation, if the following line exceeds the
00063                 // current capacity
00064                 if(result.capacity() < result.length() + bufsize)
00065                         result.reserve(result.capacity() * 2);
00066 
00067                 result += line;
00068                 result += '\n';
00069         }
00070 #else
00071         while(stream)
00072         {
00073                 // More preallocation, if the following 1024 byte exceeds the
00074                 // current capacity
00075                 if(result.capacity() < result.length() + bufsize)
00076                         result.reserve(result.capacity() * 2);
00077 
00078                 // Read data, append to resulting string
00079                 stream.read(readbuf, bufsize);
00080                 result.append(readbuf, stream.gcount() );
00081         }
00082 #endif
00083 
00084         deserialise_memory(result);
00085 }
00086 
00087 void obby::serialise::parser::deserialise_memory(const std::string& mem)
00088 {
00089         token_list list;
00090         list.deserialise(mem);
00091         token_list::iterator iter = list.begin();
00092 
00093         // Get initial '!'
00094         if(iter->get_type() != token::TYPE_EXCLAMATION)
00095         {
00096                 throw error(
00097                         _("Expected initial exclamation mark"),
00098                         iter->get_line()
00099                 );
00100         }
00101         list.next_token(iter);
00102 
00103         // Read document type
00104         if(iter->get_type() != token::TYPE_IDENTIFIER)
00105         {
00106                 throw error(
00107                         _("Expected document type after '!'"),
00108                         iter->get_line()
00109                 );
00110         }
00111         m_type = iter->get_text();
00112         list.next_token(iter);
00113 
00114         // Get indentation for following object
00115         if(iter->get_type() != token::TYPE_INDENTATION)
00116         {
00117                 throw error(
00118                         _("Expected newline after document type"),
00119                         iter->get_line()
00120                 );
00121         }
00122 
00123         // Must be top-level (indentation == 0)
00124         if(iter->get_text().length() > 0)
00125         {
00126                 throw error(
00127                         _("Expected top-level object after document type"),
00128                         iter->get_line()
00129                 );
00130         }
00131         list.next_token(iter);
00132 
00133         // Root object should follow
00134         if(iter->get_type() != token::TYPE_IDENTIFIER)
00135         {
00136                 throw error(
00137                         _("Expected root object after document type"),
00138                         iter->get_line()
00139                 );
00140         }
00141 
00142         m_object.deserialise(list, iter);
00143 
00144         // Must be EOF now
00145         if(iter != list.end() )
00146         {
00147                 format_string str(_("Expected end of input instead of '%0%'") );
00148                 str << iter->get_text();
00149                 throw error(str.str(), iter->get_line() );
00150         }
00151 }
00152 
00153 void obby::serialise::parser::serialise(const std::string& file) const
00154 {
00155         std::ofstream out(file.c_str() );
00156         if(!out)
00157         {
00158                 obby::format_string str(
00159                         _("Could not open file '%0%' for writing")
00160                 );
00161 
00162                 str << file;
00163                 throw std::runtime_error(str.str() );
00164         }
00165 
00166         serialise(out);
00167 }
00168 
00169 void obby::serialise::parser::serialise(std::ostream& stream) const
00170 {
00171         // Get string
00172         std::string result;
00173         serialise_memory(result);
00174 
00175         // Write it into the file
00176         stream << result;
00177         stream.flush();
00178 }
00179 
00180 void obby::serialise::parser::serialise_memory(std::string& mem) const
00181 {
00182         // Empty list
00183         token_list list;
00184 
00185         // Add document type
00186         list.add(token::TYPE_EXCLAMATION, "!", 0);
00187         list.add(token::TYPE_IDENTIFIER, m_type, 0);
00188 
00189         // Add top-level indentation
00190         list.add(token::TYPE_INDENTATION, "", 0);
00191 
00192         // Serialise root object with its children
00193         m_object.serialise(list);
00194         list.serialise(mem);
00195 }
00196 
00197 const std::string& obby::serialise::parser::get_type() const
00198 {
00199         return m_type;
00200 }
00201 
00202 void obby::serialise::parser::set_type(const std::string& type)
00203 {
00204         m_type = type;
00205 }
00206 
00207 const obby::serialise::object& obby::serialise::parser::get_root() const
00208 {
00209         return m_object;
00210 }
00211 
00212 obby::serialise::object& obby::serialise::parser::get_root()
00213 {
00214         return m_object;
00215 }

Generated on Fri Jan 11 10:01:32 2008 for obby by  doxygen 1.5.1