alphanum.hpp
Go to the documentation of this file.
1 #ifndef ALPHANUM__HPP
2 #define ALPHANUM__HPP
3 
4 /*
5 The Alphanum Algorithm is an improved sorting algorithm for strings
6 containing numbers. Instead of sorting numbers in ASCII order like a
7 standard sort, this algorithm sorts numbers in numeric order.
8 
9 The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
10 
11 This implementation is Copyright (c) 2008 Dirk Jagdmann <doj@cubic.org>.
12 It is a cleanroom implementation of the algorithm and not derived by
13 other's works. In contrast to the versions written by Dave Koelle this
14 source code is distributed with the libpng/zlib license.
15 
16 This software is provided 'as-is', without any express or implied
17 warranty. In no event will the authors be held liable for any damages
18 arising from the use of this software.
19 
20 Permission is granted to anyone to use this software for any purpose,
21 including commercial applications, and to alter it and redistribute it
22 freely, subject to the following restrictions:
23 
24  1. The origin of this software must not be misrepresented; you
25  must not claim that you wrote the original software. If you use
26  this software in a product, an acknowledgment in the product
27  documentation would be appreciated but is not required.
28 
29  2. Altered source versions must be plainly marked as such, and
30  must not be misrepresented as being the original software.
31 
32  3. This notice may not be removed or altered from any source
33  distribution. */
34 
35 /* $Header: /code/doj/alphanum.hpp,v 1.3 2008/01/28 23:06:47 doj Exp $ */
36 
37 #include <cassert>
38 #include <functional>
39 #include <string>
40 #include <sstream>
41 
42 #ifdef ALPHANUM_LOCALE
43 #include <cctype>
44 #endif
45 
46 #ifdef DOJDEBUG
47 #include <iostream>
48 #include <typeinfo>
49 #endif
50 
51 // TODO: make comparison with hexadecimal numbers. Extend the alphanum_comp() function by
52 // traits to choose between decimal and hexadecimal.
53 
54 namespace doj
55 {
56 
57 // anonymous namespace for functions we use internally. But if you
58 // are coding in C, you can use alphanum_impl() directly, since it
59 // uses not C++ features.
60 namespace
61 {
62 
63 // if you want to honour the locale settings for detecting digit
64 // characters, you should define ALPHANUM_LOCALE
65 #ifdef ALPHANUM_LOCALE
66 
67 bool alphanum_isdigit(int c)
68 {
69  return isdigit(c);
70 }
71 #else
72 
76 bool alphanum_isdigit(const char c)
77 {
78  return c >= '0' && c <= '9';
79 }
80 #endif
81 
97 int alphanum_impl(const char* l, const char* r)
98 {
99  enum mode_t
100  {
101  STRING,
102  NUMBER
103  } mode = STRING;
104 
105  while (*l && *r)
106  {
107  if (mode == STRING)
108  {
109  char l_char, r_char;
110  while ((l_char = *l) && (r_char = *r))
111  {
112  // check if this are digit characters
113  const bool l_digit = alphanum_isdigit(l_char), r_digit = alphanum_isdigit(r_char);
114  // if both characters are digits, we continue in NUMBER mode
115  if (l_digit && r_digit)
116  {
117  mode = NUMBER;
118  break;
119  }
120  // if only the left character is a digit, we have a result
121  if (l_digit)
122  return -1;
123  // if only the right character is a digit, we have a result
124  if (r_digit)
125  return +1;
126  // compute the difference of both characters
127  const int diff = l_char - r_char;
128  // if they differ we have a result
129  if (diff != 0)
130  return diff;
131  // otherwise process the next characters
132  ++l;
133  ++r;
134  }
135  }
136  else // mode==NUMBER
137  {
138 #ifdef ALPHANUM_LOCALE
139  // get the left number
140  char* end;
141  unsigned long l_int = strtoul(l, &end, 0);
142  l = end;
143 
144  // get the right number
145  unsigned long r_int = strtoul(r, &end, 0);
146  r = end;
147 #else
148  // get the left number
149  unsigned long l_int = 0;
150  while (*l && alphanum_isdigit(*l))
151  {
152  // TODO: this can overflow
153  l_int = l_int * 10 + *l - '0';
154  ++l;
155  }
156 
157  // get the right number
158  unsigned long r_int = 0;
159  while (*r && alphanum_isdigit(*r))
160  {
161  // TODO: this can overflow
162  r_int = r_int * 10 + *r - '0';
163  ++r;
164  }
165 #endif
166 
167  // if the difference is not equal to zero, we have a comparison result
168  const long diff = l_int - r_int;
169  if (diff != 0)
170  return diff;
171 
172  // otherwise we process the next substring in STRING mode
173  mode = STRING;
174  }
175  }
176 
177  if (*r)
178  return -1;
179  if (*l)
180  return +1;
181  return 0;
182 }
183 
184 } // namespace
185 
194 template <typename lT, typename rT>
195 int alphanum_comp(const lT& left, const rT& right)
196 {
197 #ifdef DOJDEBUG
198  std::clog << "alphanum_comp<" << typeid(left).name() << "," << typeid(right).name()
199  << "> " << left << "," << right << std::endl;
200 #endif
201  std::ostringstream l;
202  l << left;
203  std::ostringstream r;
204  r << right;
205  return alphanum_impl(l.str().c_str(), r.str().c_str());
206 }
207 
215 template <>
216 inline int alphanum_comp<std::string>(const std::string& l, const std::string& r)
217 {
218 #ifdef DOJDEBUG
219  std::clog << "alphanum_comp<std::string,std::string> " << l << "," << r << std::endl;
220 #endif
221  return alphanum_impl(l.c_str(), r.c_str());
222 }
223 
225 
226 // now follow a lot of overloaded alphanum_comp() functions to get a
227 // direct call to alphanum_impl() upon the various combinations of c
228 // and c++ strings.
229 
237 inline int alphanum_comp(char* l, char* r)
238 {
239  assert(l);
240  assert(r);
241 #ifdef DOJDEBUG
242  std::clog << "alphanum_comp<char*,char*> " << l << "," << r << std::endl;
243 #endif
244  return alphanum_impl(l, r);
245 }
246 
247 inline int alphanum_comp(const char* l, const char* r)
248 {
249  assert(l);
250  assert(r);
251 #ifdef DOJDEBUG
252  std::clog << "alphanum_comp<const char*,const char*> " << l << "," << r << std::endl;
253 #endif
254  return alphanum_impl(l, r);
255 }
256 
257 inline int alphanum_comp(char* l, const char* r)
258 {
259  assert(l);
260  assert(r);
261 #ifdef DOJDEBUG
262  std::clog << "alphanum_comp<char*,const char*> " << l << "," << r << std::endl;
263 #endif
264  return alphanum_impl(l, r);
265 }
266 
267 inline int alphanum_comp(const char* l, char* r)
268 {
269  assert(l);
270  assert(r);
271 #ifdef DOJDEBUG
272  std::clog << "alphanum_comp<const char*,char*> " << l << "," << r << std::endl;
273 #endif
274  return alphanum_impl(l, r);
275 }
276 
277 inline int alphanum_comp(const std::string& l, char* r)
278 {
279  assert(r);
280 #ifdef DOJDEBUG
281  std::clog << "alphanum_comp<std::string,char*> " << l << "," << r << std::endl;
282 #endif
283  return alphanum_impl(l.c_str(), r);
284 }
285 
286 inline int alphanum_comp(char* l, const std::string& r)
287 {
288  assert(l);
289 #ifdef DOJDEBUG
290  std::clog << "alphanum_comp<char*,std::string> " << l << "," << r << std::endl;
291 #endif
292  return alphanum_impl(l, r.c_str());
293 }
294 
295 inline int alphanum_comp(const std::string& l, const char* r)
296 {
297  assert(r);
298 #ifdef DOJDEBUG
299  std::clog << "alphanum_comp<std::string,const char*> " << l << "," << r << std::endl;
300 #endif
301  return alphanum_impl(l.c_str(), r);
302 }
303 
304 inline int alphanum_comp(const char* l, const std::string& r)
305 {
306  assert(l);
307 #ifdef DOJDEBUG
308  std::clog << "alphanum_comp<const char*,std::string> " << l << "," << r << std::endl;
309 #endif
310  return alphanum_impl(l, r.c_str());
311 }
312 
314 
321 template <class Ty>
323 {
324  bool operator()(const Ty& left, const Ty& right) const
325  {
326  return alphanum_comp(left, right) < 0;
327  }
328 };
329 
330 } // namespace doj
331 
332 #endif
left
lu_byte left
Definition: lparser.c:1226
right
lu_byte right
Definition: lparser.c:1227
doj
Definition: alphanum.hpp:54
doj::alphanum_less
Definition: alphanum.hpp:322
assert
#define assert(condition)
Definition: lz4.c:271
doj::alphanum_comp
int alphanum_comp(const lT &left, const rT &right)
Definition: alphanum.hpp:195
RosMsgParser::STRING
@ STRING
Definition: builtin_types.hpp:60
doj::alphanum_less::operator()
bool operator()(const Ty &left, const Ty &right) const
Definition: alphanum.hpp:324


plotjuggler
Author(s): Davide Faconti
autogenerated on Mon Nov 11 2024 03:23:43