1 /*
2    Copyright (C) 2003-2006, 2008 MySQL AB, 2008, 2009 Sun Microsystems, Inc.
3     All rights reserved. Use is subject to license terms.
4 
5    This program is free software; you can redistribute it and/or modify
6    it under the terms of the GNU General Public License, version 2.0,
7    as published by the Free Software Foundation.
8 
9    This program is also distributed with certain software (including
10    but not limited to OpenSSL) that is licensed under separate terms,
11    as designated in a particular file or component or in included license
12    documentation.  The authors of MySQL hereby grant you an additional
13    permission to link the program and your derivative works with the
14    separately licensed software that they have included with MySQL.
15 
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License, version 2.0, for more details.
20 
21    You should have received a copy of the GNU General Public License
22    along with this program; if not, write to the Free Software
23    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
24 */
25 
26 #include <ndb_global.h>
27 
28 #include <Properties.hpp>
29 
30 #include <NdbTCP.h>
31 #include <NdbOut.hpp>
32 
33 static
f_strdup(const char * s)34 char * f_strdup(const char * s){
35   if(!s) return 0;
36   return strdup(s);
37 }
38 
39 /**
40  * Note has to be a multiple of 4 bytes
41  */
42 const char Properties::version[] = { 2, 0, 0, 1, 1, 1, 1, 4 };
43 const char Properties::delimiter = ':';
44 
45 /**
46  * PropertyImpl
47  */
48 struct PropertyImpl{
49   PropertiesType valueType;
50   const char * name;
51   void * value;
52 
53   ~PropertyImpl();
54   PropertyImpl(const char * name, Uint32 value);
55   PropertyImpl(const char * name, Uint64 value);
56   PropertyImpl(const char * name, const char * value);
57   PropertyImpl(const char * name, const Properties * value);
58 
59   static PropertyImpl * copyPropertyImpl(const PropertyImpl &);
60 };
61 
62 /**
63  * PropertiesImpl
64  */
65 class PropertiesImpl {
66   PropertiesImpl(const PropertiesImpl &);           // Not implemented
67   PropertiesImpl& operator=(const PropertiesImpl&); // Not implemented
68 public:
69   PropertiesImpl(Properties *, bool case_insensitive);
70   PropertiesImpl(Properties *, const PropertiesImpl &);
71   ~PropertiesImpl();
72 
73   Properties * properties;
74 
75   Uint32 size;
76   Uint32 items;
77   PropertyImpl **content;
78 
79   bool m_insensitive;
80   int (* compare)(const char *s1, const char *s2);
81 
82   void setCaseInsensitiveNames(bool value);
83   void grow(int sizeToAdd);
84 
85   PropertyImpl * get(const char * name) const;
86   PropertyImpl * put(PropertyImpl *);
87   void remove(const char * name);
88 
89   Uint32 getPackedSize(Uint32 pLen) const;
90   bool pack(Uint32 *& buf, const char * prefix, Uint32 prefixLen) const;
91   bool unpack(const Uint32 * buf, Uint32 &bufLen, Properties * top, int items);
92 
93   Uint32 getTotalItems() const;
94 
setErrno(Uint32 pErr,Uint32 osErr=0)95   void setErrno(Uint32 pErr, Uint32 osErr = 0){
96     properties->setErrno(pErr, osErr);
97   }
98 
99   const char * getProps(const char * name, const PropertiesImpl ** impl) const;
100   const char * getPropsPut(const char * name, PropertiesImpl ** impl);
101 };
102 
103 /**
104  * Methods for Property
105  */
Property(const char * name,Uint32 value)106 Property::Property(const char * name, Uint32 value){
107   impl = new PropertyImpl(name, value);
108 }
109 
Property(const char * name,const char * value)110 Property::Property(const char * name, const char * value){
111   impl = new PropertyImpl(name, value);
112 }
113 
Property(const char * name,const class Properties * value)114 Property::Property(const char * name, const class Properties * value){
115   impl = new PropertyImpl(name, value);
116 
117   ((Properties*)impl->value)->setCaseInsensitiveNames(value->getCaseInsensitiveNames());
118 }
119 
~Property()120 Property::~Property(){
121   delete impl;
122 }
123 
124 /**
125  * Methods for Properties
126  */
Properties(bool case_insensitive)127 Properties::Properties(bool case_insensitive){
128   parent = 0;
129   impl = new PropertiesImpl(this, case_insensitive);
130 }
131 
Properties(const Properties & org)132 Properties::Properties(const Properties & org){
133   parent = 0;
134   impl = new PropertiesImpl(this, * org.impl);
135 }
136 
Properties(const Property * anArray,int arrayLen)137 Properties::Properties(const Property * anArray, int arrayLen){
138   impl = new PropertiesImpl(this, false);
139 
140   put(anArray, arrayLen);
141 }
142 
~Properties()143 Properties::~Properties(){
144   clear();
145   delete impl;
146 }
147 
148 void
put(const Property * anArray,int arrayLen)149 Properties::put(const Property * anArray, int arrayLen){
150   if(anArray == 0)
151     return;
152   for(int i = 0; i<arrayLen; i++)
153     impl->put(anArray[i].impl);
154 }
155 
156 template <class T>
157 bool
put(PropertiesImpl * impl,const char * name,T value,bool replace)158 put(PropertiesImpl * impl, const char * name, T value, bool replace){
159   if(name == 0){
160     impl->setErrno(E_PROPERTIES_INVALID_NAME);
161     return false;
162   }
163 
164   PropertiesImpl * tmp = 0;
165   const char * short_name = impl->getPropsPut(name, &tmp);
166 
167   if(tmp == 0){
168     impl->setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
169     return false;
170   }
171 
172   if(tmp->get(short_name) != 0){
173     if(replace){
174       tmp->remove(short_name);
175     } else {
176       impl->setErrno(E_PROPERTIES_ELEMENT_ALREADY_EXISTS);
177       return false;
178     }
179   }
180   return (tmp->put(new PropertyImpl(short_name, value)) != 0);
181 }
182 
183 
184 bool
put(const char * name,Uint32 value,bool replace)185 Properties::put(const char * name, Uint32 value, bool replace){
186   return ::put(impl, name, value, replace);
187 }
188 
189 bool
put64(const char * name,Uint64 value,bool replace)190 Properties::put64(const char * name, Uint64 value, bool replace){
191   return ::put(impl, name, value, replace);
192 }
193 
194 bool
put(const char * name,const char * value,bool replace)195 Properties::put(const char * name, const char * value, bool replace){
196   return ::put(impl, name, value, replace);
197 }
198 
199 bool
put(const char * name,const Properties * value,bool replace)200 Properties::put(const char * name, const Properties * value, bool replace){
201   return ::put(impl, name, value, replace);
202 }
203 
204 bool
getTypeOf(const char * name,PropertiesType * type) const205 Properties::getTypeOf(const char * name, PropertiesType * type) const {
206   PropertyImpl * nvp = impl->get(name);
207   if(nvp == 0){
208     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
209     return false;
210   }
211   setErrno(E_PROPERTIES_OK);
212   * type = nvp->valueType;
213   return true;
214 }
215 
216 bool
contains(const char * name) const217 Properties::contains(const char * name) const {
218   PropertyImpl * nvp = impl->get(name);
219   return nvp != 0;
220 }
221 
222 bool
get(const char * name,Uint32 * value) const223 Properties::get(const char * name, Uint32 * value) const {
224   PropertyImpl * nvp = impl->get(name);
225   if(nvp == 0){
226     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
227     return false;
228   }
229 
230   if(nvp->valueType == PropertiesType_Uint32){
231     * value = * (Uint32 *)nvp->value;
232     setErrno(E_PROPERTIES_OK);
233     return true;
234   }
235 
236   if(nvp->valueType == PropertiesType_Uint64){
237     Uint64 tmp = * (Uint64 *)nvp->value;
238     Uint64 max = 1; max <<= 32;
239     if(tmp < max){
240       * value = (Uint32)tmp;
241       setErrno(E_PROPERTIES_OK);
242       return true;
243     }
244   }
245   setErrno(E_PROPERTIES_INVALID_TYPE);
246   return false;
247 }
248 
249 bool
get(const char * name,Uint64 * value) const250 Properties::get(const char * name, Uint64 * value) const {
251   PropertyImpl * nvp = impl->get(name);
252   if(nvp == 0){
253     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
254     return false;
255   }
256 
257   if(nvp->valueType == PropertiesType_Uint32){
258     Uint32 tmp = * (Uint32 *)nvp->value;
259     * value = (Uint64)tmp;
260     setErrno(E_PROPERTIES_OK);
261     return true;
262   }
263 
264   if(nvp->valueType == PropertiesType_Uint64){
265     * value = * (Uint64 *)nvp->value;
266     setErrno(E_PROPERTIES_OK);
267     return true;
268   }
269   setErrno(E_PROPERTIES_INVALID_TYPE);
270   return false;
271 }
272 
273 bool
get(const char * name,const char ** value) const274 Properties::get(const char * name, const char ** value) const {
275   PropertyImpl * nvp = impl->get(name);
276   if(nvp == 0){
277     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
278     return false;
279   }
280 
281   if(nvp->valueType == PropertiesType_char){
282     * value = (const char *)nvp->value;
283     setErrno(E_PROPERTIES_OK);
284     return true;
285   }
286   setErrno(E_PROPERTIES_INVALID_TYPE);
287   return false;
288 }
289 
290 bool
get(const char * name,BaseString & value) const291 Properties::get(const char * name, BaseString& value) const {
292   const char *tmp = "";
293   bool ret;
294   ret = get(name, &tmp);
295   value.assign(tmp);
296   return ret;
297 }
298 
299 bool
get(const char * name,const Properties ** value) const300 Properties::get(const char * name, const Properties ** value) const {
301   PropertyImpl * nvp = impl->get(name);
302   if(nvp == 0){
303     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
304     return false;
305   }
306   if(nvp->valueType == PropertiesType_Properties){
307     * value = (const Properties *)nvp->value;
308     setErrno(E_PROPERTIES_OK);
309     return true;
310   }
311   setErrno(E_PROPERTIES_INVALID_TYPE);
312   return false;
313 }
314 
315 bool
getCopy(const char * name,char ** value) const316 Properties::getCopy(const char * name, char ** value) const {
317   PropertyImpl * nvp = impl->get(name);
318   if(nvp == 0){
319     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
320     return false;
321   }
322 
323   if(nvp->valueType == PropertiesType_char){
324     * value = f_strdup((const char *)nvp->value);
325     setErrno(E_PROPERTIES_OK);
326     return true;
327   }
328   setErrno(E_PROPERTIES_INVALID_TYPE);
329   return false;
330 }
331 
332 bool
getCopy(const char * name,Properties ** value) const333 Properties::getCopy(const char * name, Properties ** value) const {
334   PropertyImpl * nvp = impl->get(name);
335   if(nvp == 0){
336     setErrno(E_PROPERTIES_NO_SUCH_ELEMENT);
337     return false;
338   }
339 
340   if(nvp->valueType == PropertiesType_Properties){
341     * value = new Properties(* (const Properties *)nvp->value);
342     setErrno(E_PROPERTIES_OK);
343     return true;
344   }
345   setErrno(E_PROPERTIES_INVALID_TYPE);
346   return false;
347 }
348 
349 void
clear()350 Properties::clear(){
351   while(impl->items > 0)
352     impl->remove(impl->content[0]->name);
353 }
354 
355 void
remove(const char * name)356 Properties::remove(const char * name) {
357   impl->remove(name);
358 }
359 
360 void
print(FILE * out,const char * prefix) const361 Properties::print(FILE * out, const char * prefix) const{
362   char buf[1024];
363   if(prefix == 0)
364     buf[0] = 0;
365   else
366     strncpy(buf, prefix, 1024);
367 
368   for(unsigned int i = 0; i<impl->items; i++){
369     switch(impl->content[i]->valueType){
370     case PropertiesType_Uint32:
371       fprintf(out, "%s%s = (Uint32) %d\n", buf, impl->content[i]->name,
372 	      *(Uint32 *)impl->content[i]->value);
373       break;
374     case PropertiesType_Uint64:
375       fprintf(out, "%s%s = (Uint64) %lld\n", buf, impl->content[i]->name,
376 	      *(Uint64 *)impl->content[i]->value);
377       break;
378     case PropertiesType_char:
379       fprintf(out, "%s%s = (char*) \"%s\"\n", buf, impl->content[i]->name,
380 	      (char *)impl->content[i]->value);
381       break;
382     case PropertiesType_Properties:
383       char buf2 [1024];
384       BaseString::snprintf(buf2, sizeof(buf2), "%s%s%c",buf, impl->content[i]->name,
385 	      Properties::delimiter);
386       ((Properties *)impl->content[i]->value)->print(out, buf2);
387       break;
388     }
389   }
390 }
391 
Iterator(const Properties * prop)392 Properties::Iterator::Iterator(const Properties* prop) :
393   m_prop(prop),
394   m_iterator(0) {
395 }
396 
397 const char*
first()398 Properties::Iterator::first() {
399   m_iterator = 0;
400   return next();
401 }
402 
403 const char*
next()404 Properties::Iterator::next() {
405   if (m_iterator < m_prop->impl->items)
406     return m_prop->impl->content[m_iterator++]->name;
407   else
408     return NULL;
409 }
410 
411 Uint32
getPackedSize() const412 Properties::getPackedSize() const {
413   Uint32 sz = 0;
414 
415   sz += sizeof(version); // Version id of properties object
416   sz += 4;               // No Of Items
417   sz += 4;               // Checksum
418 
419   return sz + impl->getPackedSize(0);
420 }
421 
422 static
423 Uint32
computeChecksum(const Uint32 * buf,Uint32 words)424 computeChecksum(const Uint32 * buf, Uint32 words){
425   Uint32 sum = 0;
426   for(unsigned int i = 0; i<words; i++)
427     sum ^= htonl(buf[i]);
428 
429   return sum;
430 }
431 
432 bool
pack(Uint32 * buf) const433 Properties::pack(Uint32 * buf) const {
434   Uint32 * bufStart = buf;
435 
436   memcpy(buf, version, sizeof(version));
437 
438   // Note that version must be a multiple of 4
439   buf += (sizeof(version) / 4);
440 
441   * buf = htonl(impl->getTotalItems());
442   buf++;
443   bool res = impl->pack(buf, "", 0);
444   if(!res)
445     return res;
446 
447   * buf = htonl(computeChecksum(bufStart, Uint32(buf - bufStart)));
448 
449   return true;
450 }
451 
452 bool
unpack(const Uint32 * buf,Uint32 bufLen)453 Properties::unpack(const Uint32 * buf, Uint32 bufLen){
454   const Uint32 * bufStart = buf;
455   Uint32 bufLenOrg = bufLen;
456 
457   if(bufLen < sizeof(version)){
458     setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT);
459     return false;
460   }
461 
462   if(memcmp(buf, version, sizeof(version)) != 0){
463     setErrno(E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING);
464     return false;
465   }
466   bufLen -= sizeof(version);
467 
468   // Note that version must be a multiple of 4
469   buf += (sizeof(version) / 4);
470 
471   if(bufLen < 4){
472     setErrno(E_PROPERTIES_INVALID_BUFFER_TO_SHORT);
473     return false;
474   }
475 
476   Uint32 totalItems = ntohl(* buf);
477   buf++; bufLen -= 4;
478   bool res = impl->unpack(buf, bufLen, this, totalItems);
479   if(!res)
480     return res;
481 
482   Uint32 sum = computeChecksum(bufStart, (bufLenOrg-bufLen)/4);
483   if(sum != ntohl(bufStart[(bufLenOrg-bufLen)/4])){
484     setErrno(E_PROPERTIES_INVALID_CHECKSUM);
485     return false;
486   }
487   return true;
488 }
489 
490 /**
491  * Methods for PropertiesImpl
492  */
PropertiesImpl(Properties * p,bool case_insensitive)493 PropertiesImpl::PropertiesImpl(Properties * p, bool case_insensitive){
494   this->properties = p;
495   items = 0;
496   size  = 25;
497   content = new PropertyImpl * [size];
498   setCaseInsensitiveNames(case_insensitive);
499 }
500 
PropertiesImpl(Properties * p,const PropertiesImpl & org)501 PropertiesImpl::PropertiesImpl(Properties * p, const PropertiesImpl & org){
502   this->properties = p;
503   this->size  = org.size;
504   this->items = org.items;
505   this->m_insensitive = org.m_insensitive;
506   this->compare = org.compare;
507   content = new PropertyImpl * [size];
508   for(unsigned int i = 0; i<items; i++){
509     content[i] = PropertyImpl::copyPropertyImpl(* org.content[i]);
510   }
511 }
512 
~PropertiesImpl()513 PropertiesImpl::~PropertiesImpl(){
514   for(unsigned int i = 0; i<items; i++)
515     delete content[i];
516   delete [] content;
517 }
518 
519 void
setCaseInsensitiveNames(bool value)520 PropertiesImpl::setCaseInsensitiveNames(bool value){
521   m_insensitive = value;
522   if(value)
523     compare = strcasecmp;
524   else
525     compare = strcmp;
526 }
527 
528 void
grow(int sizeToAdd)529 PropertiesImpl::grow(int sizeToAdd){
530   PropertyImpl ** newContent = new PropertyImpl * [size + sizeToAdd];
531   memcpy(newContent, content, items * sizeof(PropertyImpl *));
532   delete [] content;
533   content = newContent;
534   size   += sizeToAdd;
535 }
536 
537 PropertyImpl *
get(const char * name) const538 PropertiesImpl::get(const char * name) const {
539   const PropertiesImpl * tmp = 0;
540   const char * short_name = getProps(name, &tmp);
541   if(tmp == 0){
542     return 0;
543   }
544 
545   for(unsigned int i = 0; i<tmp->items; i++) {
546     if((* compare)(tmp->content[i]->name, short_name) == 0)
547       return tmp->content[i];
548   }
549 
550   return 0;
551 }
552 
553 PropertyImpl *
put(PropertyImpl * nvp)554 PropertiesImpl::put(PropertyImpl * nvp){
555   if(items == size)
556     grow(size);
557   content[items] = nvp;
558 
559   items ++;
560 
561   if(nvp->valueType == PropertiesType_Properties){
562     ((Properties*)nvp->value)->parent = properties;
563   }
564   return nvp;
565 }
566 
567 void
remove(const char * name)568 PropertiesImpl::remove(const char * name){
569   for(unsigned int i = 0; i<items; i++){
570     if((* compare)(content[i]->name, name) == 0){
571       delete content[i];
572       memmove(&content[i], &content[i+1], (items-i-1)*sizeof(PropertyImpl *));
573       items --;
574       return;
575     }
576   }
577 }
578 
579 Uint32
getTotalItems() const580 PropertiesImpl::getTotalItems() const {
581   int ret = 0;
582   for(unsigned int i = 0; i<items; i++)
583     if(content[i]->valueType == PropertiesType_Properties){
584       ret += ((Properties*)content[i]->value)->impl->getTotalItems();
585     } else {
586       ret ++;
587     }
588   return ret;
589 }
590 
591 const char *
getProps(const char * name,const PropertiesImpl ** impl) const592 PropertiesImpl::getProps(const char * name,
593 			 const PropertiesImpl ** impl) const {
594   const char * ret = name;
595   const char * tmp = strchr(name, Properties::delimiter);
596   if(tmp == 0){
597     * impl = this;
598     return ret;
599   } else {
600     Uint32 sz = Uint32(tmp - name);
601     char * tmp2 = (char*)malloc(sz + 1);
602     memcpy(tmp2, name, sz);
603     tmp2[sz] = 0;
604 
605     PropertyImpl * nvp = get(tmp2);
606 
607     free(tmp2);
608 
609     if(nvp == 0){
610       * impl = 0;
611       return 0;
612     }
613     if(nvp->valueType != PropertiesType_Properties){
614       * impl = 0;
615       return name;
616     }
617     return ((Properties*)nvp->value)->impl->getProps(tmp+1, impl);
618   }
619 }
620 
621 const char *
getPropsPut(const char * name,PropertiesImpl ** impl)622 PropertiesImpl::getPropsPut(const char * name,
623 			    PropertiesImpl ** impl) {
624   const char * ret = name;
625   const char * tmp = strchr(name, Properties::delimiter);
626   if(tmp == 0){
627     * impl = this;
628     return ret;
629   } else {
630     Uint32 sz = Uint32(tmp - name);
631     char * tmp2 = (char*)malloc(sz + 1);
632     memcpy(tmp2, name, sz);
633     tmp2[sz] = 0;
634 
635     PropertyImpl * nvp = get(tmp2);
636 
637     if(nvp == 0){
638       Properties   * tmpP  = new Properties();
639       PropertyImpl * tmpPI = new PropertyImpl(tmp2, tmpP);
640       PropertyImpl * nvp2 = put(tmpPI);
641 
642       delete tmpP;
643       free(tmp2);
644       return ((Properties*)nvp2->value)->impl->getPropsPut(tmp+1, impl);
645     }
646     free(tmp2);
647     if(nvp->valueType != PropertiesType_Properties){
648       * impl = 0;
649       return name;
650     }
651     return ((Properties*)nvp->value)->impl->getPropsPut(tmp+1, impl);
652   }
653 }
654 
655 int
mod4(unsigned int i)656 mod4(unsigned int i){
657   int res = i + (4 - (i % 4));
658   return res;
659 }
660 
661 Uint32
getPackedSize(Uint32 pLen) const662 PropertiesImpl::getPackedSize(Uint32 pLen) const {
663   Uint32 sz = 0;
664   for(unsigned int i = 0; i<items; i++){
665     if(content[i]->valueType == PropertiesType_Properties){
666       Properties * p = (Properties*)content[i]->value;
667       sz += p->impl->getPackedSize(pLen+(Uint32)strlen(content[i]->name)+1);
668     } else {
669       sz += 4; // Type
670       sz += 4; // Name Len
671       sz += 4; // Value Len
672       sz += mod4(pLen + strlen(content[i]->name)); // Name
673       switch(content[i]->valueType){
674       case PropertiesType_char:
675 	sz += mod4(strlen((char *)content[i]->value));
676 	break;
677       case PropertiesType_Uint32:
678 	sz += mod4(4);
679 	break;
680       case PropertiesType_Uint64:
681 	sz += mod4(8);
682 	break;
683       case PropertiesType_Properties:
684       default:
685 	assert(0);
686       }
687     }
688   }
689   return sz;
690 }
691 
692 struct CharBuf {
693   char * buffer;
694   Uint32 bufLen;
695   Uint32 contentLen;
696 
CharBufCharBuf697   CharBuf(){
698     buffer     = 0;
699     bufLen     = 0;
700     contentLen = 0;
701   }
702 
~CharBufCharBuf703   ~CharBuf(){
704     free(buffer);
705   }
706 
clearCharBuf707   void clear() { contentLen = 0;}
addCharBuf708   bool add(const char * str, Uint32 strLen){
709     if(!expand(contentLen + strLen + 1))
710       return false;
711     memcpy(&buffer[contentLen], str, strLen);
712     contentLen += strLen;
713     buffer[contentLen] = 0;
714     return true;
715   }
716 
addCharBuf717   bool add(char c){
718     return add(&c, 1);
719   }
720 
expandCharBuf721   bool expand(Uint32 newSize){
722     if(newSize >= bufLen){
723 
724       char * tmp = (char*)malloc(newSize + 1024);
725       memset(tmp, 0, newSize + 1024);
726       if(tmp == 0)
727 	return false;
728       if(contentLen > 0)
729 	memcpy(tmp, buffer, contentLen);
730       if(buffer != 0)
731 	free(buffer);
732       buffer = tmp;
733       bufLen = newSize + 1024;
734     }
735     return true;
736   }
737 };
738 
739 bool
pack(Uint32 * & buf,const char * prefix,Uint32 pLen) const740 PropertiesImpl::pack(Uint32 *& buf, const char * prefix, Uint32 pLen) const {
741   CharBuf charBuf;
742 
743   for(unsigned int i = 0; i<items; i++){
744     const int strLenName      = strlen(content[i]->name);
745 
746     if(content[i]->valueType == PropertiesType_Properties){
747       charBuf.clear();
748       if(!charBuf.add(prefix, pLen)){
749 	properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
750 			     errno);
751 	return false;
752       }
753 
754       if(!charBuf.add(content[i]->name, strLenName)){
755 	properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
756 			     errno);
757 	return false;
758       }
759 
760       if(!charBuf.add(Properties::delimiter)){
761 	properties->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING,
762 			     errno);
763 	return false;
764       }
765 
766       if(!((Properties*)(content[i]->value))->impl->pack(buf,
767 							 charBuf.buffer,
768 							 charBuf.contentLen)){
769 
770 	return false;
771       }
772       continue;
773     }
774 
775     Uint32 valLenData  = 0;
776     Uint32 valLenWrite = 0;
777     Uint32 sz = 4 + 4 + 4 + mod4(pLen + strLenName);
778     switch(content[i]->valueType){
779     case PropertiesType_Uint32:
780       valLenData  = 4;
781       break;
782     case PropertiesType_Uint64:
783       valLenData  = 8;
784       break;
785     case PropertiesType_char:
786       valLenData  = Uint32(strlen((char *)content[i]->value));
787       break;
788     case PropertiesType_Properties:
789       assert(0);
790     }
791     valLenWrite = mod4(valLenData);
792     sz += valLenWrite;
793 
794     * (buf + 0) = htonl(content[i]->valueType);
795     * (buf + 1) = htonl(pLen + strLenName);
796     * (buf + 2) = htonl(valLenData);
797 
798     char * valBuf  = (char*)(buf + 3);
799     char * nameBuf = (char*)(buf + 3 + (valLenWrite / 4));
800 
801     memset(valBuf, 0, sz-12);
802 
803     switch(content[i]->valueType){
804     case PropertiesType_Uint32:
805       * (Uint32 *)valBuf = htonl(* (Uint32 *)content[i]->value);
806       break;
807     case PropertiesType_Uint64:{
808       Uint64 val =  * (Uint64 *)content[i]->value;
809       Uint32 hi = (Uint32)(val >> 32);
810       Uint32 lo = (Uint32)(val & 0xFFFFFFFF);
811       * (Uint32 *)valBuf = htonl(hi);
812       * (Uint32 *)(valBuf + 4) = htonl(lo);
813     }
814       break;
815     case PropertiesType_char:
816       memcpy(valBuf, content[i]->value, strlen((char*)content[i]->value));
817       break;
818     case PropertiesType_Properties:
819       assert(0);
820     }
821     if(pLen > 0)
822       memcpy(nameBuf, prefix, pLen);
823     memcpy(nameBuf + pLen, content[i]->name, strLenName);
824 
825     buf += (sz / 4);
826   }
827 
828   return true;
829 }
830 
831 bool
unpack(const Uint32 * buf,Uint32 & bufLen,Properties * top,int _items)832 PropertiesImpl::unpack(const Uint32 * buf, Uint32 &bufLen, Properties * top,
833 		       int _items){
834   CharBuf charBuf;
835   while(_items > 0){
836     Uint32 tmp[3];
837 
838     if(bufLen <= 12){
839       top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING);
840       return false;
841     }
842 
843     tmp[0] = ntohl(buf[0]);
844     tmp[1] = ntohl(buf[1]);
845     tmp[2] = ntohl(buf[2]);
846     buf    += 3;
847     bufLen -= 12;
848 
849     PropertiesType pt   = (PropertiesType)tmp[0];
850     Uint32 nameLen      = tmp[1];
851     Uint32 valueLen     = tmp[2];
852     Uint32 nameLenRead  = mod4(nameLen);
853     Uint32 valueLenRead = mod4(valueLen);
854 
855     Uint32 sz = nameLenRead + valueLenRead;
856     if(bufLen < sz){
857       top->setErrno(E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING);
858       return false;
859     }
860 
861     if(!charBuf.expand(sz)){
862       top->setErrno(E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING, errno);
863       return false;
864     }
865 
866     memcpy(charBuf.buffer, buf, sz);
867     buf    += (sz / 4);
868     bufLen -= sz ;
869 
870     char * valBuf  = charBuf.buffer;
871     char * nameBuf = charBuf.buffer + valueLenRead;
872 
873     nameBuf[nameLen] = 0;
874     valBuf[valueLen] = 0;
875 
876     bool res3 = false;
877     switch(pt){
878     case PropertiesType_Uint32:
879       res3 = top->put(nameBuf, ntohl(* (Uint32 *)valBuf), true);
880       break;
881     case PropertiesType_Uint64:{
882       Uint64 hi = ntohl(* (Uint32 *)valBuf);
883       Uint64 lo = ntohl(* (Uint32 *)(valBuf + 4));
884       res3 = top->put64(nameBuf, (hi << 32) + lo, true);
885     }
886       break;
887     case PropertiesType_char:
888       res3 = top->put(nameBuf, valBuf, true);
889       break;
890     case PropertiesType_Properties:
891       assert(0);
892     }
893     if(!res3){
894       return false;
895     }
896     _items--;
897   }
898   return true;
899 }
900 
~PropertyImpl()901 PropertyImpl::~PropertyImpl(){
902   free((char*)name);
903   switch(valueType){
904   case PropertiesType_Uint32:
905     delete (Uint32 *)value;
906     break;
907   case PropertiesType_Uint64:
908     delete (Uint64 *)value;
909     break;
910   case PropertiesType_char:
911     free((char *)value);
912     break;
913   case PropertiesType_Properties:
914     delete (Properties *)value;
915     break;
916   }
917 }
918 
919 PropertyImpl *
copyPropertyImpl(const PropertyImpl & org)920 PropertyImpl::copyPropertyImpl(const PropertyImpl & org){
921   switch(org.valueType){
922   case PropertiesType_Uint32:
923     return new PropertyImpl(org.name, * (Uint32 *)org.value);
924   case PropertiesType_Uint64:
925     return new PropertyImpl(org.name, * (Uint64 *)org.value);
926     break;
927   case PropertiesType_char:
928     return new PropertyImpl(org.name, (char *)org.value);
929     break;
930   case PropertiesType_Properties:
931     return new PropertyImpl(org.name, (Properties *)org.value);
932     break;
933   default:
934     assert(0);
935   }
936   return 0;
937 }
938 
PropertyImpl(const char * _name,Uint32 _value)939 PropertyImpl::PropertyImpl(const char * _name, Uint32 _value){
940   this->name = f_strdup(_name);
941   this->value = new Uint32;
942   * ((Uint32 *)this->value) = _value;
943   this->valueType = PropertiesType_Uint32;
944 }
945 
PropertyImpl(const char * _name,Uint64 _value)946 PropertyImpl::PropertyImpl(const char * _name, Uint64 _value){
947   this->name = f_strdup(_name);
948   this->value = new Uint64;
949   * ((Uint64 *)this->value) = _value;
950   this->valueType = PropertiesType_Uint64;
951 }
952 
PropertyImpl(const char * _name,const char * _value)953 PropertyImpl::PropertyImpl(const char * _name, const char * _value){
954   this->name = f_strdup(_name);
955   this->value = f_strdup(_value);
956   this->valueType = PropertiesType_char;
957 
958 }
959 
PropertyImpl(const char * _name,const Properties * _value)960 PropertyImpl::PropertyImpl(const char * _name, const Properties * _value){
961   this->name = f_strdup(_name);
962   this->value = new Properties(* _value);
963   this->valueType = PropertiesType_Properties;
964 }
965 
966 const Uint32 E_PROPERTIES_OK                                      = 0;
967 const Uint32 E_PROPERTIES_INVALID_NAME                            = 1;
968 const Uint32 E_PROPERTIES_NO_SUCH_ELEMENT                         = 2;
969 const Uint32 E_PROPERTIES_INVALID_TYPE                            = 3;
970 const Uint32 E_PROPERTIES_ELEMENT_ALREADY_EXISTS                  = 4;
971 
972 const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING              = 5;
973 const Uint32 E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING         = 6;
974 const Uint32 E_PROPERTIES_INVALID_BUFFER_TO_SHORT                 = 7;
975 const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING            = 8;
976 const Uint32 E_PROPERTIES_INVALID_CHECKSUM                        = 9;
977 const Uint32 E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING         = 10;
978 
979 /**
980  * These are methods that used to be inline
981  *
982  * But Diab 4.1f could not compile -release with to many inlines
983  */
984 void
setErrno(Uint32 pErr,Uint32 osErr) const985 Properties::setErrno(Uint32 pErr, Uint32 osErr) const {
986   if(parent != 0){
987     parent->setErrno(pErr, osErr);
988     return ;
989   }
990 
991   /**
992    * propErrno & osErrno used to be mutable,
993    * but diab didn't know what mutable meant.
994    */
995   *((Uint32*)&propErrno) = pErr;
996   *((Uint32*)&osErrno)   = osErr;
997 }
998 
999 /**
1000  * Inlined get/put(name, no, ...) - methods
1001  */
1002 
1003 bool
put(const char * name,Uint32 no,Uint32 val,bool replace)1004 Properties::put(const char * name, Uint32 no, Uint32 val, bool replace){
1005   size_t tmp_len = strlen(name)+20;
1006   char * tmp = (char*)malloc(tmp_len);
1007   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1008   bool res = put(tmp, val, replace);
1009   free(tmp);
1010   return res;
1011 }
1012 
1013 bool
put64(const char * name,Uint32 no,Uint64 val,bool replace)1014 Properties::put64(const char * name, Uint32 no, Uint64 val, bool replace){
1015   size_t tmp_len = strlen(name)+20;
1016   char * tmp = (char*)malloc(tmp_len);
1017   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1018   bool res = put64(tmp, val, replace);
1019   free(tmp);
1020   return res;
1021 }
1022 
1023 
1024 bool
put(const char * name,Uint32 no,const char * val,bool replace)1025 Properties::put(const char * name, Uint32 no, const char * val, bool replace){
1026   size_t tmp_len = strlen(name)+20;
1027   char * tmp = (char*)malloc(tmp_len);
1028   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1029   bool res = put(tmp, val, replace);
1030   free(tmp);
1031   return res;
1032 }
1033 
1034 
1035 bool
put(const char * name,Uint32 no,const Properties * val,bool replace)1036 Properties::put(const char * name, Uint32 no, const Properties * val,
1037 		bool replace){
1038   size_t tmp_len = strlen(name)+20;
1039   char * tmp = (char*)malloc(tmp_len);
1040   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1041   bool res = put(tmp, val, replace);
1042   free(tmp);
1043   return res;
1044 }
1045 
1046 
1047 bool
getTypeOf(const char * name,Uint32 no,PropertiesType * type) const1048 Properties::getTypeOf(const char * name, Uint32 no,
1049 		      PropertiesType * type) const {
1050   size_t tmp_len = strlen(name)+20;
1051   char * tmp = (char*)malloc(tmp_len);
1052   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1053   bool res = getTypeOf(tmp, type);
1054   free(tmp);
1055   return res;
1056 }
1057 
1058 bool
contains(const char * name,Uint32 no) const1059 Properties::contains(const char * name, Uint32 no) const {
1060   size_t tmp_len = strlen(name)+20;
1061   char * tmp = (char*)malloc(tmp_len);
1062   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1063   bool res = contains(tmp);
1064   free(tmp);
1065   return res;
1066 }
1067 
1068 bool
get(const char * name,Uint32 no,Uint32 * value) const1069 Properties::get(const char * name, Uint32 no, Uint32 * value) const{
1070   size_t tmp_len = strlen(name)+20;
1071   char * tmp = (char*)malloc(tmp_len);
1072   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1073   bool res = get(tmp, value);
1074   free(tmp);
1075   return res;
1076 }
1077 
1078 bool
get(const char * name,Uint32 no,Uint64 * value) const1079 Properties::get(const char * name, Uint32 no, Uint64 * value) const{
1080   size_t tmp_len = strlen(name)+20;
1081   char * tmp = (char*)malloc(tmp_len);
1082   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1083   bool res = get(tmp, value);
1084   free(tmp);
1085   return res;
1086 }
1087 
1088 
1089 bool
get(const char * name,Uint32 no,const char ** value) const1090 Properties::get(const char * name, Uint32 no, const char ** value) const {
1091   size_t tmp_len = strlen(name)+20;
1092   char * tmp = (char*)malloc(tmp_len);
1093   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1094   bool res = get(tmp, value);
1095   free(tmp);
1096   return res;
1097 }
1098 
1099 
1100 bool
get(const char * name,Uint32 no,const Properties ** value) const1101 Properties::get(const char * name, Uint32 no, const Properties ** value) const{
1102   size_t tmp_len = strlen(name)+20;
1103   char * tmp = (char*)malloc(tmp_len);
1104   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1105   bool res = get(tmp, value);
1106   free(tmp);
1107   return res;
1108 }
1109 
1110 
1111 bool
getCopy(const char * name,Uint32 no,char ** value) const1112 Properties::getCopy(const char * name, Uint32 no, char ** value) const {
1113   size_t tmp_len = strlen(name)+20;
1114   char * tmp = (char*)malloc(tmp_len);
1115   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1116   bool res = getCopy(tmp, value);
1117   free(tmp);
1118   return res;
1119 }
1120 
1121 
1122 bool
getCopy(const char * name,Uint32 no,Properties ** value) const1123 Properties::getCopy(const char * name, Uint32 no, Properties ** value) const {
1124   size_t tmp_len = strlen(name)+20;
1125   char * tmp = (char*)malloc(tmp_len);
1126   BaseString::snprintf(tmp, tmp_len, "%s_%d", name, no);
1127   bool res = getCopy(tmp, value);
1128   free(tmp);
1129   return res;
1130 }
1131 
1132 void
setCaseInsensitiveNames(bool value)1133 Properties::setCaseInsensitiveNames(bool value){
1134   impl->setCaseInsensitiveNames(value);
1135 }
1136 
1137 bool
getCaseInsensitiveNames() const1138 Properties::getCaseInsensitiveNames() const {
1139   return impl->m_insensitive;
1140 }
1141 
1142 template bool put(PropertiesImpl *, const char *, Uint32, bool);
1143 template bool put(PropertiesImpl *, const char *, Uint64, bool);
1144 template bool put(PropertiesImpl *, const char *, const char *, bool);
1145 template bool put(PropertiesImpl *, const char *, const Properties*, bool);
1146