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 wifi
00035 {
00036
00037 inline
00038 essid::essid(const frame::ssid_elt& se):
00039 std::string (se.ssid, se.ssid + se.length)
00040 {
00041 }
00042
00043 inline
00044 essid::essid(const frame::ssid_elt& se, size_t overrided_length):
00045 std::string (se.ssid, se.ssid + overrided_length)
00046 {
00047 }
00048
00049 inline
00050 essid::essid(const std::string& s): std::string (s)
00051 {
00052 }
00053
00054 inline
00055 std::ostream&
00056 essid::print(std::ostream& os) const
00057 {
00058 return os << escape();
00059 }
00060
00061 inline
00062 std::istream&
00063 essid::read(std::istream& is, bool throw_on_parse_error)
00064 {
00065 clear();
00066
00067 try
00068 {
00069 if (is.flags() & std::istream::skipws)
00070 skipws(is);
00071 eat(is, '"');
00072
00073 char c = eat(is);
00074
00075 while (c != '"')
00076 {
00077 if (c == '\\' and (c = eat(is)) == 'x')
00078 {
00079 unsigned char v = 0;
00080
00081 v = xdigit(eat_xdigit(is));
00082 c = eat(is);
00083 if (std::isxdigit(c))
00084 {
00085 v = (v << 4) | xdigit(c);
00086 c = eat(is);
00087 }
00088 push_back(v);
00089 continue;
00090 }
00091
00092 push_back(c);
00093 c = eat(is);
00094 }
00095 }
00096 catch (...)
00097 {
00098 is.setstate(is.rdstate() | std::istream::failbit);
00099 if (throw_on_parse_error)
00100 throw;
00101 }
00102 return is;
00103 }
00104
00105 inline
00106 std::string
00107 essid::escape(size_t max) const
00108 {
00109 std::ostringstream out;
00110
00111 out << '"';
00112 BOOST_FOREACH(unsigned char c, *this)
00113 {
00114 if (out.str().size() > max - 8)
00115 {
00116 out << "...";
00117 break;
00118 }
00119 if (c == '"')
00120 out << "\\\"";
00121 else if (c == '\\')
00122 out << "\\\\";
00123 else if (std::isprint(c))
00124 out << c;
00125 else
00126 out << "\\x" << std::hex << std::setw (2) << std::setfill ('0')
00127 << unsigned (c);
00128 }
00129 out << '"';
00130
00131 return out.str();
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_