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 <string>
36 #include <vector>
37 
38 #include "dbId.h"
39 #include "dbObject.h"
40 #include "dbTypes.h"
41 #include "geom.h"
42 #include "odb.h"
43 
44 namespace odb {
45 
46 class dbNet;
47 class dbBTerm;
48 class dbSWire;
49 class dbBlock;
50 class dbInst;
51 
52 class _dbBlock;
53 
54 class dbDiff : public dbObject
55 {
56   int _indent_level;
57   FILE* _f;
58   bool _deep_diff;
59   std::vector<std::string> _headers;
60   int _indent_per_level;
61   bool _has_differences;
62 
63   void write_headers();
64   void indent();
65 
66  public:
67   enum Side
68   {
69     LEFT = '<',
70     RIGHT = '>'
71   };
72 
73   dbDiff(FILE* out_file);
74   ~dbDiff();
75 
hasDifferences()76   bool hasDifferences() const { return _has_differences; }
77 
78   // begin comparison of object
79   void begin(const char* field, const char* objname, uint oid);
80   void begin(const char side, const char* field, const char* objname, uint oid);
81   void begin(const char* field,
82              const char* objname,
83              uint oid,
84              const char* name);
85   void begin(const char side,
86              const char* field,
87              const char* objname,
88              uint oid,
89              const char* name);
90   void begin_object(const char* fmt, ...) ADS_FORMAT_PRINTF(2, 3);
91 
92   // end comparison of object
93   void end_object();
94 
95   // report a difference
96   void report(const char* fmt, ...) ADS_FORMAT_PRINTF(2, 3);
97 
98   // increment the indent level
increment()99   void increment() { ++_indent_level; }
100 
101   // deccrement the indent level
decrement()102   void decrement()
103   {
104     --_indent_level;
105     assert(_indent_level >= 0);
106   }
107 
108   // set the depth of comparison.
setDeepDiff(bool value)109   void setDeepDiff(bool value) { _deep_diff = value; }
110 
111   // return the depth of comparison
deepDiff()112   bool deepDiff() { return _deep_diff; }
113 
114   // Set the indent count per level (default is 4)
setIndentPerLevel(int n)115   void setIndentPerLevel(int n) { _indent_per_level = n; }
116 
117   dbDiff& operator<<(bool c);
118   dbDiff& operator<<(char c);
119   dbDiff& operator<<(unsigned char c);
120   dbDiff& operator<<(short c);
121   dbDiff& operator<<(unsigned short c);
122   dbDiff& operator<<(int c);
123   dbDiff& operator<<(unsigned int c);
124   dbDiff& operator<<(float c);
125   dbDiff& operator<<(double c);
126   dbDiff& operator<<(long double c);
127   dbDiff& operator<<(const char* c);
128   dbDiff& operator<<(const Point& p);
129   dbDiff& operator<<(const Rect& r);
130   dbDiff& operator<<(const Oct& o);
131 
132   void diff(const char* field, bool lhs, bool rhs);
133   void diff(const char* field, char lhs, char rhs);
134   void diff(const char* field, unsigned char lhs, unsigned char rhs);
135   void diff(const char* field, short lhs, short rhs);
136   void diff(const char* field, unsigned short lhs, unsigned short rhs);
137   void diff(const char* field, int lhs, int rhs);
138   void diff(const char* field, unsigned int lhs, unsigned int rhs);
139   void diff(const char* field, float lhs, float rhs);
140   void diff(const char* field, double lhs, double rhs);
141   void diff(const char* field, long double lhs, long double rhs);
142   void diff(const char* field, Point lhs, Point rhs);
143   void diff(const char* field, Rect lhs, Rect rhs);
144   void diff(const char* field, Oct lhs, Oct rhs);
145 
146   void diff(const char* field, const char* lhs, const char* rhs);
147   void diff(const char* field, std::string lhs, std::string rhs);
148   void diff(const char* field,
149             dbOrientType::Value lhs,
150             dbOrientType::Value rhs);
151   void diff(const char* field, dbSigType::Value lhs, dbSigType::Value rhs);
152   void diff(const char* field, dbIoType::Value lhs, dbIoType::Value rhs);
153   void diff(const char* field,
154             dbPlacementStatus::Value lhs,
155             dbPlacementStatus::Value rhs);
156   void diff(const char* field,
157             dbMasterType::Value lhs,
158             dbMasterType::Value rhs);
159   void diff(const char* field,
160             dbTechLayerType::Value lhs,
161             dbTechLayerType::Value rhs);
162   void diff(const char* field,
163             dbTechLayerDir::Value lhs,
164             dbTechLayerDir::Value rhs);
165   void diff(const char* field, dbRowDir::Value lhs, dbRowDir::Value rhs);
166   void diff(const char* field, dbBoxOwner::Value lhs, dbBoxOwner::Value rhs);
167   void diff(const char* field, dbWireType::Value lhs, dbWireType::Value rhs);
168   void diff(const char* field,
169             dbWireShapeType::Value lhs,
170             dbWireShapeType::Value rhs);
171   void diff(const char* field, dbSiteClass::Value lhs, dbSiteClass::Value rhs);
172   void diff(const char* field, dbOnOffType::Value lhs, dbOnOffType::Value rhs);
173   void diff(const char* field,
174             dbClMeasureType::Value lhs,
175             dbClMeasureType::Value rhs);
176   void diff(const char* field, dbDirection::Value lhs, dbDirection::Value rhs);
177 
178   void out(char side, const char* field, bool value);
179   void out(char side, const char* field, char value);
180   void out(char side, const char* field, unsigned char value);
181   void out(char side, const char* field, short value);
182   void out(char side, const char* field, unsigned short value);
183   void out(char side, const char* field, int value);
184   void out(char side, const char* field, unsigned int value);
185   void out(char side, const char* field, float value);
186   void out(char side, const char* field, double value);
187   void out(char side, const char* field, long double value);
188   void out(char side, const char* field, Point value);
189   void out(char side, const char* field, Rect value);
190   void out(char side, const char* field, Oct value);
191   void out(char side, const char* field, const char* value);
192   void out(char side, const char* field, std::string value);
193   void out(char side, const char* field, dbOrientType::Value value);
194   void out(char side, const char* field, dbSigType::Value value);
195   void out(char side, const char* field, dbIoType::Value value);
196   void out(char side, const char* field, dbPlacementStatus::Value value);
197   void out(char side, const char* field, dbMasterType::Value value);
198   void out(char side, const char* field, dbTechLayerType::Value value);
199   void out(char side, const char* field, dbTechLayerDir::Value value);
200   void out(char side, const char* field, dbRowDir::Value value);
201   void out(char side, const char* field, dbBoxOwner::Value value);
202   void out(char side, const char* field, dbWireType::Value value);
203   void out(char side, const char* field, dbWireShapeType::Value value);
204   void out(char side, const char* field, dbSiteClass::Value value);
205   void out(char side, const char* field, dbOnOffType::Value value);
206   void out(char side, const char* field, dbClMeasureType::Value value);
207   void out(char side, const char* field, dbDirection::Value value);
208 };
209 
210 #define DIFF_BEGIN \
211   { /* } */        \
212     diff.begin(field, getObjName(), getId());
213 
214 #define DIFF_OUT_BEGIN \
215   { /* } */            \
216     diff.begin(side, field, getObjName(), getId());
217 
218 #define DIFF_END             \
219   diff.end_object(); /* { */ \
220   }
221 
222 #define DIFF_FIELD(FIELD) diff.diff(#FIELD, FIELD, rhs.FIELD);
223 
224 #define DIFF_FIELD_NO_DEEP(FIELD) \
225   if (!diff.deepDiff())           \
226     diff.diff(#FIELD, FIELD, rhs.FIELD);
227 
228 #define DIFF_STRUCT(FIELD)                      \
229   if (FIELD != rhs.FIELD) {                     \
230     FIELD.differences(diff, #FIELD, rhs.FIELD); \
231   }
232 
233 #define DIFF_NAME_CACHE(FIELD)                    \
234   if (*FIELD != *rhs.FIELD) {                     \
235     FIELD->differences(diff, #FIELD, *rhs.FIELD); \
236   }
237 
238 #define DIFF_VECTOR(FIELD)                      \
239   if (FIELD != rhs.FIELD) {                     \
240     FIELD.differences(diff, #FIELD, rhs.FIELD); \
241   }
242 
243 #define DIFF_VECTOR_DEEP(FIELD)                           \
244   if (FIELD != rhs.FIELD) {                               \
245     if (!diff.deepDiff())                                 \
246       FIELD.differences(diff, #FIELD, rhs.FIELD);         \
247     else                                                  \
248       set_symmetric_diff(diff, #FIELD, FIELD, rhs.FIELD); \
249   }
250 
251 #define DIFF_MATRIX(FIELD)                      \
252   if (FIELD != rhs.FIELD) {                     \
253     FIELD.differences(diff, #FIELD, rhs.FIELD); \
254   }
255 
256 #define DIFF_VECTOR_PTR(FIELD)                  \
257   if (FIELD != rhs.FIELD) {                     \
258     FIELD.differences(diff, #FIELD, rhs.FIELD); \
259   }
260 
261 #define DIFF_HASH_TABLE(FIELD)                  \
262   if (FIELD != rhs.FIELD) {                     \
263     FIELD.differences(diff, #FIELD, rhs.FIELD); \
264   }
265 
266 #define DIFF_OBJECT(FIELD, LHS_TBL, RHS_TBL) \
267   diff_object(diff, #FIELD, FIELD, rhs.FIELD, LHS_TBL, RHS_TBL);
268 
269 #define DIFF_SET(FIELD, LHS_ITR, RHS_ITR) \
270   diff_set(diff,                          \
271            #FIELD,                        \
272            FIELD,                         \
273            rhs.FIELD,                     \
274            (dbObject*) this,              \
275            (dbObject*) &rhs,              \
276            LHS_ITR,                       \
277            RHS_ITR);
278 
279 #define DIFF_TABLE_NO_DEEP(TABLE)         \
280   if (!diff.deepDiff()) {                 \
281     TABLE->differences(diff, *rhs.TABLE); \
282   }
283 
284 #define DIFF_TABLE(TABLE)                                 \
285   if (diff.deepDiff()) {                                  \
286     set_symmetric_diff(diff, #TABLE, *TABLE, *rhs.TABLE); \
287   } else {                                                \
288     TABLE->differences(diff, *rhs.TABLE);                 \
289   }
290 
291 #define DIFF_OUT_FIELD(FIELD) diff.out(side, #FIELD, FIELD);
292 
293 #define DIFF_OUT_FIELD_NO_DEEP(FIELD) \
294   if (!diff.deepDiff())               \
295     diff.out(side, #FIELD, FIELD);
296 
297 #define DIFF_OUT_STRUCT(FIELD) FIELD.out(diff, side, #FIELD);
298 
299 #define DIFF_OUT_NAME_CACHE(FIELD) FIELD->out(diff, side, #FIELD);
300 
301 #define DIFF_OUT_VECTOR(FIELD) FIELD.out(diff, side, #FIELD);
302 
303 #define DIFF_OUT_MATRIX(FIELD) FIELD.out(diff, side, #FIELD);
304 
305 #define DIFF_OUT_VECTOR_PTR(FIELD) FIELD.out(diff, side, #FIELD);
306 
307 #define DIFF_OUT_HASH_TABLE(FIELD) FIELD.out(diff, side, #FIELD);
308 
309 #define DIFF_OUT_OBJECT(FIELD, LHS_TBL) \
310   diff_out_object(diff, side, #FIELD, FIELD, LHS_TBL);
311 
312 #define DIFF_OUT_SET(FIELD, LHS_ITR) \
313   diff_out_set(diff, side, #FIELD, FIELD, (dbObject*) this, LHS_ITR);
314 
315 #define DIFF_OUT_TABLE_NO_DEEP(TABLE) \
316   if (!diff.deepDiff())               \
317     TABLE->out(diff, side);
318 
319 #define DIFF_OUT_TABLE(TABLE) TABLE->out(diff, side);
320 
321 template <class T>
322 class dbDiffCmp
323 {
324  public:
operator()325   int operator()(const T* lhs, const T* rhs) const { return *lhs < *rhs; }
326 };
327 
328 template <class T>
329 class dbDiffDifferences
330 {
331  public:
operator()332   void operator()(dbDiff& diff,
333                   const char* field,
334                   const T* lhs,
335                   const T* rhs) const
336   {
337     lhs->differences(diff, field, rhs);
338   }
339 };
340 
341 template <class T>
342 class dbDiffOut
343 {
344  public:
operator()345   void operator()(dbDiff& diff, char side, const char* field, const T* o) const
346   {
347     o->out(diff, side, field);
348   }
349 };
350 
351 template <class T>
352 class dbTable;
353 template <class T>
354 class dbArrayTable;
355 class dbIterator;
356 
357 template <class T>
358 void diff_object(dbDiff& diff,
359                  const char* field,
360                  dbId<T> lhs,
361                  dbId<T> rhs,
362                  dbTable<T>* lhs_tbl,
363                  dbTable<T>* rhs_tbl);
364 
365 template <class T>
366 void diff_object(dbDiff& diff,
367                  const char* field,
368                  dbId<T> lhs,
369                  dbId<T> rhs,
370                  dbArrayTable<T>* lhs_tbl,
371                  dbArrayTable<T>* rhs_tbl);
372 
373 template <class T>
374 void diff_set(dbDiff& diff,
375               const char* field,
376               dbId<T> lhs,
377               dbId<T> rhs,
378               dbObject* lhs_owner,
379               dbObject* rhs_owner,
380               dbIterator* lhs_itr,
381               dbIterator* rhs_itr);
382 
383 template <class T>
384 void set_symmetric_diff(dbDiff& diff,
385                         const char* field,
386                         std::vector<T*>& lhs,
387                         std::vector<T*>& rhs);
388 
389 template <class T>
390 void set_symmetric_diff(dbDiff& diff,
391                         const char* field,
392                         const std::vector<T>& lhs,
393                         const std::vector<T>& rhs);
394 
395 template <class T>
396 void set_symmetric_diff(dbDiff& diff,
397                         const char* field,
398                         dbTable<T>& lhs,
399                         dbTable<T>& rhs);
400 
401 template <class T>
402 void set_symmetric_diff(dbDiff& diff,
403                         const char* field,
404                         dbArrayTable<T>& lhs,
405                         dbArrayTable<T>& rhs);
406 
407 template <class T>
408 void diff_out_object(dbDiff& diff,
409                      char side,
410                      const char* field,
411                      dbId<T> id,
412                      dbTable<T>* tbl);
413 
414 template <class T>
415 void diff_out_object(dbDiff& diff,
416                      char side,
417                      const char* field,
418                      dbId<T> id,
419                      dbArrayTable<T>* tbl);
420 
421 template <class T>
422 void diff_out_set(dbDiff& diff,
423                   char side,
424                   const char* field,
425                   dbId<T> id,
426                   dbObject* owner,
427                   dbIterator* itr);
428 
429 }  // namespace odb
430