blob: 73748ee4b071e3ed9c61dc6b6d2abec534a0fe8b (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// A handy type for iterating through query results.
//
// Just define your Traits type with
//
// RowType
// Extract(statement*, RowType);
//
// and then pass an sqlite3_stmt into the constructor for begin,
// and use the no-arg constructor for an end iterator. Ex:
//
// for (RowIterator<SomeTraits> i(statement), end; i != end; ++i)
// ...
#ifndef CHROME_BROWSER_SYNC_UTIL_ROW_ITERATOR_H_
#define CHROME_BROWSER_SYNC_UTIL_ROW_ITERATOR_H_
#include "base/logging.h"
#include "third_party/sqlite/preprocessed/sqlite3.h"
template <typename ColumnType, int index = 0>
struct SingleColumnTraits {
typedef ColumnType RowType;
inline void Extract(sqlite3_stmt* statement, ColumnType* x) const {
GetColumn(statement, index, x);
}
};
template <typename RowTraits>
class RowIterator : public std::iterator<std::input_iterator_tag,
const typename RowTraits::RowType> {
public:
typedef typename RowTraits::RowType RowType;
// Statement must have been prepared, but not yet stepped:
RowIterator(sqlite3_stmt* statement, RowTraits traits = RowTraits()) {
kernel_ = new Kernel;
kernel_->done = false;
kernel_->refcount = 1;
kernel_->statement = statement;
kernel_->row_traits = traits;
++(*this);
}
RowIterator() : kernel_(NULL) { } // creates end iterator
RowIterator(const RowIterator& i)
: kernel_(NULL) {
*this = i;
}
~RowIterator() {
if (kernel_ && 0 == --(kernel_->refcount)) {
sqlite3_finalize(kernel_->statement);
delete kernel_;
}
}
RowIterator& operator = (const RowIterator& i) {
if (kernel_ && (0 == --(kernel_->refcount))) {
sqlite3_finalize(kernel_->statement);
delete kernel_;
}
kernel_ = i.kernel_;
if (kernel_)
kernel_->refcount += 1;
return *this;
}
RowIterator operator ++(int) {
RowIterator i(*this);
return ++i;
}
RowIterator& operator ++() {
DCHECK(NULL != kernel_);
if (SQLITE_ROW == sqlite3_step(kernel_->statement)) {
kernel_->row_traits.Extract(kernel_->statement, &kernel_->row);
} else {
kernel_->done = true;
}
return *this;
}
const RowType& operator *() const {
return *(operator -> ());
}
const RowType* operator ->() const {
DCHECK(NULL != kernel_);
DCHECK(!kernel_->done);
return &(kernel_->row);
}
bool operator == (const RowIterator& i) const {
if (kernel_ == i.kernel_)
return true;
if (NULL == kernel_ && i.kernel_->done)
return true;
if (NULL == i.kernel_ && kernel_->done)
return true;
return false;
}
bool operator != (const RowIterator& i) const {
return !(*this == i);
}
protected:
struct Kernel {
int refcount;
bool done;
RowType row;
sqlite3_stmt* statement;
RowTraits row_traits;
};
Kernel* kernel_;
};
#endif // CHROME_BROWSER_SYNC_UTIL_ROW_ITERATOR_H_
|