add pup support
[charm.git] / src / util / pup.h
1 /*
2 Pack/UnPack Library for UIUC Parallel Programming Lab
3 Orion Sky Lawlor, olawlor@uiuc.edu, 4/5/2000
4
5 This library allows you to easily pack an array, structure,
6 or object into a memory buffer or disk file, and then read
7 the object back later.  The library can also handle translating
8 between different machine representations for integers and floats.
9
10 Originally, you had to write separate functions for buffer 
11 sizing, pack to memory, unpack from memory, pack to disk, and 
12 unpack from disk.  These functions all perform the exact same function--
13 namely, they list the members of the array, struct, or object.
14 Further, all the functions must agree, or the unpacked data will 
15 be garbage.  This library allows the user to write *one* function,
16 pup, which will perform all needed packing/unpacking.
17
18 A simple example is:
19 class foo {
20  private:
21   CmiBool isBar;
22   int x;
23   char y;
24   unsigned long z;
25   CkVec<double> q;
26  public:
27   ...
28   void pup(PUP::er &p) {
29     PUPn(isBar);
30     PUPn(x);PUPn(y);PUPn(z);
31     PUPn(q);
32   }
33 };
34
35 A more complex example is:
36 class bar {
37  private:
38   foo f;
39   int nArr;//Length of array below
40   double *arr;//Heap-allocated array
41  public:
42   ...
43   
44   void pup(PUP::er &p) {
45     PUPn(f); // <- automatically calls foo::pup
46     PUPn(nArr);
47     if (p.isUnpacking()) // <- must allocate array on other side.
48       arr=new double[nArr];
49     PUPv(arr,nArr); // <- special syntax for arrays of simple types
50   }
51 };
52 */
53
54 #ifndef __CK_PUP_H
55 #define __CK_PUP_H
56
57 #include <stdio.h> /*<- for "FILE *" */
58
59 #ifndef __cplusplus
60 #error "Use pup_c.h for C programs-- pup.h is for C++ programs"
61 #endif
62
63 #ifdef STANDALONE_PUP
64 #define CmiAbort(x) { printf(x); abort(); }
65 #else
66 #ifndef CHARM_H
67 #  include "converse.h" // <- for CmiBool, CMK_* defines
68 #endif
69 extern "C" void CmiAbort(const char *msg);
70 #endif
71
72 //We need CkMigrateMessage only to distinguish the migration
73 // constructor from all other constructors-- the type
74 // itself has no meaningful fields.
75 typedef struct {int is_only_a_name;} CkMigrateMessage;
76
77 namespace PUP {
78
79 #if CMK_LONG_LONG_DEFINED
80 #define CMK_PUP_LONG_LONG long long
81 #elif CMK___int64_DEFINED
82 #define CMK_PUP_LONG_LONG __int64
83 #endif
84
85  
86 //Item data types-- these are used to do byte swapping, etc.
87 typedef enum {
88 //(this list must exactly match that in PUPer_xlate)
89   Tchar=0,Tshort, Tint, Tlong, Tlonglong,
90   Tuchar,Tushort,Tuint,Tulong, Tulonglong,
91 #if CMK_HAS_INT16
92   Tint128, Tuint128,
93 #endif
94   Tfloat,Tdouble,Tlongdouble,
95   Tbool,
96   Tbyte,
97   Tsync,
98   Tpointer,
99   dataType_last //<- for setting table lengths, etc.
100 } dataType;
101
102 //This should be a 1-byte unsigned type
103 typedef unsigned char myByte;
104
105 //Forward declarations
106 class er;
107 class able;
108
109 //Used for out-of-order unpacking
110 class seekBlock {
111         enum {maxSections=3};
112         int secTab[maxSections+1];//The start of each seek section
113         int nSec;//Number of sections; current section #
114         int secTabOff;//Start of the section table, relative to the seek block
115         er &p;
116         CmiBool hasEnded;
117 public:
118         //Constructor
119         seekBlock(er &Np,int nSections);
120         //Destructor
121         ~seekBlock();
122
123         //Seek to the given section number (0-based, less than nSections)
124         void seek(int toSection);
125         //Finish with this seeker (must be called)
126         void endBlock(void);
127
128         //An evil hack to avoid inheritance and virtual functions among seekers--
129         // stores the PUP::er specific block start information.
130         union {
131                 int off;
132                 long loff;
133                 const myByte *cptr;
134                 myByte *ptr;
135                 void *vptr;
136         } data;
137 };
138
139 //The abstract base class:  PUP::er.
140 class er {
141  private:
142   er(const er &p);//You don't want to copy PUP::er's.
143  protected:
144   /// These state bits describe various user-settable properties.
145   enum {IS_USERLEVEL=0x0004, // If set, this is *not* a migration pup-- it's something else.
146         IS_DELETING =0x0008, // If set, C & f90 objects should delete themselves after pup
147         IS_COMMENTS =0x0010,  // If set, this PUP::er wants comments and sync codes.
148         IS_RESTARTING=0x0020  // If set, it is during restarting
149   };
150   /// These state bits describe the PUP::er's direction.
151   enum {IS_SIZING   =0x0100,
152         IS_PACKING  =0x0200,
153         IS_UNPACKING=0x0400,
154         IS_CHECKING=0x0800,  // If set, it is checking the match of 2 checkpoints
155         TYPE_MASK   =0xFF00
156   };
157   unsigned int PUP_er_state;
158 #if CMK_EXPLICIT
159   explicit /* Makes constructor below behave better */
160 #endif
161            er(unsigned int inType): PUP_er_state(inType) {} //You don't want to create raw PUP::er's.
162  public:
163   virtual ~er();//<- does nothing, but might be needed by some child
164
165   //State queries (exactly one of these will be true)
166   CmiBool isSizing(void) const {return (PUP_er_state&IS_SIZING)!=0?CmiTrue:CmiFalse;}
167   CmiBool isPacking(void) const {return (PUP_er_state&IS_PACKING)!=0?CmiTrue:CmiFalse;}
168   CmiBool isUnpacking(void) const {return (PUP_er_state&IS_UNPACKING)!=0?CmiTrue:CmiFalse;}
169   CmiBool isChecking(void) const {return (PUP_er_state&IS_CHECKING)!=0?CmiTrue:CmiFalse;}
170   const char *  typeString() const;
171   unsigned int getStateFlags(void) const {return PUP_er_state;}
172
173   //This indicates that the pup routine should free memory during packing.
174   void becomeDeleting(void) {PUP_er_state|=IS_DELETING;}
175   CmiBool isDeleting(void) const {return (PUP_er_state&IS_DELETING)!=0?CmiTrue:CmiFalse;}
176
177   //This indicates that the pup routine should not call system objects' pups.
178   void becomeUserlevel(void) {PUP_er_state|=IS_USERLEVEL;}
179   CmiBool isUserlevel(void) const {return (PUP_er_state&IS_USERLEVEL)!=0?CmiTrue:CmiFalse;}
180   
181   //This indicates that the pup routine should not call system objects' pups.
182   void becomeRestarting(void) {PUP_er_state|=IS_RESTARTING;}
183   CmiBool isRestarting(void) const {return (PUP_er_state&IS_RESTARTING)!=0?CmiTrue:CmiFalse;}
184   
185   CmiBool hasComments(void) const {return (PUP_er_state&IS_COMMENTS)!=0?CmiTrue:CmiFalse;}
186
187 //For single elements, pretend it's an array containing one element
188   void operator()(signed char &v)     {(*this)(&v,1);}
189 #if CMK_SIGNEDCHAR_DIFF_CHAR
190   void operator()(char &v)            {(*this)(&v,1);}
191 #endif
192   void operator()(short &v)           {(*this)(&v,1);}
193   void operator()(int &v)             {(*this)(&v,1);}
194   void operator()(long &v)            {(*this)(&v,1);}
195   void operator()(unsigned char &v)   {(*this)(&v,1);}
196   void operator()(unsigned short &v)  {(*this)(&v,1);}
197   void operator()(unsigned int &v)    {(*this)(&v,1);}
198   void operator()(unsigned long &v)   {(*this)(&v,1);}
199   void operator()(float &v)           {(*this)(&v,1);}
200   void operator()(double &v)          {(*this)(&v,1);}
201 #if CMK_LONG_DOUBLE_DEFINED
202   void operator()(long double &v)     {(*this)(&v,1);}
203 #endif
204   void operator()(CmiBool &v)         {(*this)(&v,1);}
205 #ifdef CMK_PUP_LONG_LONG
206   void operator()(CMK_PUP_LONG_LONG &v) {(*this)(&v,1);}
207   void operator()(unsigned CMK_PUP_LONG_LONG &v) {(*this)(&v,1);}
208 #endif
209 #if CMK_HAS_INT16
210   void operator()(CmiInt16 &v) {(*this)(&v,1);}
211   void operator()(CmiUInt16 &v) {(*this)(&v,1);}
212 #endif
213   void operator()(void* &v,void* sig) {(*this)(&v,1,sig);}
214   
215 //For arrays:
216   //Integral types:
217   void operator()(signed char *a,int nItems)
218     {bytes((void *)a,nItems,sizeof(signed char),Tchar);}
219 #if CMK_SIGNEDCHAR_DIFF_CHAR
220   void operator()(char *a,int nItems)
221     {
222                 //printf("pup char data\n");
223                 bytes((void *)a,nItems,sizeof(char),Tchar);
224         }
225 #endif
226   void operator()(short *a,int nItems)
227     {bytes((void *)a,nItems,sizeof(short),Tshort);}
228   void operator()(int *a,int nItems)
229     {bytes((void *)a,nItems,sizeof(int),Tint);}
230   void operator()(long *a,int nItems)
231     {bytes((void *)a,nItems,sizeof(long),Tlong);}
232
233   //Unsigned integral types:
234   void operator()(unsigned char *a,int nItems)
235     {bytes((void *)a,nItems,sizeof(unsigned char),Tuchar);}
236   void operator()(unsigned short *a,int nItems)
237     {bytes((void *)a,nItems,sizeof(unsigned short),Tushort);}
238   void operator()(unsigned int *a,int nItems)
239     {bytes((void *)a,nItems,sizeof(unsigned int),Tuint);}
240   void operator()(unsigned long *a,int nItems)
241     {bytes((void *)a,nItems,sizeof(unsigned long),Tulong);}
242
243   //Floating-point types:
244   void operator()(float *a,int nItems)
245     {bytes((void *)a,nItems,sizeof(float),Tfloat);}
246   void operator()(double *a,int nItems)
247     {
248                 bytes((void *)a,nItems,sizeof(double),Tdouble);
249         }
250
251 #if CMK_LONG_DOUBLE_DEFINED
252   void operator()(long double *a,int nItems)
253     {bytes((void *)a,nItems,sizeof(long double),Tlongdouble);}
254 #endif
255
256   //For bools:
257   void operator()(CmiBool *a,int nItems)
258     {bytes((void *)a,nItems,sizeof(CmiBool),Tbool);}
259
260 #ifdef CMK_PUP_LONG_LONG
261   void operator()(CMK_PUP_LONG_LONG *a,int nItems)
262     {bytes((void *)a,nItems,sizeof(CMK_PUP_LONG_LONG),Tlonglong);}
263   void operator()(unsigned CMK_PUP_LONG_LONG *a,int nItems)
264     {bytes((void *)a,nItems,sizeof(unsigned CMK_PUP_LONG_LONG),Tulonglong);}
265 #endif
266 #if CMK_HAS_INT16
267   void operator()(CmiInt16 *a,int nItems)
268     {bytes((void *)a,nItems,sizeof(CmiInt16),Tint128);}
269   void operator()(CmiUInt16 *a,int nItems)
270     {bytes((void *)a,nItems,sizeof(CmiUInt16),Tuint128);}
271 #endif
272
273   //For pointers: the last parameter is to make it more difficult to call
274   //(should not be used in normal code as pointers may loose meaning across processor)
275   void operator()(void **a,int nItems,void *pointerSignature)
276     {bytes((void *)a,nItems,sizeof(void *),Tpointer);}
277   
278   //For raw memory (n gives number of bytes)
279 /*
280   // pup void * is error-prune, let's avoid it - Gengbin
281   void operator()(void *a,int nBytes)
282     {bytes((void *)a,nBytes,1,Tbyte);}
283 */
284
285   //For allocatable objects (system will new/delete object and call pup routine)
286   void operator()(able** a)
287     {object(a);}
288   //For pre- or stack-allocated PUP::able objects-- just call object's pup
289   void operator()(able& a);
290
291   /// A descriptive (but entirely optional) human-readable comment field
292   virtual void comment(const char *message);
293
294   /// A 32-bit "synchronization marker" (not human readable).
295   ///  Some standard codes are listed under PUP::sync_....
296   virtual void synchronize(unsigned int sync);
297   
298   /// Insert a synchronization marker and comment into the stream.
299   ///  Only applies if this PUP::er wants comments.
300   inline void syncComment(unsigned int sync,const char *message=0) {
301 #if CMK_ERROR_CHECKING
302         if (hasComments()) {
303                 synchronize(sync);
304                 if (message) comment(message);
305         }
306 #else
307         /* empty, to avoid expensive virtual function calls */
308 #endif
309   }
310
311   //Generic bottleneck: pack/unpack n items of size itemSize
312   // and data type t from p.  Desc describes the data item
313   virtual void bytes(void *p,int n,size_t itemSize,dataType t) =0;
314   virtual void object(able** a);
315
316   virtual int size(void) const { return 0; }
317   
318   virtual void setAccuracy(double _accuracy){}
319   virtual void skipNext(){}
320   virtual void skip(){}
321   virtual void resume(){}
322
323   //For seeking (pack/unpack in different orders)
324   virtual void impl_startSeek(seekBlock &s); /*Begin a seeking block*/
325   virtual int impl_tell(seekBlock &s); /*Give the current offset*/
326   virtual void impl_seek(seekBlock &s,int off); /*Seek to the given offset*/
327   virtual void impl_endSeek(seekBlock &s);/*End a seeking block*/
328
329   //See more documentation before PUP_cmiAllocSizer in pup_cmialloc.h
330   //Must be a CmiAlloced buf while packing
331   virtual void pupCmiAllocBuf(void **msg) 
332       {CmiAbort("Undefined PUPer:Did you use PUP_toMem or PUP_fromMem?\n");}
333
334   //In case source is not CmiAlloced the size can be passed and any
335   //user buf can be converted into a cmialloc'ed buf
336   virtual void pupCmiAllocBuf(void **msg, int size)
337       {CmiAbort("Undefined PUPer:Did you use PUP_toMem or PUP_fromMem?\n");}
338 };
339
340 /**
341  "Sync" codes are an extra channel to encode data in a pup stream, 
342  to indicate higher-order structures in the pup'd objects.
343  Sync codes must follow this grammar:
344    <obj> -> <obj> <obj> | <array> | <list>
345    <obj> -> begin (<obj> system) <obj> end
346    <array> -> begin <obj> (item <obj>)* end
347    <list> -> begin <obj> (index <obj> item <obj>)* end
348  This hack is used, e.g., by the debugger.
349 */
350 enum {
351   sync_builtin=0x70000000, // Built-in, standard sync codes begin here
352   sync_begin=sync_builtin+0x01000000, // Sync code at start of collection
353   sync_end=sync_builtin+0x02000000, // Sync code at end of collection
354   sync_last_system=sync_builtin+0x09000000, // Sync code at end of "system" portion of object
355   sync_array_m=0x00100000, // Linear-indexed (0..n) array-- use item to separate
356   sync_list_m=0x00200000, // Some other collection-- use index and item
357   sync_object_m=0x00300000, // Sync mask for general object
358   
359   sync_begin_array=sync_begin+sync_array_m,
360   sync_begin_list=sync_begin+sync_list_m, 
361   sync_begin_object=sync_begin+sync_object_m, 
362   
363   sync_end_array=sync_end+sync_array_m, 
364   sync_end_list=sync_end+sync_list_m, 
365   sync_end_object=sync_end+sync_object_m, 
366   
367   sync_item=sync_builtin+0x00110000, // Sync code for a list or array item
368   sync_index=sync_builtin+0x00120000, // Sync code for index of item in a list
369   
370   sync_last
371 };
372
373 /************** PUP::er -- Sizer ******************/
374 //For finding the number of bytes to pack (e.g., to preallocate a memory buffer)
375 class sizer : public er {
376  protected:
377   int nBytes;
378   //Generic bottleneck: n items of size itemSize
379   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
380  public:
381   //Write data to the given buffer
382   sizer(void):er(IS_SIZING),nBytes(0) {}
383   
384   //Return the current number of bytes to be packed
385   int size(void) const {return nBytes;}
386 };
387
388 template <class T>
389 inline int size(T &t) {
390         PUP::sizer p; p|t; return p.size();
391 }
392
393 /********** PUP::er -- Binary memory buffer pack/unpack *********/
394 class mem : public er { //Memory-buffer packers and unpackers
395  protected:
396   myByte *origBuf;//Start of memory buffer
397   myByte *buf;//Memory buffer (stuff gets packed into/out of here)
398   mem(unsigned int type,myByte *Nbuf):er(type),origBuf(Nbuf),buf(Nbuf) {}
399   mem(const mem &p);                    //You don't want to copy
400   void operator=(const mem &p);         // You don't want to copy
401
402   //For seeking (pack/unpack in different orders)
403   virtual void impl_startSeek(seekBlock &s); /*Begin a seeking block*/
404   virtual int impl_tell(seekBlock &s); /*Give the current offset*/
405   virtual void impl_seek(seekBlock &s,int off); /*Seek to the given offset*/
406  public:
407   //Return the current number of buffer bytes used
408   int size(void) const {return buf-origBuf;}
409 };
410
411 class checker : public er {
412  protected:
413   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
414   myByte * origBuf;
415   myByte * buf;
416   double accuracy;
417   bool _skip;
418   bool result;
419   bool reset;
420  public:
421         checker(void * Abuf, void * Bbuf):er(IS_CHECKING),origBuf((myByte *)Abuf),buf((myByte *)Bbuf),_skip(false),accuracy(0.0),result(true),reset(false) {}
422         virtual void setAccuracy(double _accuracy) {
423                 accuracy = _accuracy;
424                 //printf("set accuracy %lf\n",accuracy);
425         }
426         virtual void skipNext() {
427                 _skip = true;
428                 reset = true;
429                 //printf("skip\n");
430         }
431         virtual void skip() {
432                 _skip = true;
433                 reset = false;
434         }
435         virtual void resume() {
436                 _skip = false;
437         }
438
439         bool getResult() {return result;}       
440 };
441
442 //For packing into a preallocated, presized memory buffer
443 class toMem : public mem {
444  protected:
445   //Generic bottleneck: pack n items of size itemSize from p.
446   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
447  public:
448   //Write data to the given buffer
449   toMem(void *Nbuf):mem(IS_PACKING,(myByte *)Nbuf) {}
450 };
451 template <class T>
452 inline void toMemBuf(T &t,void *buf,int len) {
453         PUP::toMem p(buf);
454         p|t;
455         if (p.size()!=len) CmiAbort("Size mismatch during PUP::toMemBuf!\n"
456                 "This means your pup routine doesn't match during sizing and packing");
457 }
458
459 //For unpacking from a memory buffer
460 class fromMem : public mem {
461  protected:
462   //Generic bottleneck: unpack n items of size itemSize from p.
463   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
464  public:
465   //Read data from the given buffer
466   fromMem(const void *Nbuf):mem(IS_UNPACKING,(myByte *)Nbuf) {}
467 };
468 template <class T>
469 inline void fromMemBuf(T &t,void *buf,int len) {
470         PUP::fromMem p(buf);
471         p|t;
472         if (p.size()!=len) CmiAbort("Size mismatch during PUP::fromMemBuf!\n"
473                 "This means your pup routine doesn't match during packing and unpacking");
474 }
475
476
477 /********** PUP::er -- Binary disk file pack/unpack *********/
478 class disk : public er {
479  protected:
480   FILE *F;//Disk file to read from/write to
481   disk(unsigned int type,FILE *f):er(type),F(f) {}
482   disk(const disk &p);                  //You don't want to copy
483   void operator=(const disk &p);        // You don't want to copy
484
485   //For seeking (pack/unpack in different orders)
486   virtual void impl_startSeek(seekBlock &s); /*Begin a seeking block*/
487   virtual int impl_tell(seekBlock &s); /*Give the current offset*/
488   virtual void impl_seek(seekBlock &s,int off); /*Seek to the given offset*/
489 };
490
491 //For packing to a disk file
492 class toDisk : public disk {
493  protected:
494   //Generic bottleneck: pack n items of size itemSize from p.
495   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
496  public:
497   // Write data to the given file pointer
498   // (must be opened for binary write)
499   // You must close the file yourself when done.
500   toDisk(FILE *f):disk(IS_PACKING,f) {}
501 };
502
503 //For unpacking from a disk file
504 class fromDisk : public disk {
505  protected:
506   //Generic bottleneck: unpack n items of size itemSize from p.
507   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
508  public:
509   // Read data from the given file pointer 
510   // (must be opened for binary read)
511   // You must close the file yourself when done.
512   fromDisk(FILE *f):disk(IS_UNPACKING,f) {}
513 };
514
515 /************** PUP::er -- Text *****************/
516 class toTextUtil : public er {
517  private:
518   char *cur; /*Current output buffer*/
519   int level; /*Indentation distance*/
520   void beginEnv(const char *type,int n=0);
521   void endEnv(const char *type);
522   char *beginLine(void);
523   void endLine(void);
524  protected:
525   virtual char *advance(char *cur)=0; /*Consume current buffer and return next*/
526   toTextUtil(unsigned int inType,char *buf);
527   toTextUtil(const toTextUtil &p);              //You don't want to copy
528   void operator=(const toTextUtil &p);          // You don't want to copy
529  public:
530   virtual void comment(const char *message);
531   virtual void synchronize(unsigned int m);
532  protected:
533   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
534   virtual void object(able** a);
535 };
536 /* Return the number of characters, including terminating NULL */
537 class sizerText : public toTextUtil {
538  private:
539   char line[1000];
540   int charCount; /*Total characters seen so far (not including NULL) */
541  protected:
542   virtual char *advance(char *cur);
543  public:
544   sizerText(void);
545   int size(void) const {return charCount+1; /*add NULL*/ }
546 };
547
548 /* Copy data to this C string, including terminating NULL. */
549 class toText : public toTextUtil {
550  private:
551   char *buf;
552   int charCount; /*Total characters written so far (not including NULL) */
553  protected:
554   virtual char *advance(char *cur);
555  public:
556   toText(char *outStr);
557   toText(const toText &p);                      //You don't want to copy
558   void operator=(const toText &p);              // You don't want to copy
559   int size(void) const {return charCount+1; /*add NULL*/ }
560 };
561
562 class toTextFile : public er {
563  protected:
564   FILE *f;
565   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
566  public:
567   //Begin writing to this file, which should be opened for ascii write.
568   // You must close the file yourself when done.
569   toTextFile(FILE *f_) :er(IS_PACKING), f(f_) {}
570   toTextFile(const toTextFile &p);              //You don't want to copy
571   void operator=(const toTextFile &p);          // You don't want to copy
572   virtual void comment(const char *message);
573 };
574 class fromTextFile : public er {
575  protected:
576   FILE *f;
577   int readInt(const char *fmt="%d");
578   unsigned int readUint(const char *fmt="%u");
579   CMK_TYPEDEF_INT8 readLongInt(const char *fmt="%lld");
580   double readDouble(void);
581   
582   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
583   virtual void parseError(const char *what);
584  public:
585   //Begin writing to this file, which should be opened for ascii read.
586   // You must close the file yourself when done.
587   fromTextFile(FILE *f_) :er(IS_UNPACKING), f(f_) {}
588   fromTextFile(const fromTextFile &p);          //You don't want to copy
589   void operator=(const fromTextFile &p);        // You don't want to copy
590   virtual void comment(const char *message);
591 };
592
593 /********** PUP::er -- Heterogenous machine pack/unpack *********/
594 //This object describes the data representation of a machine.
595 class machineInfo {
596  public:
597   typedef unsigned char myByte;
598   myByte magic[4];//Magic number (to identify machineInfo structs)
599   myByte version;//0-- current version
600
601   myByte intBytes[5]; //<- sizeof(char,short,int,long,int128)
602   myByte intFormat;//0-- big endian.  1-- little endian.
603
604   myByte floatBytes; //<- sizeof(...)
605   myByte doubleBytes;
606   myByte floatFormat;//0-- big endian IEEE.  1-- little endian IEEE.
607
608   myByte boolBytes;
609   myByte pointerBytes;
610
611 //  myByte padding[1];//Padding to 16 bytes
612
613   //Return true if our magic number is valid.
614   CmiBool valid(void) const;
615   //Return true if we differ from the current (running) machine.
616   CmiBool needsConversion(void) const;
617   
618   //Get a machineInfo for the current machine
619   static const machineInfo &current(void);
620
621   void pup(er &p) {
622       myByte  padding;
623
624       p(magic, 4);
625       p(version);
626       if (version == 0) p(intBytes, 4);
627       else p(intBytes, 5);
628       p(intFormat);
629       p(floatBytes); p(doubleBytes); p(floatFormat);
630       p(boolBytes); p(pointerBytes);
631       if (version == 0) p(padding);
632   }
633 };
634
635 /// "Wrapped" PUP::er: forwards requests to another PUP::er.
636 class wrap_er : public er {
637 protected:
638         er &p;
639 public:
640         wrap_er(er &p_,unsigned int newFlags=0) :er(p_.getStateFlags()|newFlags), p(p_) {}
641         virtual int size(void) const { return p.size(); }
642         
643         virtual void impl_startSeek(seekBlock &s); /*Begin a seeking block*/
644         virtual int impl_tell(seekBlock &s); /*Give the current offset*/
645         virtual void impl_seek(seekBlock &s,int off); /*Seek to the given offset*/
646         virtual void impl_endSeek(seekBlock &s);/*End a seeking block*/
647 };
648
649 //For translating some odd disk/memory representation into the 
650 // current machine representation.  (We really only need to
651 // translate during unpack-- "reader makes right".)
652 class xlater : public wrap_er {
653  protected:
654   typedef void (*dataConverterFn)(int N,const myByte *in,myByte *out,int nElem);
655   
656   //This table is indexed by dataType, and contains an appropriate
657   // conversion function to unpack a n-item array of the corresponding 
658   // data type (possibly in-place).
659   dataConverterFn convertFn[dataType_last];
660   //Maps dataType to source machine's dataSize
661   size_t convertSize[dataType_last];
662   void setConverterInt(const machineInfo &m,const machineInfo &cur,
663     int isUnsigned,int intType,dataType dest);
664   
665   //Generic bottleneck: unpack n items of size itemSize from p.
666   virtual void bytes(void *p,int n,size_t itemSize,dataType t);
667  public:
668   xlater(const machineInfo &fromMachine, er &fromData);
669 };
670
671 /*************** PUP::able support ***************/
672 //The base class of system-allocatable objects with pup routines
673 class able {
674 public:
675         //A globally-unique, persistent identifier for an allocatable object
676         class PUP_ID {
677         public:
678                 enum {len=8};
679                 unsigned char hash[len];
680                 PUP_ID() {}
681                 PUP_ID(int val) {for (int i=0;i<len;i++) hash[i]=val;}
682                 PUP_ID(const char *name) {setName(name);}
683                 void setName(const char *name);//Write name into hash
684                 CmiBool operator==(const PUP_ID &other) const {
685                         for (int i=0;i<len;i++)
686                                 if (hash[i]!=other.hash[i])
687                                         return CmiFalse;
688                         return CmiTrue;
689                 }
690                 void pup(er &p) {
691                          p((char *)hash,sizeof(unsigned char)*len);
692                 }
693                 void pup(er &p) const {
694                          p((char *)hash,sizeof(unsigned char)*len);
695                 }
696         };
697
698 protected:
699         able() {}
700         able(CkMigrateMessage *) {}
701         virtual ~able();//Virtual destructor may be needed by some child
702
703 public:
704 //Constructor function registration:
705         typedef able* (*constructor_function)(void);
706         static PUP_ID register_constructor(const char *className,
707                 constructor_function fn);
708         static constructor_function get_constructor(const PUP_ID &id);
709         virtual /*PUP::*/able *clone(void) const;
710
711 //Target methods:
712         virtual void pup(er &p);
713         virtual const PUP_ID &get_PUP_ID(void) const=0;
714 };
715
716 //Declarations which create routines implemeting the | operator.
717 //  Macros to be used inside a class body.
718 #define PUPable_operator_inside(className)\
719     friend inline void operator|(PUP::er &p,className &a) {a.pup(p);}\
720     friend inline void operator|(PUP::er &p,className* &a) {\
721         PUP::able *pa=a;  p(&pa);  a=(className *)pa;\
722     }
723
724 //  Macros to be used outside a class body.
725 #define PUPable_operator_outside(className)\
726     inline void operator|(PUP::er &p,className &a) {a.pup(p);}\
727     inline void operator|(PUP::er &p,className* &a) {\
728         PUP::able *pa=a;  p(&pa);  a=(className *)pa;\
729     }
730
731 //Declarations to include in a PUP::able's body.
732 //  Convenient, but only usable if class is not inside a namespace.
733 #define PUPable_decl(className) \
734     PUPable_decl_inside(className) \
735     PUPable_operator_inside(className)
736
737 #define PUPable_decl_template(className) \
738     PUPable_decl_inside_template(className) \
739     PUPable_operator_inside(className)
740
741 //PUPable_decl for classes inside a namespace: inside body
742 #define PUPable_decl_inside(className) \
743 private: \
744     static PUP::able *call_PUP_constructor(void); \
745     static PUP::able::PUP_ID my_PUP_ID;\
746 public:\
747     virtual const PUP::able::PUP_ID &get_PUP_ID(void) const; \
748     static void register_PUP_ID(const char* name);
749
750 #define PUPable_decl_inside_template(className) \
751 private: \
752     static PUP::able* call_PUP_constructor(void) { \
753         return new className((CkMigrateMessage *)0);}                   \
754     static PUP::able::PUP_ID my_PUP_ID;\
755 public: \
756     virtual const PUP::able::PUP_ID &get_PUP_ID(void) const { \
757         return my_PUP_ID; }                                     \
758     static void register_PUP_ID(const char* name) { \
759         my_PUP_ID=register_constructor(name,call_PUP_constructor);}
760
761 //PUPable_decl for classes inside a namespace: in header at file scope
762 #define PUPable_decl_outside(className) \
763      PUPable_operator_outside(className)
764
765 //PUPable_decl for classes inside a namespace: in header at file scope
766 #define PUPable_decl_outside_template(templateParameters,className)     \
767      template<templateParameters> inline void operator|(PUP::er &p,className &a) {a.pup(p);} \
768      template<templateParameters> inline void operator|(PUP::er &p,className* &a) { \
769          PUP::able *pa=a;  p(&pa);  a=(className *)pa; } \
770      template<templateParameters> PUP::able *className::call_PUP_constructor(void) { \
771          return new className((CkMigrateMessage *)0);}                  \
772      template<templateParameters> const PUP::able::PUP_ID &className::get_PUP_ID(void) const { \
773          return className::my_PUP_ID; }                                 \
774      template<templateParameters> void className::register_PUP_ID(const char* name) { \
775          my_PUP_ID=register_constructor(name,className::call_PUP_constructor);}
776
777
778 //Declarations to include in an abstract PUP::able's body.
779 //  Abstract PUP::ables do not need def or reg.
780 #define PUPable_abstract(className) \
781 public:\
782     virtual const PUP::able::PUP_ID &get_PUP_ID(void) const =0; \
783     PUPable_operator_inside(className)
784
785 //Definitions to include exactly once at file scope
786 #define PUPable_def(className) \
787         PUP::able *className::call_PUP_constructor(void) \
788                 { return new className((CkMigrateMessage *)0);}\
789         const PUP::able::PUP_ID &className::get_PUP_ID(void) const\
790                 { return className::my_PUP_ID; }\
791         PUP::able::PUP_ID className::my_PUP_ID;\
792         void className::register_PUP_ID(const char* name)\
793                 {my_PUP_ID=register_constructor(name,\
794                               className::call_PUP_constructor);}
795
796 //Definitions to include exactly once at file scope
797 #define PUPable_def_template(className) \
798         template<> PUP::able::PUP_ID className::my_PUP_ID = 0;
799
800 //Code to execute exactly once at program start time
801 #define PUPable_reg(className)  \
802     className::register_PUP_ID(#className);
803 #define PUPable_reg2(classIdentifier,className) \
804     classIdentifier::register_PUP_ID(className);
805
806
807 } //<- End namespace PUP
808
809 inline void operator|(PUP::er &p,PUP::able &a) {a.pup(p);}
810 inline void operator|(PUP::er &p,PUP::able* &a) {p(&a);}
811
812 //Holds a pointer to a (possibly dynamically allocated) PUP::able.
813 //  Extracting the pointer hands the deletion responsibility over.
814 //  This is used by parameter marshalling, which doesn't work well 
815 //  with bare pointers.
816 //   CkPointer<T> t   is the parameter-marshalling equivalent of   T *t
817 template <class T>
818 class CkPointer {
819         T *allocated; //Pointer that PUP dynamically allocated for us (recv only)
820         T *ptr; //Read-only pointer
821
822 #if 0 /* Private (do-not-use) copy constructor.  This prevents allocated from being
823          deleted twice--once in the original, and again in the copy.*/
824         CkPointer(const CkPointer<T> &src); // Don't use this!
825 #else /* Some compilers, like gcc3, have a hideous bug that causes them to *demand*
826          a public copy constructor when a class is used to initialize a const-reference
827          from a temporary.  The public copy constructor should never be called, though. */
828 public:
829         CkPointer(const CkPointer<T> &src) {
830                 CmiAbort("PUPable_marshall's cannot be passed by value.  Pass them only by reference!");
831         }
832         void operator=(const CkPointer<T> &src) {
833                 CmiAbort("PUPable_marshall's cannot be passed by value.  Pass them only by reference!");
834         }
835 #endif
836 protected:
837         T *peek(void) {return ptr;}
838 public:
839         /// Used on the send side, and does *not* delete the object.
840         CkPointer(T *src)  ///< Marshall this object.
841         { 
842                 allocated=0; //Don't ever delete src
843                 ptr=src;
844         }
845         
846         /// Begin completely empty: used on marshalling recv side.
847         CkPointer(void) { 
848                 ptr=allocated=0;
849         }
850         
851         ~CkPointer() { if (allocated) delete allocated; }
852         
853         /// Extract the object held by this class.  
854         ///  Deleting the pointer is now the user's responsibility
855         inline operator T* () { allocated=0; return ptr; }
856         
857         inline void pup(PUP::er &p) {
858                 bool ptrWasNull=(ptr==0);
859                 
860                 PUP::able *ptr_able=ptr; // T must inherit from PUP::able!
861                 p|ptr_able; //Pack as a PUP::able *
862                 ptr=(T *)ptr_able;
863                 
864                 if (ptrWasNull) 
865                 { //PUP just allocated a new object for us-- 
866                   // make sure it gets deleted eventually.
867                         allocated=ptr;
868                 }
869         }
870         friend inline void operator|(PUP::er &p,CkPointer<T> &v) {v.pup(p);}
871 };
872 #define PUPable_marshall CkPointer
873
874 //Like CkPointer, but keeps deletion responsibility forever.
875 //   CkReference<T> t  is the parameter-marshalling equivalent of   T &t
876 template<class T>
877 class CkReference : private CkPointer<T> {
878 public:
879         /// Used on the send side, and does *not* delete the object.
880         CkReference(T &src)   ///< Marshall this object.
881                 :CkPointer<T>(&src) { }
882         
883         /// Begin completely empty: used on the recv side.
884         CkReference(void) {}
885         
886         /// Look at the object held by this class.  Does *not* hand over
887         /// deletion responsiblity.
888         inline operator T& () { return *this->peek(); }
889         
890         inline void pup(PUP::er &p) {CkPointer<T>::pup(p);}
891         
892         friend inline void operator|(PUP::er &p,CkReference<T> &v) {v.pup(p);}
893 };
894
895 // For people that forget the "::"
896 typedef PUP::er PUPer;
897 typedef PUP::able PUPable;
898
899 /******** PUP via pipe: another way to access PUP::ers *****
900 The parameter marshalling system pups each variable v using just:
901      p|v;
902 Thus we need a "void operator|(PUP::er &p,T &v)" for all types
903 that work with parameter marshalling. 
904 */
905
906 namespace PUP {
907         /** 
908           Traits class: decide if the type T can be safely
909           pupped as raw bytes.  This is true of classes that
910           do not contain pointers and do not need pup routines.
911           Use this like:
912              if (PUP::as_bytes<someClass>::value) { ... }
913         */
914         template<class T> class as_bytes {
915 #ifdef CK_DEFAULT_BITWISE_PUP   /* OLD */
916                 public: enum {value=1};
917 #else /* normal case: don't pack as bytes by default */
918                 public: enum {value=0};
919 #endif
920         };
921 }
922
923 #ifdef CK_DEFAULT_BITWISE_PUP   /* OLD compatability mode*/
924 /// Default operator| and PUParray: copy as bytes.
925 template <class T>
926 inline void operator|(PUP::er &p,T &t) {p((void *)&t,sizeof(T));}
927 template <class T>
928 inline void PUParray(PUP::er &p,T *ta,int n) { p((void *)ta,n*sizeof(T)); }
929
930 /* enable normal pup mode from CK_DEFAULT_BITWISE_PUP */
931 #  define PUPmarshall(type) \
932 template<class T> inline void operator|(PUP::er &p,T &t) { t.pup(p); } \
933 template<class T> inline void PUParray(PUP::er &p,T *t,int n) { \
934         for (int i=0;i<n;i++) p|t[i]; \
935 }
936
937 #else /* !CK_DEFAULT_BITWISE_PUP */
938 /// Normal case: Call pup routines by default
939 /**
940   Default operator|: call pup routine.
941 */
942 template<class T>
943 inline void operator|(PUP::er &p,T &t) { 
944         p.syncComment(PUP::sync_begin_object);
945         t.pup(p);
946         p.syncComment(PUP::sync_end_object); 
947 }
948
949 /**
950   Default PUParray: pup each element.
951 */
952 template<class T>
953 inline void PUParray(PUP::er &p,T *t,int n) {
954         p.syncComment(PUP::sync_begin_array);
955         for (int i=0;i<n;i++) {
956                 p.syncComment(PUP::sync_item);
957                 p|t[i];
958         }
959         p.syncComment(PUP::sync_end_array);
960 }
961
962 /* PUPmarshall macro: now a deprecated no-op */
963 #  define PUPmarshall(type) /* empty, pup routines now the default */
964 #endif
965 #define PUPmarshal(type) PUPmarshall(type) /*Support this common misspelling*/
966
967
968 /// Copy this type as raw memory (like memcpy).
969 #define PUPbytes(type) \
970   inline void operator|(PUP::er &p,type &t) {p((char *)&t,sizeof(type));} \
971   inline void PUParray(PUP::er &p,type *ta,int n) { p((char *)ta,n*sizeof(type)); } \
972   namespace PUP { template<> class as_bytes<type> { \
973         public: enum {value=1};  \
974   }; }
975 #define PUPmarshallBytes(type) PUPbytes(type)
976
977 /// Make PUP work with this function pointer type, copied as raw bytes.
978 #define PUPfunctionpointer(fnPtrType) \
979   inline void operator|(PUP::er &p,fnPtrType &t) {p((char *)&t,sizeof(fnPtrType));}
980
981 /// Make PUP work with this enum type, copied as an "int".
982 #define PUPenum(enumType) \
983   inline void operator|(PUP::er &p,enumType &e) { int v=e;  p|v; e=v; }
984
985
986 /**
987   For all builtin types, like "int",
988   operator| and PUParray use p(t) and p(ta,n).
989 */
990 #define PUP_BUILTIN_SUPPORT(type) \
991   inline void operator|(PUP::er &p,type &t) {p(t);} \
992   inline void PUParray(PUP::er &p,type *ta,int n) { p(ta,n); } \
993   namespace PUP { template<> class as_bytes<type> { \
994         public: enum {value=1};  \
995   }; }
996 PUP_BUILTIN_SUPPORT(signed char)
997 #if CMK_SIGNEDCHAR_DIFF_CHAR
998 PUP_BUILTIN_SUPPORT(char)
999 #endif
1000 PUP_BUILTIN_SUPPORT(unsigned char)
1001 PUP_BUILTIN_SUPPORT(short)
1002 PUP_BUILTIN_SUPPORT(int)
1003 PUP_BUILTIN_SUPPORT(long)
1004 PUP_BUILTIN_SUPPORT(unsigned short)
1005 PUP_BUILTIN_SUPPORT(unsigned int)
1006 PUP_BUILTIN_SUPPORT(unsigned long)
1007 PUP_BUILTIN_SUPPORT(float)
1008 PUP_BUILTIN_SUPPORT(double)
1009 PUP_BUILTIN_SUPPORT(CmiBool)
1010 #if CMK_LONG_DOUBLE_DEFINED
1011 PUP_BUILTIN_SUPPORT(long double)
1012 #endif
1013 #ifdef CMK_PUP_LONG_LONG
1014 PUP_BUILTIN_SUPPORT(CMK_PUP_LONG_LONG)
1015 PUP_BUILTIN_SUPPORT(unsigned CMK_PUP_LONG_LONG)
1016 #endif
1017 #if CMK_HAS_INT16
1018 PUP_BUILTIN_SUPPORT(CmiInt16)
1019 PUP_BUILTIN_SUPPORT(CmiUInt16)
1020 #endif
1021
1022
1023 //This macro is useful in simple pup routines:
1024 //  It's just p|x, but it also documents the *name* of the variable.
1025 // You must have a PUP::er named p.
1026 #define PUPn(field) \
1027   do{  if (p.hasComments()) p.comment(#field); p|field; } while(0)
1028
1029 //Like PUPn(x), above, but for arrays.
1030 #define PUPv(field,len) \
1031   do{  if (p.hasComments()) p.comment(#field); PUParray(p,field,len); } while(0)
1032
1033
1034 #endif //def __CK_PUP_H
1035
1036