HAL
sort.cpp
Go to the documentation of this file.
1 #include "gui/gui_utils/sort.h"
2 
3 #include "hal_core/defines.h"
4 
5 #include <assert.h>
6 
7 namespace hal
8 {
9  namespace gui_utility
10  {
12  {
13  bool wasNumerical = false;
14  int currentNumber = 0;
15  for (const QChar& cc : s)
16  {
17  if (cc.isDigit())
18  {
19  int digit = cc.unicode() - '0';
20  if (wasNumerical)
21  currentNumber = currentNumber * 10 + digit;
22  else
23  currentNumber = digit;
24  wasNumerical = true;
25  }
26  else
27  {
28  if (wasNumerical)
29  {
30  mNumList.append(currentNumber);
31  currentNumber = 0;
32  wasNumerical = false;
33  }
34  mRemainder += cc;
35  }
36  }
37  if (wasNumerical) mNumList.append(currentNumber);
38  }
39 
40  bool naturalOrderCompare(const QString& a, const QString& b)
41  {
42  const QChar* a_it = a.constBegin();
43  const QChar* b_it = b.constBegin();
44  QString a_num, b_num;
45  bool number_mode = false;
46  while (!a_it->isNull() && !b_it->isNull())
47  {
48  // read the entire number of each string since we want to be safe
49  // against leading zeros: 1 < 0002
50  if (a_it->isNumber() || b_it->isNumber())
51  {
52  number_mode = true;
53  if (a_it->isNumber())
54  {
55  a_num += *a_it;
56  ++a_it;
57  }
58  if (b_it->isNumber())
59  {
60  b_num += *b_it;
61  ++b_it;
62  }
63  }
64  else
65  {
66  if (number_mode)
67  {
68  int diff = numericStringCompare(a_num, b_num);
69  if (diff != 0) // keep looking if both numbers are equal
70  {
71  return diff < 0;
72  }
73  // reset number cache
74  a_num.clear();
75  b_num.clear();
76  number_mode = false;
77  // no iterator increment here, this block just evaluates
78  // the result of number mode
79  }
80  else if (*a_it != *b_it)
81  {
82  return *a_it < *b_it;
83  }
84  else
85  {
86  ++a_it;
87  ++b_it;
88  }
89  }
90  }
91  // if strings have equal length and end with numbers, compare the
92  // numbers
93  if (a_it->isNull() && b_it->isNull() && number_mode)
94  {
95  int diff = numericStringCompare(a_num, b_num);
96  if (diff) // keep looking if both numbers are equal
97  {
98  return diff < 0;
99  }
100  }
101  return a_it->isNull(); // is a shorter than b?
102  }
103 
104  bool numeratedOrderCompare(const QString& a, const QString& b)
105  {
106  NumeratedString ans(a);
107  NumeratedString bns(b);
108 
109  // check lexical part different
110  if (ans.mRemainder < bns.mRemainder) return true;
111  if (ans.mRemainder > bns.mRemainder) return false;
112  int na = ans.mNumList.size();
113  int nb = bns.mNumList.size();
114  int n = na < nb ? na : nb;
115 
116  // check whether numbers are different
117  for (int i=0; i<n; i++)
118  {
119  if (ans.mNumList.at(i) < bns.mNumList.at(i)) return true;
120  if (ans.mNumList.at(i) > bns.mNumList.at(i)) return false;
121  }
122 
123  // check whether there are additional numbers
124  if (na < nb) return true;
125  if (nb > na) return false;
126 
127  return false; // all equal
128  }
129 
130  bool lexicalOrderCompare(const QString& a, const QString& b)
131  {
132  return a < b;
133  }
134 
136  {
137  // this allows us to compare any length of number, regardless of
138  // any integer limits
139 
140  // zero-pad to same length (we don't care if the strings themselves
141  // contain any leading zeros, this still works)
142  if (a_num.size() < b_num.size())
143  {
144  a_num = a_num.rightJustified(b_num.size(), '0');
145  }
146  else
147  {
148  b_num = b_num.rightJustified(a_num.size(), '0');
149  }
150  return a_num.compare(b_num);
151  }
152 
153  int compare(mSortMechanism mechanism, QString a, QString b)
154  {
155  switch(mechanism)
156  {
157  case lexical:
158  return lexicalOrderCompare(a, b);
159  case natural:
160  return naturalOrderCompare(a, b);
161  case numerated:
162  return numeratedOrderCompare(a, b);
163  default:
164  assert(false);
165  }
166  return 0;
167  }
168 
169 
170  } // namespace gui_utility
171 }
NumeratedString(const QString &s)
Definition: sort.cpp:11
int numericStringCompare(QString a_num, QString b_num)
Definition: sort.cpp:135
bool naturalOrderCompare(const QString &a, const QString &b)
Definition: sort.cpp:40
bool numeratedOrderCompare(const QString &a, const QString &b)
Definition: sort.cpp:104
int compare(mSortMechanism mechanism, QString a, QString b)
Definition: sort.cpp:153
bool lexicalOrderCompare(const QString &a, const QString &b)
Definition: sort.cpp:130
n
Definition: test.py:6
bool isNull() const const
bool isNumber() const const
void append(const T &value)
const T & at(int i) const const
int size() const const
void clear()
int compare(const QString &other, Qt::CaseSensitivity cs) const const
QString::const_iterator constBegin() const const
QString rightJustified(int width, QChar fill, bool truncate) const const
int size() const const