00001 #ifndef ALPHANUM__HPP
00002 #define ALPHANUM__HPP
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <cassert>
00038 #include <functional>
00039 #include <string>
00040 #include <sstream>
00041
00042 #ifdef ALPHANUM_LOCALE
00043 #include <cctype>
00044 #endif
00045
00046 #ifdef DOJDEBUG
00047 #include <iostream>
00048 #include <typeinfo>
00049 #endif
00050
00051
00052
00053 namespace doj
00054 {
00055
00056
00057
00058
00059 namespace {
00060
00061
00062
00063 #ifdef ALPHANUM_LOCALE
00064
00065 bool alphanum_isdigit(int c)
00066 {
00067 return isdigit(c);
00068 }
00069 #else
00070
00074 bool alphanum_isdigit(const char c)
00075 {
00076 return c>='0' && c<='9';
00077 }
00078 #endif
00079
00095 int alphanum_impl(const char *l, const char *r)
00096 {
00097 enum mode_t { STRING, NUMBER } mode=STRING;
00098
00099 while(*l && *r)
00100 {
00101 if(mode == STRING)
00102 {
00103 char l_char, r_char;
00104 while((l_char=*l) && (r_char=*r))
00105 {
00106
00107 const bool l_digit=alphanum_isdigit(l_char), r_digit=alphanum_isdigit(r_char);
00108
00109 if(l_digit && r_digit)
00110 {
00111 mode=NUMBER;
00112 break;
00113 }
00114
00115 if(l_digit) return -1;
00116
00117 if(r_digit) return +1;
00118
00119 const int diff=l_char - r_char;
00120
00121 if(diff != 0) return diff;
00122
00123 ++l;
00124 ++r;
00125 }
00126 }
00127 else
00128 {
00129 #ifdef ALPHANUM_LOCALE
00130
00131 char *end;
00132 unsigned long l_int=strtoul(l, &end, 0);
00133 l=end;
00134
00135
00136 unsigned long r_int=strtoul(r, &end, 0);
00137 r=end;
00138 #else
00139
00140 unsigned long l_int=0;
00141 while(*l && alphanum_isdigit(*l))
00142 {
00143
00144 l_int=l_int*10 + *l-'0';
00145 ++l;
00146 }
00147
00148
00149 unsigned long r_int=0;
00150 while(*r && alphanum_isdigit(*r))
00151 {
00152
00153 r_int=r_int*10 + *r-'0';
00154 ++r;
00155 }
00156 #endif
00157
00158
00159 const long diff=l_int-r_int;
00160 if(diff != 0)
00161 return diff;
00162
00163
00164 mode=STRING;
00165 }
00166 }
00167
00168 if(*r) return -1;
00169 if(*l) return +1;
00170 return 0;
00171 }
00172
00173 }
00174
00183 template <typename lT, typename rT>
00184 int alphanum_comp(const lT& left, const rT& right)
00185 {
00186 #ifdef DOJDEBUG
00187 std::clog << "alphanum_comp<" << typeid(left).name() << "," << typeid(right).name() << "> " << left << "," << right << std::endl;
00188 #endif
00189 std::ostringstream l; l << left;
00190 std::ostringstream r; r << right;
00191 return alphanum_impl(l.str().c_str(), r.str().c_str());
00192 }
00193
00201 template <>
00202 int alphanum_comp<std::string>(const std::string& l, const std::string& r)
00203 {
00204 #ifdef DOJDEBUG
00205 std::clog << "alphanum_comp<std::string,std::string> " << l << "," << r << std::endl;
00206 #endif
00207 return alphanum_impl(l.c_str(), r.c_str());
00208 }
00209
00211
00212
00213
00214
00215
00223 int alphanum_comp(char* l, char* r)
00224 {
00225 assert(l);
00226 assert(r);
00227 #ifdef DOJDEBUG
00228 std::clog << "alphanum_comp<char*,char*> " << l << "," << r << std::endl;
00229 #endif
00230 return alphanum_impl(l, r);
00231 }
00232
00233 int alphanum_comp(const char* l, const char* r)
00234 {
00235 assert(l);
00236 assert(r);
00237 #ifdef DOJDEBUG
00238 std::clog << "alphanum_comp<const char*,const char*> " << l << "," << r << std::endl;
00239 #endif
00240 return alphanum_impl(l, r);
00241 }
00242
00243 int alphanum_comp(char* l, const char* r)
00244 {
00245 assert(l);
00246 assert(r);
00247 #ifdef DOJDEBUG
00248 std::clog << "alphanum_comp<char*,const char*> " << l << "," << r << std::endl;
00249 #endif
00250 return alphanum_impl(l, r);
00251 }
00252
00253 int alphanum_comp(const char* l, char* r)
00254 {
00255 assert(l);
00256 assert(r);
00257 #ifdef DOJDEBUG
00258 std::clog << "alphanum_comp<const char*,char*> " << l << "," << r << std::endl;
00259 #endif
00260 return alphanum_impl(l, r);
00261 }
00262
00263 int alphanum_comp(const std::string& l, char* r)
00264 {
00265 assert(r);
00266 #ifdef DOJDEBUG
00267 std::clog << "alphanum_comp<std::string,char*> " << l << "," << r << std::endl;
00268 #endif
00269 return alphanum_impl(l.c_str(), r);
00270 }
00271
00272 int alphanum_comp(char* l, const std::string& r)
00273 {
00274 assert(l);
00275 #ifdef DOJDEBUG
00276 std::clog << "alphanum_comp<char*,std::string> " << l << "," << r << std::endl;
00277 #endif
00278 return alphanum_impl(l, r.c_str());
00279 }
00280
00281 int alphanum_comp(const std::string& l, const char* r)
00282 {
00283 assert(r);
00284 #ifdef DOJDEBUG
00285 std::clog << "alphanum_comp<std::string,const char*> " << l << "," << r << std::endl;
00286 #endif
00287 return alphanum_impl(l.c_str(), r);
00288 }
00289
00290 int alphanum_comp(const char* l, const std::string& r)
00291 {
00292 assert(l);
00293 #ifdef DOJDEBUG
00294 std::clog << "alphanum_comp<const char*,std::string> " << l << "," << r << std::endl;
00295 #endif
00296 return alphanum_impl(l, r.c_str());
00297 }
00298
00300
00306 template<class Ty>
00307 struct alphanum_less : public std::binary_function<Ty, Ty, bool>
00308 {
00309 bool operator()(const Ty& left, const Ty& right) const
00310 {
00311 return alphanum_comp(left, right) < 0;
00312 }
00313 };
00314
00315 }
00316
00317
00318 #endif