| [0b990d] | 1 | //
 | 
|---|
 | 2 | // stateout.cc
 | 
|---|
 | 3 | //
 | 
|---|
 | 4 | // Copyright (C) 1998 Limit Point Systems, Inc.
 | 
|---|
 | 5 | //
 | 
|---|
 | 6 | // Author: Curtis Janssen <cljanss@limitpt.com>
 | 
|---|
 | 7 | // Maintainer: LPS
 | 
|---|
 | 8 | //
 | 
|---|
 | 9 | // This file is part of the SC Toolkit.
 | 
|---|
 | 10 | //
 | 
|---|
 | 11 | // The SC Toolkit is free software; you can redistribute it and/or modify
 | 
|---|
 | 12 | // it under the terms of the GNU Library General Public License as published by
 | 
|---|
 | 13 | // the Free Software Foundation; either version 2, or (at your option)
 | 
|---|
 | 14 | // any later version.
 | 
|---|
 | 15 | //
 | 
|---|
 | 16 | // The SC Toolkit 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 Library General Public License for more details.
 | 
|---|
 | 20 | //
 | 
|---|
 | 21 | // You should have received a copy of the GNU Library General Public License
 | 
|---|
 | 22 | // along with the SC Toolkit; see the file COPYING.LIB.  If not, write to
 | 
|---|
 | 23 | // the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 | 
|---|
 | 24 | //
 | 
|---|
 | 25 | // The U.S. Government is granted a limited license as per AL 91-7.
 | 
|---|
 | 26 | //
 | 
|---|
 | 27 | 
 | 
|---|
 | 28 | #ifdef __GNUC__
 | 
|---|
 | 29 | #pragma implementation
 | 
|---|
 | 30 | #endif
 | 
|---|
 | 31 | 
 | 
|---|
 | 32 | #include <limits.h>
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | #include <scconfig.h>
 | 
|---|
 | 35 | 
 | 
|---|
 | 36 | #include <unistd.h>
 | 
|---|
 | 37 | #include <string.h>
 | 
|---|
 | 38 | #ifdef HAVE_SYS_TIME_H
 | 
|---|
 | 39 | #include <sys/time.h>
 | 
|---|
 | 40 | #endif
 | 
|---|
 | 41 | #ifdef HAVE_PWD_H
 | 
|---|
 | 42 | #include <pwd.h>
 | 
|---|
 | 43 | #endif
 | 
|---|
 | 44 | #ifdef HAVE_SYS_TYPES_H
 | 
|---|
 | 45 | #include <sys/types.h>
 | 
|---|
 | 46 | #endif
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | #include <util/class/scexception.h>
 | 
|---|
 | 49 | #include <util/state/translate.h>
 | 
|---|
 | 50 | #include <util/state/stateout.h>
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | using namespace std;
 | 
|---|
 | 53 | using namespace sc;
 | 
|---|
 | 54 | 
 | 
|---|
 | 55 | static ClassDesc StateOut_cd(
 | 
|---|
 | 56 |     typeid(StateOut),"StateOut",1,"public DescribedClass");
 | 
|---|
 | 57 | 
 | 
|---|
 | 58 | StateOut::StateOut() :
 | 
|---|
 | 59 |   have_cd_(0),
 | 
|---|
 | 60 |   translate_(new TranslateDataOut(this, new TranslateDataBigEndian)),
 | 
|---|
 | 61 |   copy_references_(0),
 | 
|---|
 | 62 |   next_object_number_(1),
 | 
|---|
 | 63 |   nextclassid_(0),
 | 
|---|
 | 64 |   node_to_node_(0)
 | 
|---|
 | 65 | {
 | 
|---|
 | 66 | }
 | 
|---|
 | 67 | 
 | 
|---|
 | 68 | StateOut::StateOut(const StateOut&)
 | 
|---|
 | 69 | {
 | 
|---|
 | 70 |   ExEnv::errn() << "StateOut: private copy ctor called???" << endl;
 | 
|---|
 | 71 |   abort();
 | 
|---|
 | 72 | }
 | 
|---|
 | 73 | 
 | 
|---|
 | 74 | void
 | 
|---|
 | 75 | StateOut::operator=(const StateOut&)
 | 
|---|
 | 76 | {
 | 
|---|
 | 77 |   ExEnv::errn() << "StateOut: private assignment called???" << endl;
 | 
|---|
 | 78 |   abort();
 | 
|---|
 | 79 | }
 | 
