~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/src/common/util/Properties.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

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