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