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 #include "dbProperty.h"
34 
35 #include "db.h"
36 #include "dbBlock.h"
37 #include "dbChip.h"
38 #include "dbDatabase.h"
39 #include "dbLib.h"
40 #include "dbName.h"
41 #include "dbNameCache.h"
42 #include "dbPropertyItr.h"
43 #include "dbTable.h"
44 #include "dbTable.hpp"
45 #include "dbTech.h"
46 
47 namespace odb {
48 
49 template class dbTable<_dbProperty>;
50 
_dbProperty(_dbDatabase *,const _dbProperty & n)51 _dbProperty::_dbProperty(_dbDatabase*, const _dbProperty& n)
52     : _flags(n._flags), _name(n._name), _next(n._next), _owner(n._owner)
53 {
54   memcpy(&_value, &n._value, sizeof(_value));
55 }
56 
_dbProperty(_dbDatabase *)57 _dbProperty::_dbProperty(_dbDatabase*)
58 {
59   _flags._type = DB_STRING_PROP;
60   _flags._spare_bits = 0;
61   _name = 0;
62   _owner = 0;
63   memset(&_value, 0, sizeof(_value));
64 }
65 
~_dbProperty()66 _dbProperty::~_dbProperty()
67 {
68 }
69 
operator ==(const _dbProperty & rhs) const70 bool _dbProperty::operator==(const _dbProperty& rhs) const
71 {
72   if (_flags._type != rhs._flags._type)
73     return false;
74 
75   if (_flags._owner_type != rhs._flags._owner_type)
76     return false;
77 
78   if (_name != rhs._name)
79     return false;
80 
81   if (_flags._owner_type
82       != dbDatabaseObj)  // database owners are never the same...
83     if (_owner != rhs._owner)
84       return false;
85 
86   if (_next != rhs._next)
87     return false;
88 
89   switch (_flags._type) {
90     case DB_STRING_PROP:
91       if (strcmp(_value._str_val, rhs._value._str_val) != 0)
92         return false;
93 
94       break;
95 
96     case DB_BOOL_PROP:
97       if (_value._bool_val != rhs._value._bool_val)
98         return false;
99 
100       break;
101 
102     case DB_INT_PROP:
103       if (_value._int_val != rhs._value._int_val)
104         return false;
105 
106       break;
107 
108     case DB_DOUBLE_PROP:
109       if (_value._double_val != rhs._value._double_val)
110         return false;
111 
112       break;
113   }
114 
115   return true;
116 }
117 
differences(dbDiff & diff,const char * field,const _dbProperty & rhs) const118 void _dbProperty::differences(dbDiff& diff,
119                               const char* field,
120                               const _dbProperty& rhs) const
121 {
122   DIFF_BEGIN
123   DIFF_FIELD(_flags._type);
124   DIFF_FIELD(_flags._owner_type);
125   DIFF_FIELD(_name);
126 
127   if (_flags._owner_type
128       != dbDatabaseObj)  // database owners are never the same...
129   {
130     DIFF_FIELD(_owner);
131   }
132 
133   DIFF_FIELD(_next);
134   DIFF_END
135 }
136 
out(dbDiff & diff,char side,const char * field) const137 void _dbProperty::out(dbDiff& diff, char side, const char* field) const
138 {
139   DIFF_OUT_BEGIN
140   DIFF_OUT_FIELD(_flags._type);
141   DIFF_OUT_FIELD(_flags._owner_type);
142   DIFF_OUT_FIELD(_name);
143   DIFF_OUT_FIELD(_owner);
144   DIFF_OUT_FIELD(_next);
145   DIFF_END
146 }
147 
operator <<(dbOStream & stream,const _dbProperty & prop)148 dbOStream& operator<<(dbOStream& stream, const _dbProperty& prop)
149 {
150   uint* bit_field = (uint*) &prop._flags;
151   stream << *bit_field;
152   stream << prop._name;
153   stream << prop._next;
154   stream << prop._owner;
155 
156   switch (prop._flags._type) {
157     case DB_BOOL_PROP:
158       stream << prop._value._bool_val;
159       break;
160 
161     case DB_INT_PROP:
162       stream << prop._value._int_val;
163       break;
164 
165     case DB_STRING_PROP:
166       stream << prop._value._str_val;
167       break;
168 
169     case DB_DOUBLE_PROP:
170       stream << prop._value._double_val;
171       break;
172   }
173 
174   return stream;
175 }
176 
operator >>(dbIStream & stream,_dbProperty & prop)177 dbIStream& operator>>(dbIStream& stream, _dbProperty& prop)
178 {
179   uint* bit_field = (uint*) &prop._flags;
180   stream >> *bit_field;
181   stream >> prop._name;
182   stream >> prop._next;
183   stream >> prop._owner;
184 
185   switch (prop._flags._type) {
186     case DB_BOOL_PROP:
187       stream >> prop._value._bool_val;
188       break;
189 
190     case DB_INT_PROP:
191       stream >> prop._value._int_val;
192       break;
193 
194     case DB_STRING_PROP:
195       stream >> prop._value._str_val;
196       break;
197 
198     case DB_DOUBLE_PROP:
199       stream >> prop._value._double_val;
200       break;
201   }
202 
203   return stream;
204 }
205 
operator <(const _dbProperty & rhs) const206 bool _dbProperty::operator<(const _dbProperty& rhs) const
207 {
208   return _name < rhs._name;
209 }
210 
getItr(dbObject * object)211 dbPropertyItr* _dbProperty::getItr(dbObject* object)
212 {
213 next_object:
214   switch (object->getObjectType()) {
215     case dbDatabaseObj: {
216       _dbDatabase* db = (_dbDatabase*) object;
217       return db->_prop_itr;
218     }
219 
220     case dbChipObj: {
221       _dbChip* chip = (_dbChip*) object;
222       return chip->_prop_itr;
223     }
224 
225     case dbBlockObj: {
226       _dbBlock* blk = (_dbBlock*) object;
227       return blk->_prop_itr;
228     }
229 
230     case dbLibObj: {
231       _dbLib* lib = (_dbLib*) object;
232       return lib->_prop_itr;
233     }
234 
235     case dbTechObj: {
236       _dbTech* tech = (_dbTech*) object;
237       return tech->_prop_itr;
238     }
239 
240     default:
241       object = object->getImpl()->getOwner();
242       goto next_object;
243   }
244 
245   assert(0);
246   return NULL;
247 }
248 
getNameCache(dbObject * object)249 _dbNameCache* _dbProperty::getNameCache(dbObject* object)
250 {
251 next_object:
252   switch (object->getObjectType()) {
253     case dbDatabaseObj: {
254       _dbDatabase* db = (_dbDatabase*) object;
255       return db->_name_cache;
256     }
257 
258     case dbChipObj: {
259       _dbChip* chip = (_dbChip*) object;
260       return chip->_name_cache;
261     }
262 
263     case dbBlockObj: {
264       _dbBlock* blk = (_dbBlock*) object;
265       return blk->_name_cache;
266     }
267 
268     case dbLibObj: {
269       _dbLib* lib = (_dbLib*) object;
270       return lib->_name_cache;
271     }
272 
273     case dbTechObj: {
274       _dbTech* tech = (_dbTech*) object;
275       return tech->_name_cache;
276     }
277 
278     default:
279       object = object->getImpl()->getOwner();
280       goto next_object;
281   }
282 
283   assert(0);
284   return NULL;
285 }
286 
getPropTable(dbObject * object)287 dbTable<_dbProperty>* _dbProperty::getPropTable(dbObject* object)
288 {
289 next_object:
290   switch (object->getObjectType()) {
291     case dbDatabaseObj: {
292       _dbDatabase* db = (_dbDatabase*) object;
293       return db->_prop_tbl;
294     }
295 
296     case dbChipObj: {
297       _dbChip* chip = (_dbChip*) object;
298       return chip->_prop_tbl;
299     }
300 
301     case dbBlockObj: {
302       _dbBlock* blk = (_dbBlock*) object;
303       return blk->_prop_tbl;
304     }
305 
306     case dbLibObj: {
307       _dbLib* lib = (_dbLib*) object;
308       return lib->_prop_tbl;
309     }
310 
311     case dbTechObj: {
312       _dbTech* tech = (_dbTech*) object;
313       return tech->_prop_tbl;
314     }
315 
316     default:
317       object = object->getImpl()->getOwner();
318       goto next_object;
319   }
320 
321   assert(0);
322   return NULL;
323 }
324 
createProperty(dbObject * object_,const char * name,_PropTypeEnum type)325 _dbProperty* _dbProperty::createProperty(dbObject* object_,
326                                          const char* name,
327                                          _PropTypeEnum type)
328 {
329   _dbObject* object = (_dbObject*) object_;
330   dbTable<_dbProperty>* propTable = getPropTable(object);
331 
332   // Create property
333   _dbProperty* prop = propTable->create();
334   uint oid = object->getOID();
335   prop->_flags._type = type;
336   prop->_flags._owner_type = object->getType();
337   prop->_owner = oid;
338 
339   // Get name-id, increment reference count
340   _dbNameCache* cache = getNameCache(object);
341   uint name_id = cache->addName(name);
342   prop->_name = name_id;
343 
344   // Link property into owner's prop-list
345   dbObjectTable* table = object->getTable();
346   dbId<_dbProperty> propList = table->getPropList(oid);
347   prop->_next = propList;
348   propList = prop->getImpl()->getOID();
349   table->setPropList(oid, propList);
350   return prop;
351 }
352 
353 /////////////////////////////////////////////
354 // property
355 /////////////////////////////////////////////
356 
getType()357 dbProperty::Type dbProperty::getType()
358 {
359   _dbProperty* prop = (_dbProperty*) this;
360   return (dbProperty::Type) prop->_flags._type;
361 }
362 
getName()363 std::string dbProperty::getName()
364 {
365   _dbProperty* prop = (_dbProperty*) this;
366   _dbNameCache* cache = _dbProperty::getNameCache(this);
367   const char* name = cache->getName(prop->_name);
368   return name;
369 }
370 
getPropOwner()371 dbObject* dbProperty::getPropOwner()
372 {
373   _dbProperty* prop = (_dbProperty*) this;
374   dbObjectTable* table = prop->getTable()->getObjectTable(
375       (dbObjectType) prop->_flags._owner_type);
376   return table->getObject(prop->_owner);
377 }
378 
find(dbObject * object,const char * name)379 dbProperty* dbProperty::find(dbObject* object, const char* name)
380 {
381   _dbNameCache* cache = _dbProperty::getNameCache(object);
382 
383   uint name_id = cache->findName(name);
384 
385   if (name_id == 0)
386     return NULL;
387 
388   dbSet<dbProperty> props = getProperties(object);
389 
390   dbSet<dbProperty>::iterator itr;
391 
392   for (itr = props.begin(); itr != props.end(); ++itr) {
393     _dbProperty* p = (_dbProperty*) *itr;
394 
395     if (p->_name == name_id)
396       return (dbProperty*) p;
397   }
398 
399   return NULL;
400 }
401 
find(dbObject * object,const char * name,Type type)402 dbProperty* dbProperty::find(dbObject* object, const char* name, Type type)
403 {
404   _dbNameCache* cache = _dbProperty::getNameCache(object);
405 
406   uint name_id = cache->findName(name);
407 
408   if (name_id == 0)
409     return NULL;
410 
411   dbSet<dbProperty> props = getProperties(object);
412 
413   dbSet<dbProperty>::iterator itr;
414 
415   for (itr = props.begin(); itr != props.end(); ++itr) {
416     _dbProperty* p = (_dbProperty*) *itr;
417 
418     if ((p->_name == name_id) && (p->_flags._type == (_PropTypeEnum) type))
419       return (dbProperty*) p;
420   }
421 
422   return NULL;
423 }
424 
getProperties(dbObject * object)425 dbSet<dbProperty> dbProperty::getProperties(dbObject* object)
426 {
427   dbSet<dbProperty> props(object, _dbProperty::getItr(object));
428   return props;
429 }
430 
destroy(dbProperty * prop_)431 void dbProperty::destroy(dbProperty* prop_)
432 {
433   _dbProperty* prop = (_dbProperty*) prop_;
434 
435   // unlink property from owner
436   dbTable<_dbProperty>* propTable = _dbProperty::getPropTable(prop);
437   dbObjectTable* ownerTable = prop->getTable()->getObjectTable(
438       (dbObjectType) prop->_flags._owner_type);
439 
440   dbId<_dbProperty> propList = ownerTable->getPropList(prop->_owner);
441   dbId<_dbProperty> cur = propList;
442   uint oid = prop->getOID();
443 
444   while (cur) {
445     _dbProperty* p = propTable->getPtr(cur);
446 
447     if (cur == oid) {
448       if (cur == propList)
449         ownerTable->setPropList(prop->_owner, p->_next);
450       else
451         p->_next = prop->_next;
452 
453       break;
454     }
455 
456     cur = p->_next;
457   }
458 
459   // Remove reference to name
460   _dbNameCache* cache = _dbProperty::getNameCache(prop);
461   cache->removeName(prop->_name);
462 
463   // destroy hier. props.
464   dbProperty::destroyProperties(prop);
465   // destroy the prop
466   propTable->destroy(prop);
467 }
468 
destroyProperties(dbObject * obj)469 void dbProperty::destroyProperties(dbObject* obj)
470 {
471   _dbObject* object = obj->getImpl();
472   uint oid = object->getOID();
473   dbObjectTable* objTable = object->getTable();
474   dbId<_dbProperty> cur = objTable->getPropList(oid);
475 
476   if (!cur)
477     return;
478 
479   _dbNameCache* cache = _dbProperty::getNameCache(obj);
480   dbTable<_dbProperty>* propTable = _dbProperty::getPropTable(obj);
481   while (cur) {
482     _dbProperty* p = propTable->getPtr(cur);
483     cache->removeName(p->_name);
484     cur = p->_next;
485     dbProperty::destroyProperties(p);
486     propTable->destroy(p);
487   }
488 
489   objTable->setPropList(oid, cur);
490 }
491 
destroy(dbSet<dbProperty>::iterator itr)492 dbSet<dbProperty>::iterator dbProperty::destroy(dbSet<dbProperty>::iterator itr)
493 {
494   dbProperty* p = *itr;
495   dbSet<dbProperty>::iterator n = ++itr;
496   dbProperty::destroy(p);
497   return n;
498 }
499 
500 /////////////////////////////////////////////
501 // bool property
502 /////////////////////////////////////////////
503 
getValue()504 bool dbBoolProperty::getValue()
505 {
506   _dbProperty* prop = (_dbProperty*) this;
507   return prop->_value._bool_val;
508 }
509 
setValue(bool value)510 void dbBoolProperty::setValue(bool value)
511 {
512   _dbProperty* prop = (_dbProperty*) this;
513   prop->_value._bool_val = value;
514 }
515 
create(dbObject * object,const char * name,bool value)516 dbBoolProperty* dbBoolProperty::create(dbObject* object,
517                                        const char* name,
518                                        bool value)
519 {
520   if (find(object, name))
521     return NULL;
522 
523   _dbProperty* prop = _dbProperty::createProperty(object, name, DB_BOOL_PROP);
524   prop->_value._bool_val = value;
525   return (dbBoolProperty*) prop;
526 }
527 
find(dbObject * object,const char * name)528 dbBoolProperty* dbBoolProperty::find(dbObject* object, const char* name)
529 {
530   return (dbBoolProperty*) dbProperty::find(
531       object, name, dbProperty::BOOL_PROP);
532 }
533 
534 /////////////////////////////////////////////
535 // string property
536 /////////////////////////////////////////////
537 
getValue()538 std::string dbStringProperty::getValue()
539 {
540   _dbProperty* prop = (_dbProperty*) this;
541   return prop->_value._str_val;
542 }
543 
setValue(const char * value)544 void dbStringProperty::setValue(const char* value)
545 {
546   _dbProperty* prop = (_dbProperty*) this;
547   assert(value);
548 
549   if (prop->_value._str_val)
550     free((void*) prop->_value._str_val);
551 
552   prop->_value._str_val = strdup(value);
553   ZALLOCATED(prop->_value._str_val);
554 }
555 
create(dbObject * object,const char * name,const char * value)556 dbStringProperty* dbStringProperty::create(dbObject* object,
557                                            const char* name,
558                                            const char* value)
559 {
560   _dbProperty* prop = (_dbProperty*) find(object, name);
561   if (prop) {
562     std::string val = std::string(prop->_value._str_val) + " " + value;
563     free(prop->_value._str_val);
564     prop->_value._str_val = strdup(val.c_str());
565     ZALLOCATED(prop->_value._str_val);
566     return (dbStringProperty*) prop;
567   }
568 
569   prop = _dbProperty::createProperty(object, name, DB_STRING_PROP);
570   prop->_value._str_val = strdup(value);
571   ZALLOCATED(prop->_value._str_val);
572   return (dbStringProperty*) prop;
573 }
574 
find(dbObject * object,const char * name)575 dbStringProperty* dbStringProperty::find(dbObject* object, const char* name)
576 {
577   return (dbStringProperty*) dbProperty::find(
578       object, name, dbProperty::STRING_PROP);
579 }
580 
581 /////////////////////////////////////////////
582 // int property
583 /////////////////////////////////////////////
584 
getValue()585 int dbIntProperty::getValue()
586 {
587   _dbProperty* prop = (_dbProperty*) this;
588   return prop->_value._int_val;
589 }
590 
setValue(int value)591 void dbIntProperty::setValue(int value)
592 {
593   _dbProperty* prop = (_dbProperty*) this;
594   prop->_value._int_val = value;
595 }
596 
create(dbObject * object,const char * name,int value)597 dbIntProperty* dbIntProperty::create(dbObject* object,
598                                      const char* name,
599                                      int value)
600 {
601   if (find(object, name))
602     return NULL;
603 
604   _dbProperty* prop = _dbProperty::createProperty(object, name, DB_INT_PROP);
605   prop->_value._int_val = value;
606   return (dbIntProperty*) prop;
607 }
608 
find(dbObject * object,const char * name)609 dbIntProperty* dbIntProperty::find(dbObject* object, const char* name)
610 {
611   return (dbIntProperty*) dbProperty::find(object, name, dbProperty::INT_PROP);
612 }
613 
614 /////////////////////////////////////////////
615 // double property
616 /////////////////////////////////////////////
617 
getValue()618 double dbDoubleProperty::getValue()
619 {
620   _dbProperty* prop = (_dbProperty*) this;
621   return prop->_value._double_val;
622 }
623 
setValue(double value)624 void dbDoubleProperty::setValue(double value)
625 {
626   _dbProperty* prop = (_dbProperty*) this;
627   prop->_value._double_val = value;
628 }
629 
create(dbObject * object,const char * name,double value)630 dbDoubleProperty* dbDoubleProperty::create(dbObject* object,
631                                            const char* name,
632                                            double value)
633 {
634   if (find(object, name))
635     return NULL;
636 
637   _dbProperty* prop = _dbProperty::createProperty(object, name, DB_DOUBLE_PROP);
638   prop->_value._double_val = value;
639   return (dbDoubleProperty*) prop;
640 }
641 
find(dbObject * object,const char * name)642 dbDoubleProperty* dbDoubleProperty::find(dbObject* object, const char* name)
643 {
644   return (dbDoubleProperty*) dbProperty::find(
645       object, name, dbProperty::DOUBLE_PROP);
646 }
647 
writePropValue(dbProperty * prop,FILE * out)648 void dbProperty::writePropValue(dbProperty* prop, FILE* out)
649 {
650   switch (prop->getType()) {
651     case dbProperty::STRING_PROP: {
652       dbStringProperty* p = (dbStringProperty*) prop;
653       std::string v = p->getValue();
654       fprintf(out, "\"%s\" ", v.c_str());
655       break;
656     }
657 
658     case dbProperty::INT_PROP: {
659       dbIntProperty* p = (dbIntProperty*) prop;
660       int v = p->getValue();
661       fprintf(out, "%d ", v);
662       break;
663     }
664 
665     case dbProperty::DOUBLE_PROP: {
666       dbDoubleProperty* p = (dbDoubleProperty*) prop;
667       double v = p->getValue();
668       fprintf(out, "%G ", v);
669     }
670 
671     default:
672       break;
673   }
674 }
675 
writeProperties(dbObject * object,FILE * out)676 void dbProperty::writeProperties(dbObject* object, FILE* out)
677 {
678   dbSet<dbProperty> props = dbProperty::getProperties(object);
679   dbSet<dbProperty>::iterator itr;
680 
681   for (itr = props.begin(); itr != props.end(); ++itr) {
682     dbProperty* prop = *itr;
683     std::string name = prop->getName();
684     fprintf(out, "    PROPERTY %s ", name.c_str());
685     writePropValue(prop, out);
686     fprintf(out, ";\n");
687   }
688 }
689 
690 /* Sample Code to access dbTechLayer properties
691 void dbProperty::writeProperties( dbTechLayer * object, FILE *out )
692 {
693     dbSet<dbProperty> props = dbProperty::getProperties(object);
694     dbSet<dbProperty>::iterator itr;
695 
696     for( itr = props.begin(); itr != props.end(); ++itr )
697     {
698         dbProperty * prop = *itr;
699         std::string name = prop->getName();
700 
701         to get value of a  string type:
702              dbStringProperty * p = (dbStringProperty *) prop;
703             std::string v = p->getValue();
704         look function dbProperty::writePropValue on how to retrieve int and
705 double values
706     }
707 }
708 */
709 
710 }  // namespace odb
711