object.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 "common.hpp"
00020 #include "format_string.hpp"
00021 #include "serialise/error.hpp"
00022 #include "serialise/object.hpp"
00023 
00024 obby::serialise::object::attribute_iterator::attribute_iterator(
00025         const base_iterator& base
00026 ) :
00027         base_iterator(base)
00028 {
00029 }
00030 /*
00031 obby::serialise::object::attribute_iterator::value_type&
00032 obby::serialise::object::attribute_iterator::operator*()
00033 {
00034         return base_iterator::operator->()->second;
00035 }
00036 */
00037 const obby::serialise::object::attribute_iterator::value_type&
00038 obby::serialise::object::attribute_iterator::operator*() const
00039 {
00040         return base_iterator::operator->()->second;
00041 }
00042 /*
00043 obby::serialise::object::attribute_iterator::value_type*
00044 obby::serialise::object::attribute_iterator::operator->()
00045 {
00046         return &base_iterator::operator->()->second;
00047 }
00048 */
00049 const obby::serialise::object::attribute_iterator::value_type*
00050 obby::serialise::object::attribute_iterator::operator->() const
00051 {
00052         return &base_iterator::operator->()->second;
00053 }
00054 
00055 obby::serialise::object::object(
00056         const object* parent
00057 ) :
00058         m_parent(parent), m_name(), m_line(0)
00059 {
00060 }
00061 
00062 void obby::serialise::object::serialise(
00063         token_list& tokens
00064 ) const
00065 {
00066         // Find indentation level
00067         unsigned int indentation_deep = get_indentation();
00068 
00069         // Add object name
00070         tokens.add(token::TYPE_IDENTIFIER, m_name, 0);
00071 
00072         // Add attributes
00073         for(attribute_iterator iter = attributes_begin();
00074             iter != attributes_end();
00075             ++ iter)
00076         {
00077                 iter->serialise(tokens);
00078         }
00079 
00080         // Add children
00081         for(child_iterator iter = children_begin();
00082             iter != children_end();
00083             ++ iter)
00084         {
00085                 // Indent child to our indentation + 1
00086                 tokens.add(
00087                         token::TYPE_INDENTATION,
00088                         std::string(indentation_deep + 1, ' '),
00089                         0
00090                 );
00091 
00092                 // Serialise it
00093                 iter->serialise(tokens);
00094         }
00095 }
00096 
00097 void obby::serialise::object::deserialise(
00098         const token_list& tokens,
00099         token_list::iterator& iter
00100 )
00101 {
00102         unsigned int indentation_deep = get_indentation();
00103 
00104         // Object name
00105         m_name = iter->get_text();
00106 
00107         // Line of object declaration
00108         m_line = iter->get_line();
00109         ++ iter;
00110 
00111         // Expect any number of attributes
00112         while(iter != tokens.end() &&
00113               iter->get_type() == token::TYPE_IDENTIFIER)
00114                 m_attributes[iter->get_text()].deserialise(tokens, iter);
00115 
00116         // Indentation (for child objects)
00117         while(iter != tokens.end() &&
00118               iter->get_type() == token::TYPE_INDENTATION)
00119         {
00120                 // Get indentation of this child
00121                 unsigned int child_indentation = iter->get_text().length();
00122                 // Belongs to some super-object
00123                 if(child_indentation <= indentation_deep) break;
00124 
00125                 // Is a child
00126                 tokens.next_token(iter);
00127 
00128                 // Next token must be identifier (object name)
00129                 if(iter->get_type() == token::TYPE_IDENTIFIER)
00130                 {
00131                         if(indentation_deep != child_indentation - 1)
00132                         {
00133                                 throw error(
00134                                         _(
00135                                                 "Child object's indentation "
00136                                                 "must be parent's plus one"
00137                                         ),
00138                                         iter->get_line()
00139                                 );
00140                         }
00141 
00142                         object& child = add_child();
00143                         child.deserialise(tokens, iter);
00144                 }
00145                 else
00146                 {
00147                         throw error(
00148                                 _("Expected child object after indentation"),
00149                                 iter->get_line()
00150                         );
00151                 }
00152         }
00153 
00154         // An object _must_ follow even if it is not a child of us but one of
00155         // our parent (or grandparent...).
00156         if(iter != tokens.end() && iter->get_type() != token::TYPE_INDENTATION)
00157         {
00158                 obby::format_string str(
00159                         _("Expected child object instead of '%0%'")
00160                 );
00161                 str << iter->get_text();
00162                 throw error(str.str(), iter->get_line() );
00163         }
00164 }
00165 
00166 const obby::serialise::object* obby::serialise::object::get_parent() const
00167 {
00168         return m_parent;
00169 }
00170 
00171 obby::serialise::object& obby::serialise::object::add_child()
00172 {
00173         m_children.push_back(object(this) );
00174         return m_children.back();
00175 }
00176 
00177 const std::string& obby::serialise::object::get_name() const
00178 {
00179         return m_name;
00180 }
00181 
00182 void obby::serialise::object::set_name(
00183         const std::string& name
00184 )
00185 {
00186         m_name = name;
00187 }
00188 
00189 obby::serialise::attribute& obby::serialise::object::add_attribute(
00190         const std::string& name
00191 )
00192 {
00193         return m_attributes.insert(
00194                 std::make_pair(name, attribute(name))
00195         ).first->second;
00196 }
00197 
00198 obby::serialise::attribute*
00199 obby::serialise::object::get_attribute(const std::string& name)
00200 {
00201         attribute_map::iterator iter = m_attributes.find(name);
00202         if(iter == m_attributes.end() ) return NULL;
00203         return &iter->second;
00204 }
00205 
00206 const obby::serialise::attribute*
00207 obby::serialise::object::get_attribute(const std::string& name) const
00208 {
00209         attribute_map::const_iterator iter = m_attributes.find(name);
00210         if(iter == m_attributes.end() ) return NULL;
00211         return &iter->second;
00212 }
00213 
00214 obby::serialise::attribute&
00215 obby::serialise::object::get_required_attribute(const std::string& name)
00216 {
00217         attribute_map::iterator iter = m_attributes.find(name);
00218         if(iter == m_attributes.end() )
00219         {
00220                 format_string str(_("Object '%0%' requires attribute '%1%'") );
00221                 str << m_name << name;
00222                 throw error(str.str(), m_line);
00223         }
00224 
00225         return iter->second;
00226 }
00227 
00228 const obby::serialise::attribute&
00229 obby::serialise::object::get_required_attribute(const std::string& name) const
00230 {
00231         attribute_map::const_iterator iter = m_attributes.find(name);
00232         if(iter == m_attributes.end() )
00233         {
00234                 format_string str(_("Object '%0%' requires attribute '%1%'") );
00235                 str << m_name << name;
00236                 throw error(str.str(), m_line);
00237         }
00238 
00239         return iter->second;
00240 }
00241 
00242 obby::serialise::object::attribute_iterator
00243 obby::serialise::object::attributes_begin() const
00244 {
00245         return attribute_iterator(m_attributes.begin() );
00246 }
00247 
00248 obby::serialise::object::attribute_iterator
00249 obby::serialise::object::attributes_end() const
00250 {
00251         return attribute_iterator(m_attributes.end() );
00252 }
00253 
00254 obby::serialise::object::child_iterator
00255 obby::serialise::object::children_begin() const
00256 {
00257         return m_children.begin();
00258 }
00259 
00260 obby::serialise::object::child_iterator
00261 obby::serialise::object::children_end() const
00262 {
00263         return m_children.end();
00264 }
00265 
00266 unsigned int obby::serialise::object::get_line() const
00267 {
00268         return m_line;
00269 }
00270 
00271 unsigned int obby::serialise::object::get_indentation() const
00272 {
00273         unsigned int indentation_deep = 0;
00274         const object* parent = m_parent;
00275 
00276         // Find indentation level
00277         while(parent != NULL)
00278         {
00279                 ++ indentation_deep;
00280                 parent = parent->get_parent();
00281         }
00282 
00283         return indentation_deep;
00284 }

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