00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "dcPackerCatalog.h"
00016 #include "dcPackerInterface.h"
00017 #include "dcPacker.h"
00018 #include "dcSwitchParameter.h"
00019
00020
00021
00022
00023
00024
00025
00026 DCPackerCatalog::
00027 DCPackerCatalog(const DCPackerInterface *root) : _root(root) {
00028 _live_catalog = NULL;
00029 }
00030
00031
00032
00033
00034
00035
00036
00037 DCPackerCatalog::
00038 DCPackerCatalog(const DCPackerCatalog ©) :
00039 _root(copy._root),
00040 _entries(copy._entries),
00041 _entries_by_name(copy._entries_by_name),
00042 _entries_by_field(copy._entries_by_field)
00043 {
00044 _live_catalog = NULL;
00045 }
00046
00047
00048
00049
00050
00051
00052
00053 DCPackerCatalog::
00054 ~DCPackerCatalog() {
00055 if (_live_catalog != (LiveCatalog *)NULL) {
00056 delete _live_catalog;
00057 }
00058
00059 SwitchCatalogs::iterator si;
00060 for (si = _switch_catalogs.begin(); si != _switch_catalogs.end(); ++si) {
00061 delete (*si).second;
00062 }
00063 }
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 int DCPackerCatalog::
00074 find_entry_by_name(const string &name) const {
00075 EntriesByName::const_iterator ni;
00076 ni = _entries_by_name.find(name);
00077 if (ni != _entries_by_name.end()) {
00078 return (*ni).second;
00079 }
00080 return -1;
00081 }
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 int DCPackerCatalog::
00092 find_entry_by_field(const DCPackerInterface *field) const {
00093 EntriesByField::const_iterator ni;
00094 ni = _entries_by_field.find(field);
00095 if (ni != _entries_by_field.end()) {
00096 return (*ni).second;
00097 }
00098 return -1;
00099 }
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 const DCPackerCatalog::LiveCatalog *DCPackerCatalog::
00114 get_live_catalog(const char *data, size_t length) const {
00115 if (_live_catalog != (LiveCatalog *)NULL) {
00116
00117
00118 return _live_catalog;
00119 }
00120
00121 LiveCatalog *live_catalog = new LiveCatalog;
00122 live_catalog->_catalog = this;
00123 live_catalog->_live_entries.reserve(_entries.size());
00124 LiveCatalogEntry zero_entry;
00125 zero_entry._begin = 0;
00126 zero_entry._end = 0;
00127 for (size_t i = 0; i < _entries.size(); i++) {
00128 live_catalog->_live_entries.push_back(zero_entry);
00129 }
00130
00131 DCPacker packer;
00132 packer.set_unpack_data(data, length, false);
00133 packer.begin_unpack(_root);
00134 const DCSwitchParameter *last_switch = NULL;
00135 r_fill_live_catalog(live_catalog, packer, last_switch);
00136 bool okflag = packer.end_unpack();
00137
00138 if (!okflag) {
00139 delete live_catalog;
00140 return NULL;
00141 }
00142
00143 if (_root->has_fixed_structure()) {
00144
00145
00146
00147 ((DCPackerCatalog *)this)->_live_catalog = live_catalog;
00148 }
00149
00150 return live_catalog;
00151 }
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165 void DCPackerCatalog::
00166 release_live_catalog(const DCPackerCatalog::LiveCatalog *live_catalog) const {
00167 if (live_catalog != _live_catalog) {
00168 delete (LiveCatalog *)live_catalog;
00169 }
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 void DCPackerCatalog::
00179 add_entry(const string &name, const DCPackerInterface *field,
00180 const DCPackerInterface *parent, int field_index) {
00181 Entry entry;
00182 entry._name = name;
00183 entry._field = field;
00184 entry._parent = parent;
00185 entry._field_index = field_index;
00186
00187 int entry_index = (int)_entries.size();
00188 _entries.push_back(entry);
00189 _entries_by_field.insert(EntriesByField::value_type(field, entry_index));
00190
00191
00192
00193
00194
00195
00196 _entries_by_name[name] = entry_index;
00197
00198
00199
00200
00201
00202 string local_name = field->get_name();
00203 if (local_name != name) {
00204 _entries_by_name.insert(EntriesByName::value_type(local_name, entry_index));
00205 }
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 void DCPackerCatalog::
00217 r_fill_catalog(const string &name_prefix, const DCPackerInterface *field,
00218 const DCPackerInterface *parent, int field_index) {
00219 string next_name_prefix = name_prefix;
00220
00221 if (parent != (const DCPackerInterface *)NULL && !field->get_name().empty()) {
00222
00223 next_name_prefix += field->get_name();
00224 add_entry(next_name_prefix, field, parent, field_index);
00225
00226 next_name_prefix += ".";
00227 }
00228
00229 const DCSwitchParameter *switch_parameter = field->as_switch_parameter();
00230 if (switch_parameter != (DCSwitchParameter *)NULL) {
00231
00232
00233
00234
00235
00236 _switch_prefixes[switch_parameter] = next_name_prefix;
00237 }
00238
00239
00240 if (field->has_nested_fields()) {
00241 int num_nested = field->get_num_nested_fields();
00242
00243 for (int i = 0; i < num_nested; i++) {
00244 DCPackerInterface *nested = field->get_nested_field(i);
00245 if (nested != (DCPackerInterface *)NULL) {
00246 r_fill_catalog(next_name_prefix, nested, field, i);
00247 }
00248 }
00249 }
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259 void DCPackerCatalog::
00260 r_fill_live_catalog(LiveCatalog *live_catalog, DCPacker &packer,
00261 const DCSwitchParameter *&last_switch) const {
00262 const DCPackerInterface *current_field = packer.get_current_field();
00263
00264 int field_index = live_catalog->find_entry_by_field(current_field);
00265 if (field_index >= 0) {
00266 nassertv(field_index < (int)live_catalog->_live_entries.size());
00267 live_catalog->_live_entries[field_index]._begin = packer.get_num_unpacked_bytes();
00268 }
00269
00270 if (packer.has_nested_fields() &&
00271 (packer.get_pack_type() != PT_string && packer.get_pack_type() != PT_blob)) {
00272 packer.push();
00273 while (packer.more_nested_fields()) {
00274 r_fill_live_catalog(live_catalog, packer, last_switch);
00275 }
00276 packer.pop();
00277
00278 } else {
00279 packer.unpack_skip();
00280 }
00281
00282 if (field_index >= 0) {
00283 live_catalog->_live_entries[field_index]._end = packer.get_num_unpacked_bytes();
00284 }
00285
00286 if (last_switch != packer.get_last_switch()) {
00287
00288
00289 last_switch = packer.get_last_switch();
00290
00291 const DCPackerInterface *switch_case = packer.get_current_parent();
00292 nassertv(switch_case != (DCPackerInterface *)NULL);
00293 const DCPackerCatalog *switch_catalog =
00294 live_catalog->_catalog->update_switch_fields(last_switch, switch_case);
00295 nassertv(switch_catalog != (DCPackerCatalog *)NULL);
00296 live_catalog->_catalog = switch_catalog;
00297
00298
00299
00300 LiveCatalogEntry zero_entry;
00301 zero_entry._begin = 0;
00302 zero_entry._end = 0;
00303 for (size_t i = live_catalog->_live_entries.size();
00304 i < switch_catalog->_entries.size();
00305 i++) {
00306 live_catalog->_live_entries.push_back(zero_entry);
00307 }
00308 }
00309 }
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 const DCPackerCatalog *DCPackerCatalog::
00330 update_switch_fields(const DCSwitchParameter *switch_parameter,
00331 const DCPackerInterface *switch_case) const {
00332 SwitchCatalogs::const_iterator si = _switch_catalogs.find(switch_case);
00333 if (si != _switch_catalogs.end()) {
00334 return (*si).second;
00335 }
00336
00337
00338
00339
00340
00341 SwitchPrefixes::const_iterator pi = _switch_prefixes.find(switch_parameter);
00342 if (pi == _switch_prefixes.end()) {
00343
00344
00345
00346 return this;
00347 }
00348
00349 string name_prefix = (*pi).second;
00350
00351
00352
00353 DCPackerCatalog *switch_catalog = new DCPackerCatalog(*this);
00354
00355
00356
00357
00358
00359 int num_nested = switch_case->get_num_nested_fields();
00360 for (int i = 1; i < num_nested; i++) {
00361 DCPackerInterface *nested = switch_case->get_nested_field(i);
00362 if (nested != (DCPackerInterface *)NULL) {
00363 switch_catalog->r_fill_catalog(name_prefix, nested, switch_case, i);
00364 }
00365 }
00366
00367
00368
00369 ((DCPackerCatalog *)this)->_switch_catalogs[switch_case] = switch_catalog;
00370
00371 return switch_catalog;
00372 }