|---|
 | 80 | 
 | 
|---|
 | 81 | StateOut::~StateOut()
 | 
|---|
 | 82 | {
 | 
|---|
 | 83 |   delete translate_;
 | 
|---|
 | 84 | }
 | 
|---|
 | 85 | 
 | 
|---|
 | 86 | void
 | 
|---|
 | 87 | StateOut::flush()
 | 
|---|
 | 88 | {
 | 
|---|
 | 89 | }
 | 
|---|
 | 90 | 
 | 
|---|
 | 91 | int
 | 
|---|
 | 92 | StateOut::tell()
 | 
|---|
 | 93 | {
 | 
|---|
 | 94 |   return 0;
 | 
|---|
 | 95 | }
 | 
|---|
 | 96 | 
 | 
|---|
 | 97 | void
 | 
|---|
 | 98 | StateOut::seek(int loc)
 | 
|---|
 | 99 | {
 | 
|---|
 | 100 | }
 | 
|---|
 | 101 | 
 | 
|---|
 | 102 | int
 | 
|---|
 | 103 | StateOut::seekable()
 | 
|---|
 | 104 | {
 | 
|---|
 | 105 |   return 0;
 | 
|---|
 | 106 | }
 | 
|---|
 | 107 | 
 | 
|---|
 | 108 | int
 | 
|---|
 | 109 | StateOut::use_directory()
 | 
|---|
 | 110 | {
 | 
|---|
 | 111 |   return 0;
 | 
|---|
 | 112 | }
 | 
|---|
 | 113 | 
 | 
|---|
 | 114 | int
 | 
|---|
 | 115 | StateOut::put_array_char(const char*p,int size)
 | 
|---|
 | 116 | {
 | 
|---|
 | 117 |   return translate_->put(p,size);
 | 
|---|
 | 118 | }
 | 
|---|
 | 119 | 
 | 
|---|
 | 120 | int
 | 
|---|
 | 121 | StateOut::put_array_uint(const unsigned int*p,int size)
 | 
|---|
 | 122 | {
 | 
|---|
 | 123 |   return translate_->put(p,size);
 | 
|---|
 | 124 | }
 | 
|---|
 | 125 | 
 | 
|---|
 | 126 | int
 | 
|---|
 | 127 | StateOut::put_array_int(const int*p,int size)
 | 
|---|
 | 128 | {
 | 
|---|
 | 129 |   return translate_->put(p,size);
 | 
|---|
 | 130 | }
 | 
|---|
 | 131 | 
 | 
|---|
 | 132 | int
 | 
|---|
 | 133 | StateOut::put_array_float(const float*p,int size)
 | 
|---|
 | 134 | {
 | 
|---|
 | 135 |   return translate_->put(p,size);
 | 
|---|
 | 136 | }
 | 
|---|
 | 137 | 
 | 
|---|
 | 138 | int
 | 
|---|
 | 139 | StateOut::put_array_double(const double*p,int size)
 | 
|---|
 | 140 | {
 | 
|---|
 | 141 |   return translate_->put(p,size);
 | 
|---|
 | 142 | }
 | 
|---|
 | 143 | 
 | 
|---|
 | 144 | int StateOut::put(char r) { return put_array_char(&r,1); }
 | 
|---|
 | 145 | int StateOut::put(unsigned int r) { return put_array_uint(&r,1); }
 | 
|---|
 | 146 | int StateOut::put(bool r) { return put(int(r)); }
 | 
|---|
 | 147 | int StateOut::put(int r) { return put_array_int(&r,1); }
 | 
|---|
 | 148 | int StateOut::put(float r) { return put_array_float(&r,1); }
 | 
|---|
 | 149 | int StateOut::put(double r) { return put_array_double(&r,1); }
 | 
|---|
 | 150 | int StateOut::put(unsigned long r)
 | 
|---|
 | 151 | {
 | 
|---|
 | 152 |   if (r > INT_MAX) {
 | 
|---|
 | 153 |       throw LimitExceeded<unsigned long>(
 | 
|---|
 | 154 |           "StateOut::put max allowed size exceeded",
 | 
|---|
 | 155 |           __FILE__, __LINE__, INT_MAX, r);
 | 
|---|
 | 156 |     }
 | 
|---|
 | 157 |   return put(int(r));
 | 
|---|
 | 158 | }
 | 
|---|
 | 159 | 
 | 
