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