- Solved the proliferation of type checks for different DAI_ENUM's in properties.cpp
[libdai.git] / src / properties.cpp
1 /* Copyright (C) 2006-2008 Joris Mooij [j dot mooij at science dot ru dot nl]
2 Radboud University Nijmegen, The Netherlands
3
4 This file is part of libDAI.
5
6 libDAI is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 libDAI is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with libDAI; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21
22 #include <iostream>
23 #include <dai/properties.h>
24 #include <dai/exceptions.h>
25
26
27 namespace dai {
28
29
30 /// Sends a single Property object to an output stream
31 std::ostream& operator<< (std::ostream & os, const Property & p) {
32 os << p.first << "=";
33 if( p.second.type() == typeid(size_t) )
34 os << boost::any_cast<size_t>(p.second);
35 else if( p.second.type() == typeid(std::string) )
36 os << boost::any_cast<std::string>(p.second);
37 else if( p.second.type() == typeid(double) )
38 os << boost::any_cast<double>(p.second);
39 else if( p.second.type() == typeid(bool) )
40 os << boost::any_cast<bool>(p.second);
41 else if( p.second.type() == typeid(PropertySet) )
42 os << boost::any_cast<PropertySet>(p.second);
43 else
44 DAI_THROW(UNKNOWN_PROPERTY_TYPE);
45 return( os );
46 }
47
48
49 /// Sends a PropertySet object to an output stream
50 std::ostream& operator<< (std::ostream & os, const PropertySet & ps) {
51 os << "[";
52 for( PropertySet::const_iterator p = ps.begin(); p != ps.end(); p++ ) {
53 if( p != ps.begin() )
54 os << ",";
55 os << (Property)*p;
56 }
57 os << "]";
58 return os;
59 }
60
61
62 /// Reads a PropertySet object from an input stream, storing values as strings
63 std::istream& operator >> (std::istream& is, PropertySet & ps) {
64 ps = PropertySet();
65
66 std::string s;
67 is >> s;
68
69 // Check whether s is of the form "[.*]"
70 if( (s.length() < 2) || (s.at(0) != '[') || (s.at(s.length()-1)) != ']' )
71 DAI_THROW(MALFORMED_PROPERTY);
72
73 size_t N = s.length() - 1;
74 for( size_t token_start = 1; token_start < N; ) {
75 size_t token_end;
76
77 // scan until '=' is found
78 for( token_end = token_start + 1; token_end < N; token_end++ )
79 if( s[token_end] == '=' )
80 break;
81 if( token_end == N )
82 DAI_THROW(MALFORMED_PROPERTY);
83 // we found a key
84 std::string key = s.substr(token_start, token_end - token_start);
85
86 token_start = token_end + 1;
87 // scan until matching ',' is found
88 int level = 0;
89 for( token_end = token_start; token_end < N; token_end++ ) {
90 if( s[token_end] == '[' )
91 level++;
92 else if( s[token_end] == ']' )
93 level--;
94 else if( (s[token_end] == ',') && (level == 0) )
95 break;
96 }
97 if( !(level == 0) )
98 DAI_THROW(MALFORMED_PROPERTY);
99 // we found a vlue
100 std::string value = s.substr(token_start, token_end - token_start);
101
102 // store the key,value pair
103 ps.Set(key,value);
104
105 // go on with the next one
106 token_start = token_end + 1;
107 }
108
109 return is;
110 }
111
112
113 } // end of namespace dai