|---|
 | 160 | // This deletes all references to objects, so if they are output
 | 
|---|
 | 161 | // again, they will be written in their entirety.
 | 
|---|
 | 162 | void
 | 
|---|
 | 163 | StateOut::forget_references()
 | 
|---|
 | 164 | {
 | 
|---|
 | 165 |   ps_.clear();
 | 
|---|
 | 166 | }
 | 
|---|
 | 167 | 
 | 
|---|
 | 168 | // This deletes all references to objects, so if they are output
 | 
|---|
 | 169 | // again, they will be written in their entirety.  These also
 | 
|---|
 | 170 | // cause all future reference information to be ignored.  All
 | 
|---|
 | 171 | // referenced objects will be copied.
 | 
|---|
 | 172 | void
 | 
|---|
 | 173 | StateOut::copy_references()
 | 
|---|
 | 174 | {
 | 
|---|
 | 175 |   copy_references_ = 1;
 | 
|---|
 | 176 | }
 | 
|---|
 | 177 | 
 | 
|---|
 | 178 | int
 | 
|---|
 | 179 | StateOut::put_array_void(const void*p,int s)
 | 
|---|
 | 180 | {
 | 
|---|
 | 181 |   ExEnv::errn() << "StateOut::put_array_void(const void*p,int s) "
 | 
|---|
 | 182 |        << "is a derived class responsiblility" << endl
 | 
|---|
 | 183 |        << "  exact type is \"" << class_name() << "\"" << endl;
 | 
|---|
 | 184 |   abort();
 | 
|---|
 | 185 |   return -1;
 | 
|---|
 | 186 | }
 | 
|---|
 | 187 | 
 | 
|---|
 | 188 | void
 | 
|---|
 | 189 | StateOut::put_header()
 | 
|---|
 | 190 | {
 | 
|---|
 | 191 |   const char *magic = "\001SCSO\002";
 | 
|---|
 | 192 |   put_array_char(magic,6);
 | 
|---|
 | 193 | 
 | 
|---|
 | 194 |   // Switch to the native format and get_header will figure it out when read
 | 
|---|
 | 195 |   delete translate_;
 | 
|---|
 | 196 |   translate_ = new TranslateDataOut(this,new TranslateData);
 | 
|---|
 | 197 | 
 | 
|---|
 | 198 |   char format = translate_->translator()->format_code();
 | 
|---|
 | 199 |   put_array_char(&format,1);
 | 
|---|
 | 200 | 
 | 
|---|
 | 201 |   const int version = 1;
 | 
|---|
 | 202 |   put_array_int(&version,1);
 | 
|---|
 | 203 | 
 | 
|---|
 | 204 |   char userid[9];
 | 
|---|
 | 205 |   memset(userid,0,9);
 | 
|---|
 | 206 | #if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID)
 | 
|---|
 | 207 |   const char *pw_name = getpwuid(geteuid())->pw_name;
 | 
|---|
 | 208 |   if (pw_name) {
 | 
|---|
 | 209 |       strncpy(userid, pw_name, 9);
 | 
|---|
 | 210 |       userid[8] = 0;
 | 
|---|
 | 211 |     }
 | 
|---|
 | 212 | #else
 | 
|---|
 | 213 |   strcpy(userid,"UNKNOWN");
 | 
|---|
 | 214 | #endif
 | 
|---|
 | 215 |   put_array_char(userid,9);
 | 
|---|
 | 216 | 
 | 
|---|
 | 217 |   timeval tv;
 | 
|---|
 | 218 |   gettimeofday(&tv,0);
 | 
|---|
 | 219 |   int date = (int) tv.tv_sec;
 | 
|---|
 | 220 |   put_array_int(&date,1);
 | 
|---|
 | 221 | 
 | 
|---|
 | 222 |   // record the position of the directory locator
 | 
|---|
 | 223 |   dir_loc_loc_ = tell();
 | 
|---|
 | 224 | 
 | 
|---|
 | 225 |   // the directory location defaults to 0 (no directory)
 | 
|---|
 | 226 |   int dir_loc = 0;
 | 
|---|
 | 227 |   // however, if a directory is to be used make dir_loc -1 (invalid)
 | 
|---|
 | 228 |   if (use_directory()) dir_loc = -1;
 | 
|---|
 | 229 |   put_array_int(&dir_loc,1);
 | 
|---|
 | 230 | }
 | 
