/*serialization2.m. 
Paul Johnson
March 6, 2002


Diddled serialization1.m. Changed to store data in Map with integer
keys.

Requires Swarm newer than 2002-03-08

To save data use:
   ./serialize2 -m create

   ./serialize2
to read the saved data back in and generate some printout.
*/

#import <simtools.h> // initSwarm
#import <defobj.h> // Archivers
#import <defobj/Create.h> // CreateDrop
#import <defobj/defalloc.h> // getZone


#define CATEGORY_COUNT 12
#define SCALE_COUNT 7


@interface Data: CreateDrop
{
  const char *date;
  double value;
  double V1;
  double V2;
  int V3;

#ifndef DYN_MEM
  int category[CATEGORY_COUNT];
  double scales[SCALE_COUNT];
#else
  int * category;
  double * scales;

#endif
}




- createEnd;
- setDate: (const char *)date;
- (double)getVal;
- setVal: (double)value;
- (void)lispOutDeep: stream;

@end

@implementation Data


- createEnd
{
  V1=2.3;
  V2=3.3;
  V3=5;

#ifdef DYN_MEM
  printf("DYN_MEM is set\n");
  scales = [globalZone  allocBlock: (SCALE_COUNT* sizeof(double)) ];
  category = [globalZone allocBlock: (CATEGORY_COUNT* sizeof(int))];
#endif
  return [super createEnd];
}




- setDate: (const char *)theDate
{
  date = STRDUP (theDate);
  return self;
}

- setVal: (double)theValue
{
  int i;
  value = theValue;
  for (i = 0; i < CATEGORY_COUNT; i++)
    {
      category[i] = i;
    }
  
  for (i = 0; i < SCALE_COUNT; i++)
    {
      scales[i] = [uniformDblRand getDoubleWithMin:0 withMax:1L];
    }
  

  return self;
}


- (double)getVal
{
  return value;
}


- (void)lispOutDeep: stream
{
  int categoryCount = CATEGORY_COUNT;
  int scaleCount = SCALE_COUNT;

  [stream catStartMakeInstance: "Data"];
  [super lispOutVars: stream deep: YES];

#ifdef DYN_MEM
  [stream catSeparator];
  [stream catKeyword: "category"];  //name by which to save array
  [stream catSeparator];
  lisp_process_array (1, &categoryCount, fcall_type_sint,
                      category, NULL, stream, NO);
  
  [stream catSeparator];
  [stream catKeyword: "scales"];   //name by which to save array
  [stream catSeparator];
  lisp_process_array (1, &scaleCount, fcall_type_double,
                      scales, NULL, stream, NO);
#endif
  [stream catEndMakeInstance];
}




@end

@interface Controller: CreateDrop
{
  id collection;
}

- createMap;
@end

#define NAME "myCollection"

@implementation Controller

- createMap
{
#define DATA(value,day) [[[[Data createBegin: getZone (self)] createEnd] setVal: value] setDate: day] 
  collection = [Map createBegin: getZone (self)];
  [collection setCompareIntegers];
  [collection createEnd];
  [collection at: (id)1 insert: DATA(1.0,"bday")];
  [collection at: (id)22 insert: DATA(2.0,"flower")];
  [collection at: (id)31 insert: DATA(3.0,"pumper")];
  return collection;
}

@end

int
main (int argc, const char **argv) 
{
  id archiver;
  id controller;

  initSwarmBatch (argc, argv);
  
#ifdef USE_HDF5
  archiver = [HDF5Archiver create: globalZone setPath: "collection.hdf"];
#else
  archiver = [[[LispArchiver createBegin: globalZone]
		setPath: "collection.scm"]
	       createEnd];
#endif
  controller = [Controller create: globalZone];
  
  
  if (strcmp ([arguments getAppModeString], "create") == 0)
    {
      id list = [controller createMap];
    
      //print it out to see if it is there
      {
	id key, obj;
	id index = [list begin: scratchZone];
	  
	for (obj = [index next: &key];
	     [index getLoc] == Member;
	     obj = [index next: &key])
	  {
	    printf ("Key: %d Value: %f\n",
		    (int *) key,
		    [obj getVal]);
	    }
	  [index drop];
	}
  
      [archiver putDeep: NAME object: list]; 
      
#ifndef USE_HDF5
      [archiver sync];  //required only for Lisp anymore?
#endif
    }     
  else
    {
      id collection, index, obj, key;

      collection = [archiver getObject: NAME];
      if (collection)
	{
	  index = [collection begin: scratchZone];
	  
	  for (obj = [index next: &key];
	       [index getLoc] == Member;
	       obj = [index next: &key])
	    {
	      printf ("key: %d Value: %f\n",
		      (int *) key,
		      [obj getVal]);
	    }
	  [index drop];
	}
    }
  
  
  [archiver drop]; //must drop to make it write in hdf5 mode. Replaces effect of sync?
  return 0;
}

/*
Local Variables:
compile-command: "$SWARMHOME/bin/libtool-swarm --mode=link gcc3 -DDYN_MEM -D_GNU_SOURCE -o serialize2  -g -Wno-import -I$SWARMHOME/include -I$SWARMHOME/include/swarm -L$SWARMHOME/lib -L$SWARMHOME/lib/swarm serialization2.m  -lswarm -lobjc "
End:
*/

