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