|---|
 | 231 | 
 | 
|---|
 | 232 | void
 | 
|---|
 | 233 | StateOut::put_directory()
 | 
|---|
 | 234 | {
 | 
|---|
 | 235 |   std::map<ClassDescP,int>::iterator iid;
 | 
|---|
 | 236 |   std::map<Ref<SavableState>,StateOutData>::iterator isd;
 | 
|---|
 | 237 | 
 | 
|---|
 | 238 |   // write the class information
 | 
|---|
 | 239 |   put(classidmap_.size());
 | 
|---|
 | 240 |   for (iid=classidmap_.begin(); iid!=classidmap_.end(); iid++) {
 | 
|---|
 | 241 |       const ClassDesc *cd = iid->first;
 | 
|---|
 | 242 |       int classid = iid->second;
 | 
|---|
 | 243 |       putstring(cd->name());
 | 
|---|
 | 244 |       put(cd->version());
 | 
|---|
 | 245 |       put(classid);
 | 
|---|
 | 246 | #if DEBUG
 | 
|---|
 | 247 |       ExEnv::outn() << "PUT CLASS:"
 | 
|---|
 | 248 |                    << " NAME = " << cd->name()
 | 
|---|
 | 249 |                    << " VERSION = " << cd->version()
 | 
|---|
 | 250 |                    << " ID = " << classid << endl;
 | 
|---|
 | 251 | #endif
 | 
|---|
 | 252 |     }
 | 
|---|
 | 253 | 
 | 
|---|
 | 254 |   // write the object information
 | 
|---|
 | 255 |   put(ps_.size());
 | 
|---|
 | 256 |   for (isd=ps_.begin(); isd!=ps_.end(); isd++) {
 | 
|---|
 | 257 |       const StateOutData& ptr = isd->second;
 | 
|---|
 | 258 |       put(ptr.num);
 | 
|---|
 | 259 |       put(ptr.type);
 | 
|---|
 | 260 |       put(ptr.offset);
 | 
|---|
 | 261 |       put(ptr.size);
 | 
|---|
 | 262 | #if DEBUG
 | 
|---|
 | 263 |       ExEnv::outn() << "PUT OBJECT:"
 | 
|---|
 | 264 |                    << " NUM = " << ptr.num
 | 
|---|
 | 265 |                    << " TYPE = " << ptr.type
 | 
|---|
 | 266 |                    << " OFFSET = " << ptr.offset
 | 
|---|
 | 267 |                    << " SIZE = " << ptr.size
 | 
|---|
 | 268 |                    << endl;
 | 
|---|
 | 269 | #endif
 | 
|---|
 | 270 |     }
 | 
|---|
 | 271 | }
 | 
|---|
 | 272 | 
 | 
|---|
 | 273 | int
 | 
|---|
 | 274 | StateOut::putstring(const char*s)
 | 
|---|
 | 275 | {
 | 
|---|
 | 276 |   int r=0;
 | 
|---|
 | 277 |   if (s) {
 | 
|---|
 | 278 |       int size = strlen(s)+1;
 | 
|---|
 | 279 |       r += put(size);
 | 
|---|
 | 280 |       r += put_array_char(s,size-1);
 | 
|---|
 | 281 |     }
 | 
|---|
 | 282 |   else {
 | 
|---|
 | 283 |       r += put((int)0);
 | 
|---|
 | 284 |     }
 | 
|---|
 | 285 |   return r;
 | 
|---|
 | 286 | }
 | 
|---|
 | 287 | 
 | 
|---|
 | 288 | int
 | 
|---|
 | 289 | StateOut::put(const std::string &s)
 | 
|---|
 | 290 | {
 | 
|---|
 | 291 |   int r = putstring(s.c_str());
 | 
|---|
 | 292 |   return r;
 | 
|---|
 | 293 | }
 | 
|---|
 | 294 | 
 | 
|---|
 | 295 | int
 | 
|---|
 | 296 | StateOut::put(const char*s,int size)
 | 
|---|
 | 297 | {
 | 
|---|
 | 298 |   int r=0;
 | 
|---|
 | 299 |   if (s) {
 | 
|---|
 | 300 |       r += put(size);
 | 
|---|
 | 301 |       r += put_array_char(s,size);
 | 
|---|
 | 302 |     }
 | 
|---|
 | 303 |   else {
 | 
|---|
 | 304 |       r += put((int)0);
 | 
|---|
 | 305 |     }
 | 
|---|
 | 306 |   return r;
 | 
|---|
 | 307 | }
 | 
