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