40 return Item(t_string) ;
45 std::istringstream ss ;
56 std::istringstream ss ;
61 catch( std::exception & )
69 std::ostringstream ss ;
92 check( t_map ) ; need( k ) ;
93 return (*m_map.find(k)).second ;
98 check( t_map ) ; update( k ) ;
104 check( t_list ) ; need( i ) ;
105 return m_list.at(i) ;
116 m_list.push_back( i ) ;
126 check( t_map ) ; update( k ) ;
132 Map::iterator p = m_map.find( k ) ;
133 if( p != m_map.end() )
136 m_keys.erase( std::remove(m_keys.begin(),m_keys.end(),k) , m_keys.end() ) ;
140 void G::Item::update(
const std::string & k )
142 if( std::find(m_keys.begin(),m_keys.end(),k) == m_keys.end() )
143 m_keys.push_back( k ) ;
149 return std::find(m_keys.begin(),m_keys.end(),k) != m_keys.end() ;
156 out.m_list.reserve( m_keys.size() ) ;
157 for( std::vector<std::string>::const_iterator p = m_keys.begin() ; p != m_keys.end() ; ++p )
164 checkNot( t_string ) ;
165 return std::max(m_list.size(),m_map.size()) ;
170 if( m_type == t_list )
171 return m_list.empty() ;
172 else if( m_type == t_map)
173 return m_map.empty() ;
175 return m_string.empty() ;
180 check( t_list ) ; need( i ) ;
181 return m_list.at(i) ;
190 void G::Item::checkNot( Type type )
const
193 throw Error(
"type mismatch") ;
197 void G::Item::check( Type type )
const
200 throw Error(
"type mismatch") ;
204 void G::Item::check()
const
206 if( m_type == t_map && m_keys.size() != m_map.size() )
207 throw Error(
"internal error") ;
208 if( m_map.size() != 0U && m_list.size() != 0U )
209 throw Error(
"internal error") ;
212 void G::Item::need(
const std::string & k )
const
214 if( m_map.find(k) == m_map.end() )
215 throw Error(
"item not found",k) ;
218 void G::Item::need(
size_t i )
const
220 if( i >= m_list.size() )
221 throw Error(
"invalid index") ;
224 bool G::Item::less(
const Item & a ,
const Item & b )
226 return a.m_string < b.m_string ;
231 std::string sp0(
int indent )
233 if( indent < 0 )
return " " ;
234 return "\n" + std::string(indent*2,
' ') ;
236 std::string sp(
int indent )
238 if( indent < 0 )
return ", " ;
239 return ",\n" + std::string(indent*2,
' ') ;
241 std::string spx(
int indent )
243 if( indent < 0 )
return " " ;
244 if( indent ) indent-- ;
245 return "\n" + std::string(indent*2,
' ') ;
251 if( m_type == t_string )
253 static const std::string specials_in(
"\r\n\t" , 4U ) ;
254 static const std::string specials_out(
"rnt0" ) ;
255 s <<
"\"" <<
G::Str::escaped(m_string,
'\\',specials_in,specials_out) <<
"\"" ;
257 else if( m_type == t_list )
260 std::string sep = sp0(indent) ;
261 for(
size_t i = 0U ; i < m_list.size() ; i++ , sep = sp(indent) )
264 m_list.at(i).out( s , indent+(indent>0) ) ;
266 s << spx(indent) <<
"]" ;
268 else if( m_type == t_map )
271 std::string sep = sp0(indent) ;
272 for( std::vector<std::string>::const_iterator p = m_keys.begin() ; p != m_keys.end() ; ++p , sep = sp(indent) )
274 s << sep <<
"\"" << *p <<
"\" : " ;
275 if( m_map.find(*p) != m_map.end() )
276 (*m_map.find(*p)).second.out( s , indent+(indent>0) ) ;
278 s << spx(indent) <<
"}" ;
282 void G::Item::clear( Type type )
291 void G::Item::read( std::istream & stream ,
char c )
296 if( !std::getline(stream,part,c) )
298 m_string.append( part ) ;
299 if( !escaped(m_string) )
301 m_string.append( 1U , c ) ;
306 bool G::Item::escaped(
const std::string & s )
308 typedef std::string::const_iterator ptr_t ;
310 for( ptr_t p = s.begin() ; p != s.end() ; ++p )
320 void G::Item::readn( std::istream & s ,
char c0 )
322 m_string = std::string( 1U , c0 ) ;
327 if( c >=
'0' && c <=
'9' )
329 m_string.append( 1U , c ) ;
341 stream.setf( std::ios_base::skipws ) ;
348 else if( c ==
'"' || c ==
'\'' )
353 else if( c >=
'0' && c <=
'9' )
356 readn( stream , c ) ;
363 m_list.push_back(
Item() ) ;
364 stream >> m_list.back() ;
366 if( c ==
']' ) break ;
367 if( c !=
',' )
throw ParseError() ;
376 if( c ==
'}' ) break ;
377 if( c !=
'"' && c !=
'\'' )
throw ParseError() ;
378 Item key( t_string ) ;
379 key.read( stream , c ) ;
380 if( key.m_string.empty() )
throw ParseError() ;
382 if( c !=
':' )
throw ParseError() ;
385 update(key.m_string) ;
386 m_map[key.m_string] = value ;
388 if( c ==
'}' ) break ;
389 if( c !=
',' )
throw ParseError() ;
void remove(const std::string &k)
Removes an item from this map item.
void out(std::ostream &s, int indent=-1) const
Does output streaming, using a json-like format.
static Item map()
Factory function for a map item.
size_t size() const
Returns the size of this map-or-list item.
bool empty() const
Returns true if an empty item.
void in(std::istream &s)
Does input parsing. Throws on error.
static std::string escaped(const std::string &, char c_escape, const std::string &specials_in, const std::string &specials_out)
Returns the escape()d string.
std::string str(int indent=-1) const
Returns a string representation, using a json-like format.
static Item parse(const std::string &)
Parses the string representation. Throws on error.
static Item list()
Factory function for a list item.
const Item & operator[](const std::string &k) const
Indexing operator for a map item. Throws if no such item.
std::string operator()() const
Returns the value of this string item.
A variant class holding a string, an item map keyed by name, or an ordered list of items...
static void unescape(std::string &s, char c_escape, const char *specials_in, const char *specials_out)
Unescapes the string by replacing e-e with e, e-special-in with special-out, and e-other with other...
void add(const std::string &s)
Adds a string item to this list item.
static Item string()
Factory function for a string item.
Item(Type type=t_string)
Constructor.
Item keys() const
Returns the keys of this map item as a list of string items.
bool has(const std::string &k) const
Returns true if this map item has the named key.
Type type() const
Returns the item type (string, list or map).