|---|
 | 308 | 
 | 
|---|
 | 309 | int
 | 
|---|
 | 310 | StateOut::put(const unsigned int*s,int size)
 | 
|---|
 | 311 | {
 | 
|---|
 | 312 |   int r=0;
 | 
|---|
 | 313 |   if (s) {
 | 
|---|
 | 314 |       r += put(size);
 | 
|---|
 | 315 |       r += put_array_uint(s,size);
 | 
|---|
 | 316 |     }
 | 
|---|
 | 317 |   else {
 | 
|---|
 | 318 |       r += put((int)0);
 | 
|---|
 | 319 |     }
 | 
|---|
 | 320 |   return r;
 | 
|---|
 | 321 | }
 | 
|---|
 | 322 | 
 | 
|---|
 | 323 | int
 | 
|---|
 | 324 | StateOut::put(const int*s,int size)
 | 
|---|
 | 325 | {
 | 
|---|
 | 326 |   int r=0;
 | 
|---|
 | 327 |   if (s) {
 | 
|---|
 | 328 |       r += put(size);
 | 
|---|
 | 329 |       r += put_array_int(s,size);
 | 
|---|
 | 330 |     }
 | 
|---|
 | 331 |   else {
 | 
|---|
 | 332 |       r += put((int)0);
 | 
|---|
 | 333 |     }
 | 
|---|
 | 334 |   return r;
 | 
|---|
 | 335 | }
 | 
|---|
 | 336 | 
 | 
|---|
 | 337 | int
 | 
|---|
 | 338 | StateOut::put(const float*s,int size)
 | 
|---|
 | 339 | {
 | 
|---|
 | 340 |   int r=0;
 | 
|---|
 | 341 |   if (s) {
 | 
|---|
 | 342 |       r += put(size);
 | 
|---|
 | 343 |       r += put_array_float(s,size);
 | 
|---|
 | 344 |     }
 | 
|---|
 | 345 |   else {
 | 
|---|
 | 346 |       r += put((int)0);
 | 
|---|
 | 347 |     }
 | 
|---|
 | 348 |   return r;
 | 
|---|
 | 349 | }
 | 
|---|
 | 350 | 
 | 
|---|
 | 351 | int
 | 
|---|
 | 352 | StateOut::put(const double*s,int size)
 | 
|---|
 | 353 | {
 | 
|---|
 | 354 |   int r=0;
 | 
|---|
 | 355 |   if (s) {
 | 
|---|
 | 356 |       r += put(size);
 | 
|---|
 | 357 |       r += put_array_double(s,size);
 | 
|---|
 | 358 |     }
 | 
|---|
 | 359 |   else {
 | 
|---|
 | 360 |       r += put((int)0);
 | 
|---|
 | 361 |     }
 | 
|---|
 | 362 |   return r;
 | 
|---|
 | 363 | }
 | 
|---|
 | 364 | 
 | 
|---|
 | 365 | int
 | 
|---|
 | 366 | StateOut::put(const ClassDesc*cd)
 | 
|---|
 | 367 | {
 | 
|---|
 | 368 |   int r=0;
 | 
|---|
 | 369 |   // write out parent info
 | 
|---|
 | 370 |   if (classidmap_.find((ClassDesc*)cd) == classidmap_.end()) {
 | 
|---|
 | 371 |       r += putparents(cd);
 | 
|---|
 | 372 |       if (!use_directory()) {
 | 
|---|
 | 373 |           const char* name = cd->name();
 | 
|---|
 | 374 |           int size = strlen(name);
 | 
|---|
 | 375 |           r += put(size);
 | 
|---|
 | 376 |           r += put_array_char(name,size);
 | 
|---|
 | 377 |           r += put(cd->version());
 | 
|---|
 | 378 |         }
 | 
|---|
 | 379 |       classidmap_[(ClassDesc*)cd] = nextclassid_++;
 | 
|---|
 | 380 |     }
 | 
|---|
 | 381 |   if (!use_directory()) {
 | 
|---|
 | 382 |       // write out a 0 to indicate the end of the list
 | 
|---|
 | 383 |       r += put((int)0);
 | 
|---|
 | 384 |     }
 | 
|---|
 | 385 |   // the cast is needed to de-const-ify cd
 | 
|---|
 | 386 |   r += put(classidmap_[(ClassDesc*)cd]);
 | 
|---|
 | 387 |   return r;
 | 
|---|
 | 388 |   }
 | 
