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