00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef WIFI_ESSID_HXX_
00023 # define WIFI_ESSID_HXX_
00024
00025 # include <sstream>
00026 # include <iomanip>
00027 # include <stdexcept>
00028 # include <cctype>
00029
00030 # include <boost/foreach.hpp>
00031
00032 # include <wipal/wifi/essid.hh>
00033
00034 namespace wpl
00035 {
00036
00037 namespace wifi
00038 {
00039
00040 inline
00041 essid::essid(const ssid_elt& se):
00042 std::string (se.ssid, se.ssid + se.length)
00043 {
00044 }
00045
00046 inline
00047 essid::essid(const ssid_elt& se, size_t overrided_length):
00048 std::string (se.ssid, se.ssid + overrided_length)
00049 {
00050 }
00051
00052 inline
00053 essid::essid(const std::string& s): std::string (s)
00054 {
00055 }
00056
00057 inline
00058 std::ostream&
00059 essid::print(std::ostream& os) const
00060 {
00061 return os << escape();
00062 }
00063
00064 inline
00065 std::istream&
00066 essid::read(std::istream& is, bool throw_on_parse_error)
00067 {
00068 clear();
00069
00070 try
00071 {
00072 if (is.flags() & std::istream::skipws)
00073 skipws(is);
00074 eat(is, '"');
00075
00076 char c = eat(is);
00077
00078 while (c != '"')
00079 {
00080 if (c == '\\' and (c = eat(is)) == 'x')
00081 {
00082 unsigned char v = 0;
00083
00084 v = xdigit(eat_xdigit(is));
00085 c = eat(is);
00086 if (std::isxdigit(c))
00087 {
00088 v = (v << 4) | xdigit(c);
00089 c = eat(is);
00090 }
00091 push_back(v);
00092 continue;
00093 }
00094
00095 push_back(c);
00096 c = eat(is);
00097 }
00098 }
00099 catch (...)
00100 {
00101 is.setstate(is.rdstate() | std::istream::failbit);
00102 if (throw_on_parse_error)
00103 throw;
00104 }
00105 return is;
00106 }
00107
00108 inline
00109 std::string
00110 essid::escape(size_t max) const
00111 {
00112 std::ostringstream out;
00113
00114 out << '"';
00115 BOOST_FOREACH(unsigned char c, *this)
00116 {
00117 if (out.str().size() > max - 8)
00118 {
00119 out << "...";
00120 break;
00121 }
00122 if (c == '"')
00123 out << "\\\"";
00124 else if (c == '\\')
00125 out << "\\\\";
00126 else if (std::isprint(c))
00127 out << c;
00128 else
00129 out << "\\x" << std::hex << std::setw (2) << std::setfill ('0')
00130 << unsigned (c);
00131 }
00132 out << '"';
00133
00134 return out.str();
00135 }
00136
00137 inline
00138 void
00139 essid::skipws(std::istream& is)
00140 {
00141 while (std::isspace(is.peek()) and is and not is.eof())
00142 is.get();
00143 }
00144
00145 inline
00146 unsigned char
00147 essid::eat(std::istream& is)
00148 {
00149 unsigned char r = is.get();
00150
00151 if (not is or is.eof())
00152 throw
00153 std::invalid_argument ("essid parse error: error or unexpected eof");
00154 return r;
00155 }
00156
00157 inline
00158 unsigned char
00159 essid::eat_xdigit(std::istream& is)
00160 {
00161 unsigned char r = eat(is);
00162
00163 if (not std::isxdigit(r))
00164 throw std::invalid_argument ("essid parse error: expected hex digit, "
00165 "got '" + r + '\'');
00166 return r;
00167 }
00168
00169 inline
00170 unsigned char
00171 essid::eat(std::istream& is, const unsigned char c)
00172 {
00173 unsigned char r = eat(is);
00174
00175 if (r != c)
00176 {
00177 std::ostringstream e;
00178
00179 e << "essid parse error: expected '" << c << "', got '" << r << '\'';
00180 throw std::invalid_argument (e.str());
00181 }
00182 return r;
00183 }
00184
00185 inline
00186 unsigned
00187 essid::xdigit(const unsigned char c)
00188 {
00189 if ('0' <= c and c <= '9')
00190 return c - '0';
00191 if ('a' <= c and c <= 'f')
00192 return c - 'a' + 10;
00193 if ('A' <= c and c <= 'F')
00194 return c - 'A' + 10;
00195
00196 throw std::logic_error ("ESSID parse error: internal error, "
00197 "fill a bug report");
00198 }
00199
00200 inline
00201 std::ostream&
00202 operator << (std::ostream& o, const essid& s)
00203 {
00204 return s.print(o);
00205 }
00206
00207 inline
00208 std::istream&
00209 operator >> (std::istream& i, essid& s)
00210 {
00211 return s.read(i);
00212 }
00213
00214 }
00215
00216 }
00217
00218 #endif // ! WIFI_ESSID_HXX_