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