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