00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
00032
00033
00034
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
00044
00045
00046
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
00067 unsigned int indentation_deep = get_indentation();
00068
00069
00070 tokens.add(token::TYPE_IDENTIFIER, m_name, 0);
00071
00072
00073 for(attribute_iterator iter = attributes_begin();
00074 iter != attributes_end();
00075 ++ iter)
00076 {
00077 iter->serialise(tokens);
00078 }
00079
00080
00081 for(child_iterator iter = children_begin();
00082 iter != children_end();
00083 ++ iter)
00084 {
00085
00086 tokens.add(
00087 token::TYPE_INDENTATION,
00088 std::string(indentation_deep + 1, ' '),
00089 0
00090 );
00091
00092
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
00105 m_name = iter->get_text();
00106
00107
00108 m_line = iter->get_line();
00109 ++ iter;
00110
00111
00112 while(iter != tokens.end() &&
00113 iter->get_type() == token::TYPE_IDENTIFIER)
00114 m_attributes[iter->get_text()].deserialise(tokens, iter);
00115
00116
00117 while(iter != tokens.end() &&
00118 iter->get_type() == token::TYPE_INDENTATION)
00119 {
00120
00121 unsigned int child_indentation = iter->get_text().length();
00122
00123 if(child_indentation <= indentation_deep) break;
00124
00125
00126 tokens.next_token(iter);
00127
00128
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
00155
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
00277 while(parent != NULL)
00278 {
00279 ++ indentation_deep;
00280 parent = parent->get_parent();
00281 }
00282
00283 return indentation_deep;
00284 }