1// field.cpp -- 2// $Id: field.cpp 1230 2007-03-09 15:58:53Z jcw $ 3// This is part of Metakit, the homepage is http://www.equi4.com/metakit.html 4 5/** @file 6 * Implementation of the field structure tree 7 */ 8 9#include "header.h" 10#include "field.h" 11 12#include <stdlib.h> // strtol 13 14#if !q4_INLINE 15#include "field.inl" 16#endif 17 18///////////////////////////////////////////////////////////////////////////// 19// Implemented in this file 20 21class c4_Field; 22 23///////////////////////////////////////////////////////////////////////////// 24// c4_Field 25 26c4_Field::c4_Field(const char * &description_, c4_Field *parent_): _type(0) { 27 _indirect = this; 28 29 size_t n = strcspn(description_, ",[]"); 30 const char *p = strchr(description_, ':'); 31 32 if (p != 0 && p < description_ + n) { 33 _name = c4_String(description_, p - description_); 34 _type = p[1] &~0x20; // force to upper case 35 } else { 36 _name = c4_String(description_, n); 37 _type = 'S'; 38 } 39 40 description_ += n; 41 42 if (*description_ == '[') { 43 ++description_; 44 _type = 'V'; 45 46 if (*description_ == '^') { 47 ++description_; 48 _indirect = parent_; 49 d4_assert(*description_ == ']'); 50 } 51 52 if (*description_ == ']') 53 ++description_; 54 else 55 do { 56 // 2004-01-20 ignore duplicate property names 57 // (since there is no good way to report errors at this point) 58 c4_Field *sf = d4_new c4_Field(description_, this); 59 for (int i = 0; i < NumSubFields(); ++i) 60 if (SubField(i).Name().CompareNoCase(sf->Name()) == 0) { 61 delete sf; 62 sf = 0; 63 break; 64 } 65 if (sf != 0) 66 _subFields.Add(sf); 67 } while (*description_++ == ','); 68 } 69} 70 71c4_Field::~c4_Field() { 72 if (_indirect == this) { 73 //better? for (int i = NumSubFields(); --i >= 0 ;) 74 for (int i = 0; i < NumSubFields(); ++i) { 75 c4_Field *sf = &SubField(i); 76 if (sf != this) 77 // careful with recursive subfields 78 delete sf; 79 } 80 } 81} 82 83c4_String c4_Field::Description(bool anonymous_)const { 84 c4_String s = anonymous_ ? "?" : (const char*)Name(); 85 86 if (Type() == 'V') 87 s += "[" + DescribeSubFields(anonymous_) + "]"; 88 else { 89 s += ":"; 90 s += (c4_String)Type(); 91 } 92 93 return s; 94} 95 96c4_String c4_Field::DescribeSubFields(bool)const { 97 d4_assert(Type() == 'V'); 98 99 if (_indirect != this) 100 return "^"; 101 102 c4_String s; 103 char c = 0; 104 105 for (int i = 0; i < NumSubFields(); ++i) { 106 if (c != 0) 107 s += (c4_String)c; 108 s += SubField(i).Description(); 109 c = ','; 110 } 111 112 return s; 113} 114 115///////////////////////////////////////////////////////////////////////////// 116