1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 // list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 // this list of conditions and the following disclaimer in the documentation
15 // and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32
33 #pragma once
34
35 #include <vector>
36
37 #include "dbDiff.h"
38 #include "dbStream.h"
39 #include "odb.h"
40
41 namespace odb {
42
43 template <class T>
44 class dbVector : public std::vector<T>
45 {
46 public:
47 typedef typename std::vector<T>::iterator iterator;
48 typedef typename std::vector<T>::const_iterator const_iterator;
49 typedef std::vector<T> _base;
50
51 dbVector<T>& operator=(const std::vector<T>& v)
52 {
53 if (this != &v)
54 *(std::vector<T>*) this = v;
55
56 return *this;
57 }
58
dbVector()59 dbVector() {}
60
dbVector(const dbVector<T> & v)61 dbVector(const dbVector<T>& v) : std::vector<T>(v) {}
62
~dbVector()63 ~dbVector() {}
64
begin()65 iterator begin() { return _base::begin(); }
end()66 iterator end() { return _base::end(); }
begin()67 const_iterator begin() const { return _base::begin(); }
end()68 const_iterator end() const { return _base::end(); }
69 void differences(dbDiff& diff,
70 const char* field,
71 const dbVector<T>& rhs) const;
72 void out(dbDiff& diff, char side, const char* field) const;
73 };
74
75 #ifndef WIN32
76 template <class T>
77 class dbVector<T*> : public std::vector<T*>
78 {
79 public:
80 typedef typename std::vector<T*>::iterator iterator;
81 typedef typename std::vector<T*>::const_iterator const_iterator;
82 typedef std::vector<T*> _base;
83
84 dbVector<T*>& operator=(const std::vector<T*>& v)
85 {
86 if (this != &v)
87 *(std::vector<T>*) this = v;
88
89 return *this;
90 }
91
dbVector()92 dbVector() {}
93
dbVector(const dbVector<T * > & v)94 dbVector(const dbVector<T*>& v) : std::vector<T*>(v) {}
95
~dbVector()96 ~dbVector() {}
97
begin()98 iterator begin() { return _base::begin(); }
end()99 iterator end() { return _base::end(); }
begin()100 const_iterator begin() const { return _base::begin(); }
end()101 const_iterator end() const { return _base::end(); }
102
103 bool operator==(const dbVector<T*>& rhs) const
104 {
105 if (_base::size() != rhs.size())
106 return false;
107
108 typename dbVector<T*>::const_iterator i1 = begin();
109 typename dbVector<T*>::const_iterator i2 = rhs.begin();
110
111 for (; i1 != end(); ++i1, ++i2)
112 if (**i1 != **i2)
113 return false;
114
115 return true;
116 }
117
118 bool operator!=(const dbVector<T*>& rhs) const
119 {
120 return !this->operator==(rhs);
121 }
122
123 void differences(dbDiff& diff,
124 const char* field,
125 const dbVector<T*>& rhs) const;
126 void out(dbDiff& diff, char side, const char* field) const;
127 };
128 #endif
129
130 template <class T>
131 inline dbOStream& operator<<(dbOStream& stream, const dbVector<T>& v)
132 {
133 unsigned int sz = v.size();
134 stream << sz;
135
136 typename dbVector<T>::const_iterator itr;
137
138 for (itr = v.begin(); itr != v.end(); ++itr) {
139 const T& value = *itr;
140 stream << value;
141 }
142
143 return stream;
144 }
145
146 template <class T>
147 inline dbIStream& operator>>(dbIStream& stream, dbVector<T>& v)
148 {
149 v.clear();
150 unsigned int sz;
151 stream >> sz;
152 v.reserve(sz);
153
154 T t;
155 unsigned int i;
156 for (i = 0; i < sz; ++i) {
157 stream >> t;
158 v.push_back(t);
159 }
160
161 return stream;
162 }
163
164 template <class T>
differences(dbDiff & diff,const char * field,const dbVector<T> & rhs)165 inline void dbVector<T>::differences(dbDiff& diff,
166 const char* field,
167 const dbVector<T>& rhs) const
168 {
169 const_iterator i1 = begin();
170 const_iterator i2 = rhs.begin();
171 unsigned int i = 0;
172
173 for (; i1 != end() && i2 != rhs.end(); ++i1, ++i2, ++i) {
174 if (*i1 != *i2) {
175 diff.report("< %s[%d] = ", field, i);
176 diff << *i1;
177 diff << "\n";
178 diff.report("> %s[%d] = ", field, i);
179 diff << *i2;
180 diff << "\n";
181 }
182 }
183
184 for (; i1 != end(); ++i1, ++i) {
185 diff.report("< %s[%d] = ", field, i);
186 diff << *i1;
187 diff << "\n";
188 }
189
190 for (; i2 != rhs.end(); ++i2, ++i) {
191 diff.report("> %s[%d] = ", field, i);
192 diff << *i2;
193 diff << "\n";
194 }
195 }
196
197 template <class T>
out(dbDiff & diff,char side,const char * field)198 inline void dbVector<T>::out(dbDiff& diff, char side, const char* field) const
199 {
200 const_iterator i1 = begin();
201 unsigned int i = 0;
202
203 for (; i1 != end(); ++i1, ++i) {
204 diff.report("%c %s[%d] = ", side, field, i);
205 diff << *i1;
206 diff << "\n";
207 }
208 }
209
210 #ifndef WIN32
211 template <class T>
differences(dbDiff & diff,const char * field,const dbVector<T * > & rhs)212 inline void dbVector<T*>::differences(dbDiff& diff,
213 const char* field,
214 const dbVector<T*>& rhs) const
215 {
216 const_iterator i1 = begin();
217 const_iterator i2 = rhs.begin();
218 unsigned int i = 0;
219
220 for (; i1 != end() && i2 != rhs.end(); ++i1, ++i2, ++i) {
221 if (*i1 != *i2) {
222 diff.report("<> %s[%d]:\n", field, i);
223 (*i1)->differences(diff, NULL, *(*i2));
224 }
225 }
226
227 for (; i1 != end(); ++i1, ++i) {
228 diff.report("< %s[%d]:\n", field, i);
229 (*i1)->out(diff, dbDiff::LEFT, NULL);
230 }
231
232 for (; i2 != rhs.end(); ++i2, ++i) {
233 diff.report("> %s[%d]:\n", field, i);
234 (*i2)->out(diff, dbDiff::RIGHT, NULL);
235 }
236 }
237
238 template <class T>
out(dbDiff & diff,char side,const char * field)239 inline void dbVector<T*>::out(dbDiff& diff, char side, const char* field) const
240 {
241 const_iterator i1 = begin();
242 unsigned int i = 0;
243
244 for (; i1 != end(); ++i1, ++i) {
245 diff.report("%c %s[%d]:\n", side, field, i);
246 (*i1)->out(diff, side, NULL);
247 }
248 }
249
250 #endif
251
252 } // namespace odb
253