|---|
 | 389 | 
 | 
|---|
 | 390 | int
 | 
|---|
 | 391 | StateOut::putparents(const ClassDesc*cd)
 | 
|---|
 | 392 | {
 | 
|---|
 | 393 |   int r=0;
 | 
|---|
 | 394 |   const ParentClasses& parents = cd->parents();
 | 
|---|
 | 395 | 
 | 
|---|
 | 396 |   for (int i=0; i<parents.n(); i++) {
 | 
|---|
 | 397 |       // the cast is needed to de-const-ify the class descriptor
 | 
|---|
 | 398 |       ClassDesc*tmp = (ClassDesc*) parents[i].classdesc();
 | 
|---|
 | 399 |       if (classidmap_.find(tmp) == classidmap_.end()) {
 | 
|---|
 | 400 |           r += putparents(tmp);
 | 
|---|
 | 401 |           if (!use_directory()) {
 | 
|---|
 | 402 |               const char* name = tmp->name();
 | 
|---|
 | 403 |               int size = strlen(name);
 | 
|---|
 | 404 |               r += put(size);
 | 
|---|
 | 405 |               r += put_array_char(name,size);
 | 
|---|
 | 406 |               r += put(tmp->version());
 | 
|---|
 | 407 |             }
 | 
|---|
 | 408 |           classidmap_[(ClassDesc*)tmp] = nextclassid_++;
 | 
|---|
 | 409 |         }
 | 
|---|
 | 410 |     }
 | 
|---|
 | 411 | 
 | 
|---|
 | 412 |   return r;
 | 
|---|
 | 413 | }
 | 
|---|
 | 414 | 
 | 
|---|
 | 415 | int
 | 
|---|
 | 416 | StateOut::putobject(const Ref<SavableState> &p)
 | 
|---|
 | 417 | {
 | 
|---|
 | 418 |   int r=0;
 | 
|---|
 | 419 |   if (p.null()) {
 | 
|---|
 | 420 |       // reference to null
 | 
|---|
 | 421 |       r += put(0);
 | 
|---|
 | 422 |     }
 | 
|---|
 | 423 |   else {
 | 
|---|
 | 424 |       std::map<Ref<SavableState>,StateOutData>::iterator ind = ps_.find(p);
 | 
|---|
 | 425 |       if (ind == ps_.end() || copy_references_) {
 | 
|---|
 | 426 |           StateOutData dp;
 | 
|---|
 | 427 |           // object has not been written yet
 | 
|---|
 | 428 |           dp.num = next_object_number_++;
 | 
|---|
 | 429 |           dp.offset = tell();
 | 
|---|
 | 430 |           r += put(dp.num);
 | 
|---|
 | 431 |           const ClassDesc *cd = p->class_desc();
 | 
|---|
 | 432 |           r += put(cd);
 | 
|---|
 | 433 |           dp.type = classidmap_[(ClassDesc*)cd];
 | 
|---|
 | 434 |           if (!copy_references_) ps_[p] = dp;
 | 
|---|
 | 435 |           have_classdesc();
 | 
|---|
 | 436 |           p->save_vbase_state(*this);
 | 
|---|
 | 437 |           p->save_data_state(*this);
 | 
|---|
 | 438 |           if (!copy_references_) {
 | 
|---|
 | 439 |               ind = ps_.find(p);
 | 
|---|
 | 440 |               ind->second.size = tell() - ind->second.offset;
 | 
|---|
 | 441 |             }
 | 
|---|
 | 442 |         }
 | 
|---|
 | 443 |       else {
 | 
|---|
 | 444 |           // object has already been written
 | 
|---|
 | 445 |           r += put(ind->second.num);
 | 
|---|
 | 446 |         }
 | 
|---|
 | 447 |     }
 | 
|---|
 | 448 |   return r;
 | 
|---|
 | 449 | }
 | 
|---|
 | 450 | 
 | 
|---|
 | 451 | /////////////////////////////////////////////////////////////////////////////
 | 
|---|
 | 452 | 
 | 
|---|
 | 453 | // Local Variables:
 | 
|---|
 | 454 | // mode: c++
 | 
|---|
 | 455 | // c-file-style: "CLJ"
 | 
|---|
 | 456 | // End:
 | 
|---|