23
23
along with this program; if not, write to the Free Software
24
24
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
25
25
26
- /* *
27
- A RandomAccessIterator that splits up a char/uchar array into fixed-length
28
- elements, so that they can be sorted using std::sort. There is also a helper
29
- function varlen_sort() that is an adapter around std::sort for this purpose.
30
- */
31
-
32
26
#include < assert.h>
33
27
34
28
#include " template_utils.h"
35
29
36
30
#include < algorithm>
37
- #include < memory>
38
- #include < utility>
31
+ #include < cstddef>
32
+ #include < iterator>
33
+
34
+ template <class RandomIt , class Compare >
35
+ void my_insert_sort (RandomIt first, RandomIt last, Compare comp) {
36
+ for (RandomIt high_water_mark = first + 1 ; high_water_mark < last;
37
+ ++high_water_mark) {
38
+ for (RandomIt cur = high_water_mark; cur > first; --cur) {
39
+ RandomIt prev = cur - 1 ;
40
+ if (comp (*prev, *cur)) break ;
41
+ std::iter_swap (cur - 1 , cur);
42
+ }
43
+ }
44
+ }
39
45
40
46
/*
41
47
Conceptually similar to a struct { uchar[N] },
42
- except that most of the time, it just holds a reference to an underlying
48
+ except that it just holds a reference to an underlying
43
49
array, instead of keeping the memory itself.
44
50
*/
45
51
struct varlen_element {
46
52
varlen_element (unsigned char *ptr_arg, size_t elem_size_arg)
47
53
: ptr(ptr_arg), elem_size(elem_size_arg) {}
48
54
49
- varlen_element (varlen_element &other) = delete ;
50
-
51
- /*
52
- In this case, we need to own the memory ourselves. It is really only used
53
- when std::sort wants to do an insertion sort and needs a temporary element.
54
- */
55
- varlen_element (varlen_element &&other) : elem_size(other.elem_size) {
56
- if (other.mem != nullptr ) {
57
- mem = std::move (other.mem );
58
- } else {
59
- mem.reset (new unsigned char [other.elem_size ]);
60
- memcpy (mem.get (), other.ptr , elem_size);
61
- }
62
- ptr = mem.get ();
63
- }
64
-
55
+ varlen_element (const varlen_element &other) = delete ;
56
+ varlen_element (varlen_element &&other) = delete ;
65
57
varlen_element &operator =(const varlen_element &other) = delete ;
66
- varlen_element &operator =(varlen_element &&other) {
67
- assert (elem_size == other.elem_size );
68
- memcpy (ptr, other.ptr , elem_size);
69
- return *this ;
70
- }
58
+ varlen_element &operator =(varlen_element &&other) = delete ;
71
59
72
- std::unique_ptr<unsigned char []> mem;
73
- unsigned char *ptr = nullptr ;
74
- size_t elem_size = 0 ;
60
+ unsigned char *ptr{nullptr };
61
+ size_t elem_size{0 };
75
62
};
76
63
77
64
// ValueSwappable.
78
- static inline void swap (const varlen_element &a, const varlen_element &b) {
65
+ inline void swap (const varlen_element &a, const varlen_element &b) {
79
66
assert (a.elem_size == b.elem_size );
80
67
std::swap_ranges (a.ptr , a.ptr + a.elem_size , b.ptr );
81
68
}
82
69
83
- // Conceptually similar to a _pointer_ to an uchar[N].
70
+ /* *
71
+ A RandomAccessIterator that splits up a char/uchar array into fixed-length
72
+ elements. Conceptually similar to a _pointer_ to an uchar[N].
73
+ */
84
74
class varlen_iterator {
85
75
public:
86
76
varlen_iterator (unsigned char *ptr_arg, size_t elem_size_arg)
@@ -95,7 +85,8 @@ class varlen_iterator {
95
85
96
86
// EqualityComparable (required for InputIterator).
97
87
bool operator ==(const varlen_iterator &other) const {
98
- return ptr == other.ptr && elem_size == other.elem_size ;
88
+ assert (elem_size == other.elem_size );
89
+ return ptr == other.ptr ;
99
90
}
100
91
101
92
// InputIterator (required for ForwardIterator).
@@ -195,11 +186,12 @@ struct iterator_traits<varlen_iterator> : iterator_traits<varlen_element *> {
195
186
*/
196
187
template <class T , class Compare >
197
188
inline void varlen_sort (T *first, T *last, size_t elem_size, Compare comp) {
198
- std::sort (varlen_iterator (pointer_cast<unsigned char *>(first), elem_size),
199
- varlen_iterator (pointer_cast<unsigned char *>(last), elem_size),
200
- [comp](const varlen_element &a, const varlen_element &b) {
201
- return comp (pointer_cast<T *>(a.ptr ), pointer_cast<T *>(b.ptr ));
202
- });
189
+ my_insert_sort (
190
+ varlen_iterator (pointer_cast<unsigned char *>(first), elem_size),
191
+ varlen_iterator (pointer_cast<unsigned char *>(last), elem_size),
192
+ [comp](const varlen_element &a, const varlen_element &b) {
193
+ return comp (pointer_cast<T *>(a.ptr ), pointer_cast<T *>(b.ptr ));
194
+ });
203
195
}
204
196
205
197
#endif // !defined(VARLEN_SORT_INCLUDED)
0 commit comments