1 /* 2 * $Id: binio.h,v 1.6 2010-07-03 19:42:31 dhmunro Exp $ 3 * Declare structures and functions for arrays of data that have 4 * meaningful interpretations on disk. 5 * 6 * Yorick supports the following data types: 7 * 8 * char short int long float double 9 * string pointer complex struct(instance) 10 */ 11 /* Copyright (c) 2005, The Regents of the University of California. 12 * All rights reserved. 13 * This file is part of yorick (http://yorick.sourceforge.net). 14 * Read the accompanying LICENSE file for details. 15 */ 16 17 #ifndef BINIO_H 18 #define BINIO_H 19 20 #include "hash.h" 21 22 /*--------------------------------------------------------------------------*/ 23 24 /* IOStream is a complicated data structure which completely represents 25 a binary I/O stream. The data in the file(s) can be decribed using 26 the Contents Log (CLOG) language. Major components of the IOStream 27 are: 28 1. A table of data primitive and compound data types (structTable). 29 2. A table of variables (dataTable), which associate a variable 30 name with its data type, dimensions, and disk address. 31 3. An optional block of history information, detailing the 32 disk addresses (and files, if this is a family of files) of 33 the history records, if there are any. 34 4. An optional list of pointees, associating memory and disk 35 addresses of indirectly referenced data (not explicitly 36 in the dataTable). 37 5. An optional file containing the (plain text) CLOG description 38 of this file. 39 6. The list of cache blocks associated with this file, and the 40 last address read or written (since ftell doesn't know about 41 the cache buffers). 42 */ 43 typedef struct IOStream IOStream; 44 45 /* StructDef is the definition of a data structure, explicating the 46 meaning of data either on disk or in memory, and its relationship to 47 other data types. All structure definitions representing disk data 48 are "owned" by the IOStream associated with the disk file. Each 49 disk structure has a "model" data structure representing the 50 memory version of the same data. A conversion procedure converts 51 from a representation to its model or vice versa -- a feature 52 designed to handle disk data written in a non-native format. 53 (A structure representing data in memory may also have a "model" 54 and a corresponding conversion routine to handle automatic memory-to- 55 memory type conversions.) 56 A StructDef may represent either a primitive data type, or a compound 57 data type consisting of dimensioned members of simpler data types. 58 All data structures have an ASCII name, which is used to make 59 default correspondences between in-memory and on-disk structures. */ 60 typedef struct StructDef StructDef; 61 62 /* Array is a block of data with a specific data type (specified by 63 a StructDef) and dimensions. All objects of type pointer must be 64 either 0, or point to the first address of an Array value. 65 An Array represents scalar data if its dimension list is nil. */ 66 typedef struct Array Array; 67 68 /* Dimension is an element of a linked list of dimensions. A Dimension 69 list is always from slowest to fastest varying dimension. Each 70 dimension has an origin (suggested minimum index value) and length. */ 71 typedef struct Dimension Dimension; 72 struct Dimension { 73 Dimension *next; /* list goes from slowest to fastest varying */ 74 long number; /* length of this dimension */ 75 long origin; /* index of first element along this dimension */ 76 int references; /* reference counter */ 77 }; 78 79 /* Member is a data type and dimension list. The dataTable of an IOStream, 80 the member list of a StructDef, and an Array all consist in part of 81 one or more Member instances. */ 82 typedef struct Member Member; 83 struct Member { /* most general type of x: base_type x[][]...[][]; */ 84 StructDef *base; /* array base data type */ 85 Dimension *dims; /* array dimension list (may be nil) */ 86 long number; /* of items in array (product of dimensions) */ 87 }; 88 89 /* Strider is an element of a linked list of strides through data. Each 90 Strider consists of a stride (in bytes), a number of "footprints", 91 and an optional Array of type long containing an index list. */ 92 typedef struct Strider Strider; 93 struct Strider { 94 Strider *next; /* logically next faster varying block */ 95 long stride; /* stride length in bytes */ 96 long number; /* number of strides to take + 1 (# footprints!) */ 97 Array *indexList; /* if !=0, offset list (units of 'stride' bytes) */ 98 }; 99 100 /* Operations is a virtual function table for a DataBlock, the 101 container class for Array, StructDef, and IOStream (and others). */ 102 typedef struct Operations Operations; 103 /* The Operations* members depend on the details of Yorick, and are 104 therefore split out to allow this binary file package to be used 105 in non-Yorick based codes. These three values are explicitly 106 needed: */ 107 PLUG_API Operations *yOpsStruct, *yOpsStream, *yOpsStructDef; 108 109 /* DataLayout is a complete description of a primitive data type, 110 including byte size, alignment, byte order, and floating point layout 111 (if the type represents a real number). */ 112 typedef struct DataLayout DataLayout; 113 114 /* FPLayout is a description of the format of a floating point number, 115 detailing the bit addresses and number of bits in the exponent and 116 mantissa. The StructDefs of an IOStream corresponding to the float 117 and double primitive types must be describable by an FPLayout. */ 118 typedef struct FPLayout FPLayout; 119 120 /* IOOperations is an additional virtual function table for an IOStream. */ 121 typedef struct IOOperations IOOperations; 122 123 /* HistoryInfo keeps history record information for an IOStream. */ 124 typedef struct HistoryInfo HistoryInfo; 125 126 /* PointeeList keeps an association of disk and memory addresses for an 127 IOStream. This allows multiply referenced pointers to be written 128 only once. More subtlely, with a PointeeList, the algorithm to 129 write an arbitrarily complex tree of pointers requires a bounded 130 amount of stack space. */ 131 typedef struct PointeeList PointeeList; 132 typedef struct MDinfo MDinfo; /* for PointeeList */ 133 struct PointeeList { 134 int writing; /* 0 if table keyed to disk address, 135 1 if keyed to memory address */ 136 long nValid; /* number of valid objects (i.e.- where both 137 disk data address and m pointer contain 138 valid data) */ 139 HashXTable table; /* generic hash table for address correspondence */ 140 MDinfo *mdInfo; /* memory-disk correspondence list */ 141 }; 142 143 /* CLbuffer describes the state of the binary data description language 144 file associated with an IOStream. Defined in clog.c. */ 145 typedef struct CLbuffer CLbuffer; 146 147 /* CacheBlock is required by IOStream, but is opaque here. See cache.c. */ 148 typedef struct CacheBlock CacheBlock; 149 150 /*--------------------------------------------------------------------------*/ 151 152 struct IOStream { 153 int references; /* reference counter */ 154 Operations *ops; /* virtual function table */ 155 void *stream; /* usually the FILE*, but opaque here -- 156 0 indicates file has been closed */ 157 char *fullname; /* filename after YExpandName */ 158 int permissions; /* +1 read permission, +2 write permission 159 +4 append mode, +8 binary mode, 160 +16 not seekable, +32 pipe, +64 clog mode 161 */ 162 163 IOOperations *ioOps; /* virtual functions to read and write file */ 164 165 long blockSize; /* MUST be a power of 2 minus 1 (default 0x3fff) 166 all cache blocks will be multiples of 167 blockSize+1 bytes */ 168 CacheBlock *blockList; /* list of cache blocks for this file, 169 stored highest to lowest address */ 170 long seqAddress; /* address immediately after last address 171 actually read or written using YcRead or 172 YcWrite -- different from ftell(stream) 173 because of caching */ 174 175 int structAlign; /* byte offset of any struct in another struct 176 must be multiple of this (the alignment of 177 some structs may be more strict than this) */ 178 int dataAlign; /* 0 -- align variables to addresses as if 179 the file were a giant struct instance 180 >0 -- byte offset of any variable in file 181 must be a multiple of this 182 WARNING WARNING WARNING WARNING WARNING 183 This MUST be 0 in order to correctly write 184 a PDB file with history records. */ 185 186 HashTable structTable; /* table of StructDef names for this file */ 187 StructDef **structList; /* corresponding to structTable->names */ 188 189 HashTable dataTable; /* table of variable names for this file */ 190 Member *types; /* corresponding types and dimensions */ 191 long *addresses; /* corresponding addresses */ 192 long nextAddress; /* next free address (may be end of pointee) */ 193 long offset; /* to be applied to all addresses */ 194 195 HistoryInfo *history; /* non-0 if there is a history record structure 196 -- If so, then no changes to the dataTable 197 (which represents static variables) are 198 permitted. 199 Note that this IOStream may be either 200 history->parent or history->child. */ 201 202 CLbuffer *contentsLog; /* if non-0, contains "CLOG" textual equivalent 203 of structTable, dataTable, and history */ 204 205 PointeeList pointeeList; /* list of memory<->disk address correspondence 206 to aid in pointee reads or writes */ 207 void (*CloseHook)(IOStream *file); /* if non-0, called before close */ 208 }; 209 210 /* check to see if this is in-memory file created by vopen 211 * return value is the Array* or 0, stream is p_file* 212 */ 213 PLUG_API void *y_vopen_file(void *stream); 214 215 /*--------------------------------------------------------------------------*/ 216 217 /* A Copier copies data of type base from t to s. If t==s, the Copier 218 must appropriately zero s, releasing pointees if appropriate. If 219 t==s, non-pointered data should be left unchanged (the Copier is a 220 no-op). There are only 4 possible Copiers-- CopyX should be used 221 for StructDefs which contain no pointers, CopyS for StructDefs 222 whose members include pointers or strings. CopyQ is for stringStruct 223 and CopyP is for pointerStruct. */ 224 typedef void Copier(StructDef *base, void *dst, const void *src, long n); 225 PLUG_API Copier CopyX, CopyQ, CopyP, CopyS; 226 227 /* A Converter converts n objects to or from type base, which will often 228 be a foreign disk file data type. The conversion is from baseData to 229 modelData if toBase is 0, from modelData to baseData if toBase 230 is non-0. */ 231 typedef void Converter(StructDef *base, void *baseData, void *modelData, 232 long n, int toBase); 233 PLUG_API Converter ConvertI, ConvertF, ConvertQ, ConvertP, ConvertS; 234 235 struct StructDef { 236 int references; /* reference counter */ 237 Operations *ops; /* virtual function table */ 238 Operations *dataOps; /* virtual functions for an instance */ 239 240 long size; /* size of an instance of this data structure */ 241 int alignment; /* byte address must be multiple of this */ 242 243 HashTable table; /* rapid name->index and index->name associations */ 244 Member *members; /* members[table->maxEntries] is Member array */ 245 long *offsets; /* byte offsets corresponding to members */ 246 247 Copier *Copy; /* copy/initialize/delete operation */ 248 249 IOStream *file; /* non-zero if the data resides on disk 250 if file!=0, then model!=0 */ 251 long index; /* if file!=0, index in file->structList, 252 else index in yStructList */ 253 254 int addressType; /* 0 -> object is in memory (file==0), and address 255 is void* 256 1 -> object is on disk (file!=0) and address 257 is long 258 2 -> address cannot be meaningfully incremented 259 to find members or array elements */ 260 261 /* The remaining elements are to implement "transparent translation" 262 of this data type into another -- usually to change from disk 263 format to memory format. */ 264 StructDef *model; /* memory equivalent of disk StructDef 265 is NEVER 0 when file!=0, 266 also destination or source type for Convert */ 267 Converter *Convert; 268 /* Convert may be 0 if no conversion is required. 269 The order and fpLayout members can be used as a context 270 by Convert. In particular, fpLayout need not actually point 271 to an FPLayout, as long as the first member of the struct 272 it does point to is a reference counter. */ 273 int order; /* 1 MSB first, -1 LSB first, 274 -w for LSW first, MSB first within word size w 275 w for MSW first, LSB first within word size w */ 276 FPLayout *fpLayout; /* if non-0, used by Export/Import to translate 277 data format */ 278 }; 279 280 /* Nine in-memory data structures are predefined, corresponding with 281 the primitive data types in the C programming language: */ 282 PLUG_API StructDef charStruct; 283 PLUG_API StructDef shortStruct; 284 PLUG_API StructDef intStruct; 285 PLUG_API StructDef longStruct; 286 PLUG_API StructDef floatStruct; 287 PLUG_API StructDef doubleStruct; 288 PLUG_API StructDef stringStruct; /* char * always 0-terminated */ 289 PLUG_API StructDef pointerStruct; /* void * all pointers generic */ 290 PLUG_API StructDef complexStruct; /* struct complex { double re, im; } */ 291 /* The indirect types string and pointer are for restricted use only, 292 in the sense that special memory management routines must be used 293 to allocate and free the associated memory. 294 An IOStream structTable always begins with the on-disk analogues 295 of char, short, int, long, float, double, string, and pointer. */ 296 297 /*--------------------------------------------------------------------------*/ 298 299 /* Every on-disk StructDef in the structList for an IOStream has a 300 counterpart "model" StructDef representing the same data translated 301 into memory format. As for IOStreams, the first 8 StructDefs in 302 yStructList are always, in order, char, short, int, long, float, 303 double, string, pointer. The 9th in yStructList is complex. */ 304 305 PLUG_API HashTable yStructTable; /* table of StructDef names for memory */ 306 PLUG_API StructDef **yStructList; /* corresponding to yStructTable->names */ 307 308 /*--------------------------------------------------------------------------*/ 309 310 /* possibly should do this at configuration time... */ 311 #if defined(__i386__) || defined(_WIN32) 312 # define PAD_ARRAY 313 #endif 314 315 struct Array { 316 int references; /* reference counter */ 317 Operations *ops; /* virtual function table */ 318 Member type; /* full data type, i.e.- base_type x[]...[] */ 319 #ifdef PAD_ARRAY 320 /* on a pentium, 4-byte aligned doubles are legal, but access is 321 * far slower than to 8-byte aligned doubles 322 * since a Member is 12 bytes long, need to add 4 more here 323 * -- no other platform at this time needs this hack */ 324 int pad; 325 #endif 326 union { 327 /* Appropriate member is selected by ops; there are only 10 possible ops, 328 corresponding to char, short, int, long, float, double, complex, 329 string, pointer, and struct instance. 330 Actual array length is determined by type. */ 331 char c[1]; 332 short s[1]; 333 int i[1]; 334 long l[1]; 335 float f[1]; 336 double d[2]; /* also complex */ 337 char *q[1]; /* string */ 338 void *p[1]; 339 } value; 340 }; 341 342 /*--------------------------------------------------------------------------*/ 343 344 /* Each StructDef has an alignment, computed as the alignment of its 345 most restrictively aligned member. Some compilers/machines impose 346 an additional restriction on all structs, regardless of the most 347 restrictive member, in which case yStructAlign is set to that 348 additional struct alignment restriction. 349 350 IBM has a crazy special rule for PowerPC architecture, where 351 if the first member of a struct is a double, the struct alignment 352 is 8 instead of 4 (which is otherwise the most restrictive alignment). 353 However, IBM's own C compiler misapplies this rule so that only 354 the size of the struct is padded up to a multiple of 8 while its 355 alignment remains 4. This is yStructAlign=-1. 356 On PowerPCs, gcc attempts to follow IBMs written rule, and they 357 interpret a struct whose first member is an array of double to 358 *not* get the extra alignment. This is yStructAlign=-2. 359 See play/any/numfmt.c for more details. 360 361 It is also possible for a C compiler to require different alignment 362 for an array than for a scalar. Yorick cannot handle this. 363 Finally, the (hopefully defunct?) hybrid C compiler under the 364 (definitely defunct) NLTSS Cray operating system aligned a scalar 365 char to an address with remainder 7 modulo 8, which is hopeless. */ 366 PLUG_API int yStructAlign; 367 368 struct DataLayout { 369 int alignment; 370 long size; 371 int order; 372 FPLayout *fpLayout; 373 }; 374 375 /* Foreign formats for floating point data can be handled, provided they 376 fit within the parametrization of the FPLayout struct. 377 Foreign integer formats are described by a simple int (the order 378 member of a StructDef above). */ 379 struct FPLayout { 380 /* Addresses are in bits with 0 128-bit of the most significant byte 381 of the object, 8 the 128-bit of the 2nd most significant byte, 382 and so on until 8*size-1 is the 1-bit of the least significant 383 byte. The actual storage order of the bytes is given by the 384 order member of the DataLayout. 385 sgnAddr - bit address of overall sign 386 expAddr, expSize - bit address and size of exponent 387 manAddr, manSize - bit address and size of mantissa 388 manNorm - if non-zero, address of leading 1 in mantissa 389 expBias - exponent bias 390 */ 391 int references; /* reference counter */ 392 int sgnAddr, expAddr, expSize, manAddr, manSize, manNorm; 393 long expBias; 394 }; 395 396 /* Floating point layouts for floats and doubles on this machine */ 397 PLUG_API FPLayout *fltLayout, *dblLayout; 398 399 /*--------------------------------------------------------------------------*/ 400 401 struct IOOperations { 402 /* An IOStream requires the virtual functions Read, Write, Tell, 403 Seek, and SeekEnd, which are similar to the C standard library 404 routines fread, fwrite, ftell, fseek(,,SEEK_SET), and fseek(,,SEEK_END). 405 All 5 routines must be provided, but they may simply call YError if 406 the operation makes no sense. The Read function should return the 407 number (of objects of size size) actually read if EOF occured before 408 the read was complete; n on success. 409 In all cases, YError should be called if an error is detected, 410 AFTER the error is cleared, on the presumption that the next 411 operation will be valid. */ 412 long (*Read)(IOStream *file, void *buf, long size, long n); 413 void (*Write)(IOStream *file, const void *buf, long size, long n); 414 long (*Tell)(IOStream *file, long offset); 415 void (*Seek)(IOStream *file, long offset); 416 void (*SeekEnd)(IOStream *file, long offset); 417 void (*Close)(IOStream *file); 418 }; 419 420 struct HistoryInfo { 421 IOStream *parent; /* original file always used for static data */ 422 IOStream *child; /* separate IOStream used for history record traffic 423 so that child->members[i].base->file has a place 424 to point which may represent a different file in 425 a history family starting from the original parent */ 426 427 int nFamily; /* number of files in this family */ 428 char **famNames; /* used for child->fullname, 429 famNames[0]==parent->fullname 430 allocated length is 4*(1 + (nFamily-1)/4) */ 431 int fileNumber; /* 0 to nFamily-1, specifies index of current child */ 432 long fileSize; /* approximate maximum size for a file in family */ 433 #define DEFAULT_FILE_SIZE 0x800000 434 int copyParent; /* non-0 if parent (static variables) is to be copied 435 when a new file is added to this family */ 436 437 long recordSize; /* length of one record in bytes (not including 438 any strings, pointees, or other indirections) */ 439 int recordAlign; /* alignment for records -- either child->dataAlign, 440 or most restrictive alignment in child->structList 441 when 1st record was declared 442 Unlike a StructDef, recordSize is not necessarily 443 a multiple of recordAlign. */ 444 long nRecords; /* number of history records of this type */ 445 long recNumber; /* index into ifile and offset 446 for record represented by child (-1 if none) */ 447 448 /* allocated length of following arrays is 16*(1 + (nRecs-1)/16) */ 449 int *ifile; /* list of indices into famNames */ 450 long *offset; /* list of record byte addresses */ 451 double *time; /* 0 or list of floating point values of records */ 452 long *ncyc; /* 0 or list of integer values of records */ 453 }; 454 455 struct MDinfo { 456 void *m; /* memory address, always an Array->value.c; the 457 MDinfo owns a reference of the Array */ 458 long d; /* disk address of the pointee header */ 459 long data; /* disk address of the pointee data */ 460 StructDef *base; /* disk StructDef for this data -- this pointer does 461 NOT own a reference to base */ 462 }; 463 464 /*--------------------------------------------------------------------------*/ 465 466 /* fullname is NOT copied and FreeIOStream will do p_free(ios->fullname) */ 467 PLUG_API IOStream *NewIOStream(char *fullname, void *stream, int permissions); 468 PLUG_API void FreeIOStream(void *ios); /* *** Use Unref(ios) *** */ 469 470 PLUG_API StructDef *NewStructDef(IOStream *file, long index); 471 PLUG_API void FreeStructDef(void *base); /* *** Use Unref(base) *** */ 472 473 PLUG_API Array *NewArray(StructDef *base, Dimension *dims); 474 PLUG_API void FreeArray(void *array); /* *** Use Unref(array) *** */ 475 476 /* NewTmpArray/ClearTmpArray may be used to get one or two temporary 477 arrays. Call ClearTmpArray first, then NewTmpArray several times, 478 then ClearTmpArray. At the third call to NewTmpArray, the Array 479 returned by the first call is Unref'ed; at the fourth call to 480 NewTmpArray, the second is Unref'ed; and so on. */ 481 PLUG_API Array *NewTmpArray(StructDef *base, Dimension *dims); 482 PLUG_API void ClearTmpArray(void); 483 484 /* NewDimension does NOT do Ref(next) */ 485 /* WARNING: NewArray(base, NewDimension(...)) is a memory leak! 486 * need to use ynew_dim() below instead in this context 487 */ 488 PLUG_API int yForceOrigin; /* non-zero to ignore stated origin in Dimension 489 lists, and always assume 1-origin indices */ 490 PLUG_API Dimension *NewDimension(long number, long origin, Dimension *next); 491 PLUG_API void FreeDimension(Dimension *dims); 492 493 PLUG_API Strider *NewStrider(long stride, long number); 494 PLUG_API void FreeStrider(Strider *strider); 495 496 /*--------------------------------------------------------------------------*/ 497 498 #ifdef NOT_YORICK 499 /* This is the minimal Operations -- a virtual delete function. 500 Without this, the Unref macro is unusable. */ 501 struct Operations { 502 void (*Free)(void *); /* crucial member for Unref -- first in struct 503 to allow alternate Operations to be used */ 504 }; 505 #endif 506 507 #define Ref(db) ((db)?++(db)->references:0 , (db)) 508 #define RefNC(db) (++(db)->references , (db)) 509 #define Unref(db) {if ((db) && --(db)->references<0) (db)->ops->Free(db);} 510 #define UnrefNC(db) {if (--(db)->references<0) (db)->ops->Free(db);} 511 512 PLUG_API long TotalNumber(const Dimension *dims); 513 PLUG_API int CountDims(const Dimension *dims); 514 /* Note-- like NewDimension, CopyDims does NOT do Ref(next) */ 515 PLUG_API Dimension *CopyDims(Dimension *dims, Dimension *next, int copyOrigin); 516 517 /* CopyStrider also does NOT do Ref(next) */ 518 PLUG_API Strider *CopyStrider(Strider *strider, Strider *next); 519 520 /* tmpDims can be used for "protected" scratch space to build dimension 521 * lists. Before using tmpDims, always call FreeDimension(tmpDims). 522 * ynew_dim() sets tmpDims to the result of NewDimension(), so 523 * it can be used as argument to functions like NewArray which 524 * increment the use counter 525 */ 526 PLUG_API Dimension *tmpDims; 527 PLUG_API Dimension *ynew_dim(long n, Dimension *next); 528 529 /* Given a pointer to data (memory representation of a pointerStruct), 530 return the associated Array. */ 531 PLUG_API void *Pointee(void *pointer); 532 533 /* StructEqual tests for two structures which are exactly the same. 534 EquivStruct tests whether the file StructDef belonging to an IOStream 535 is equivalent to the mem StructDef belonging to yStructTable. */ 536 PLUG_API int StructEqual(StructDef *l, StructDef *r); 537 PLUG_API int EquivStruct(StructDef *fil, StructDef *mem); 538 539 /* Adjust the address to a multiple of the alignment (no-op if <2). */ 540 PLUG_API long AlignAdjust(long address, int alignment); 541 542 /* StructName works for disk or memory based StructDefs, 543 CopyStruct returns the StructDef in file->structTable equivalent 544 to the given base, creating it if necessary */ 545 PLUG_API char *StructName(StructDef *base); 546 PLUG_API StructDef *CopyStruct(IOStream *file, StructDef *base); 547 548 /*--------------------------------------------------------------------------*/ 549 550 /* AddStruct adds an empty data structure to a file structTable, 551 returning the new StructDef. Returns 0 on error. If the name 552 is a duplicate, returns 0 to signal error, but the names "string" 553 and "pointer" are excepted from this rule, provided that the 554 associated StructDef has not been referenced. 555 If file==0, the yStructTable is assumed. 556 If n is non-0, it must be the exact length of name -- 557 if n is 0, name is presumed 0-terminated. 558 If file->history!=0, the struct is added to the history child. 559 This is illegal after the second history record has begun. */ 560 PLUG_API StructDef *AddStruct(IOStream *file, const char *name, long n); 561 562 /* AddMember increments references to memType, dims -- offset 563 is computed if input offset<0. Returns 0 on success, 1 if name is a 564 duplicate, 2 if memType or a sub-structure has a type name conflict 565 in the file which owns base. 566 (If return non-0 memType, dims references NOT incremented). 567 In any case, hashIndex set to index of member in base. 568 In the case of a duplicate name, memType and dims are NOT 569 checked for consistency with the existing member. 570 ******* 571 WARNING-- if offset is specified, base->alignment cannot be updated, 572 and the proper alignment must be set by hand */ 573 PLUG_API int AddMember(StructDef *base, long offset, const char *name, 574 StructDef *memType, Dimension *dims); 575 576 /* DefinePrimitive is called in lieu of AddMember to define a primitive 577 data type after AddStruct has been called. If model==0, then must 578 have Convert==0, and DefinePrimitive will try to match the given 579 size, order, and fpLayout to one of char, short, long, float, or 580 double (never int) as best it can. If model is one of the primitive 581 types (char, short, int, long, float, double, string, or pointer), 582 and size==0, DefinePrimitive will also set Convert appropriately. 583 If order==0 (opaque primitive), a model must be supplied. 584 If non-zero, fpLayout is copied. 585 Returns 0 on success, 586 1 on attempt to redefine char, short, int, long, float, or double 587 to a model other than the default one 588 2 on attempt to alias another type to string or pointer without 589 providing an explicit Converter 590 3 if an opaque type model size differs and no Converter supplied, 591 4 if Converter supplied without a model 592 5 if no model supplied for opaque primitive */ 593 PLUG_API int DefinePrimitive(StructDef *base, long size, int alignment, 594 int addressType, int order, FPLayout *fpLayout, 595 StructDef *model, Converter *Convert); 596 597 /* InstallStruct finishes a structure defintion begun with AddStruct 598 and AddMember calls. If base->file==0, base is added to yStructTable 599 incrementing base->references. 600 If base->file, then an equivalent in-memory model is found for 601 base->model: First, yStructTable table is checked for an 602 in-memory equivalent StructDef of the same name as base. Failing 603 this, if base is a primitive with non-zero base->order or base->size==1, 604 it is matched to the "closest" of the primitive data types char, short, 605 long, float, or double (never int). Failing this, an in-memory model 606 is constructed and installed on the spot. 607 In all cases, base->dataOps is set to "validate" the StructDef. 608 If model is non-zero, it is assumed to be the correct model for base. */ 609 PLUG_API void InstallStruct(StructDef *base, StructDef *model); 610 611 /* If DefInstallHook is non-0, InstallStruct calls it after 612 installing base in yStructTable if base->file!=0 */ 613 PLUG_API void (*DefInstallHook)(const char *name, StructDef *base); 614 615 /* AddVariable increments references to varType, dims -- address 616 is computed if input address<0. Returns 0 on success, 1 if name is 617 a duplicate, and 2 if the name of varType or one of its sub-structures 618 already belongs to a non-equivalent data structure (in either non-0 619 case varType, dims references NOT incremented). 620 For returns 0 or 1, hashIndex set to index of name in file->dataTable, 621 or file->history->child->dataTable, if file->history!=0. 622 In the case of a duplicate name, varType and dims are NOT 623 checked for consistency with the existing variable. 624 If file->history!=0, the variable is added to the history child 625 (i.e.- it becomes a record variable). This is illegal after the 626 second history record has begun. */ 627 PLUG_API int AddVariable(IOStream *file, long address, const char *name, 628 StructDef *varType, Dimension *dims); 629 630 /* AddHistory adds a history child to an existing IOStream, returning the 631 file->history if successful. Size is the approximate maximum size of 632 one file in the history family, or 0 for the default (4 Megabytes). */ 633 PLUG_API HistoryInfo *AddHistory(IOStream *file, long size); 634 635 /* AddRecord adds a record to the HistoryInfo, returning 0 on success. 636 flags is +1 if time exists, +2 if ncyc exists 637 The record is assumed to be in the current history child at the 638 specified address, or at the next available address if address<0. */ 639 PLUG_API int AddRecord(HistoryInfo *history, 640 int flags, double time, long ncyc, long address); 641 642 /* AddNextFile adds a new file to the HistoryInfo, returning 0 on 643 success. If the fullname is 0, the NextFileName function is used. 644 If the create flag is non-0, the file is created (possibly copying 645 the parent data), otherwise the file is expected to exist. */ 646 PLUG_API int AddNextFile(HistoryInfo *history, char *filename, int create); 647 648 /* Return value must be freed with p_free. 649 Algorithm: 650 (1) Strip directory (if any) from name. 651 (2) If final character is a digit (0-9), it becomes increment character, 652 else the character before the final dot (.) is the increment 653 character (or the final character if there is no dot). 654 (3) If the increment character is not A-Z, a-z, or 0-9, scan backwards 655 through the name until a character in this range is found. 656 (4) Loop: 657 If the increment character is before the beginning of name, 658 or if it is not in the range A-Z, a-z, or 0-9, insert the 659 character "A" and break out of this loop. 660 If it is 9 or z or Z, it becomes 0, 661 else increment it and break out of this loop. 662 Back up so the increment character becomes the previous character. 663 */ 664 PLUG_API char *NextFileName(const char *name); 665 666 /* JumpToTime (JumpToCycle) jumps to the nearest time (ncyc) in the 667 current record sequence to the specified time (ncyc). Returns 0 668 on success, non-0 on failure. */ 669 PLUG_API int JumpToTime(HistoryInfo *history, double time); 670 PLUG_API int JumpToCycle(HistoryInfo *history, long ncyc); 671 /* JumpRecord returns 0 on success, 1 on recNumber out of range. 672 If recNumber is out of range, there is no current record. */ 673 PLUG_API int JumpRecord(HistoryInfo *history, long recNumber); 674 675 /*--------------------------------------------------------------------------*/ 676 677 /* Parameters for adjusting caching system -- see cache.c */ 678 PLUG_API long yMaxBlockSize, yCacheSize, yCacheTotal, y_block_size_0; 679 PLUG_API int yCacheNumber, yCacheN; 680 681 /* copy src from 0 to src->nextAddress to dst, return 0 on success */ 682 PLUG_API int YCopyFile(IOStream *dst, IOStream *src); 683 684 /* FlushFile flushes all cache blocks associated with file, optionally 685 discarding them altogether. */ 686 PLUG_API void FlushFile(IOStream *file, int discardCache); 687 688 /* YcRead and YcWrite are the lowest level read and write primitives for 689 moving data to or from an IOStream. The addr and len are in bytes. 690 All data goes through the cache buffer system defined in cache.c. */ 691 PLUG_API long YcRead(IOStream *file, void *buf, long addr, long len); 692 PLUG_API void YcWrite(IOStream *file, const void *buf, long addr, long len); 693 694 /* YRead and YWrite are the high level interface to an IOStream. 695 The base->file MUST be non-zero. In both cases, the void* is an 696 in-memory buffer holding (or big enough to hold) number objects of size 697 base->model->...->size. If strider is non-0, number is ignored and 698 the disk data referenced will be described by the strider. (Use the 699 Scatter and Gather routines from bcast.h to apply a Strider to arrays 700 in memory.) 701 These routines perform any data type conversions necessary to move 702 foreign formats, strings, or pointers to and from disk. */ 703 PLUG_API void YWrite(void *src, long dst, StructDef *base, long number, 704 const Strider *strider); 705 PLUG_API void YRead(void *dst, long src, StructDef *base, long number, 706 const Strider *strider); 707 708 /*--------------------------------------------------------------------------*/ 709 710 /* CLupdate ensures that file->contentsLog exists and is up to date. */ 711 PLUG_API void CLupdate(IOStream *file); 712 713 /* CLopen checks to see if file has a Clog description appended to it, 714 returning 0 if it does, in which case the file is updated. */ 715 PLUG_API int CLopen(IOStream *file, int familyOK); 716 717 /* CLclose is suitable for use as a CloseHook -- appends Clog description 718 to end of file and zaps file->contentsLog. */ 719 PLUG_API void CLclose(IOStream *file); 720 721 /* ZapClogFile frees file->contentsLog, and destroys the associated file. */ 722 PLUG_API void ZapClogFile(IOStream *file); 723 724 /* FreeClogFile frees file->contentsLog. */ 725 PLUG_API void FreeClogFile(IOStream *file); 726 727 /* DumpClogFile creates a Contents Log named clogName, describing file. 728 This is completely independent of the file->contentsLog, if any. */ 729 PLUG_API int DumpClogFile(IOStream *file, const char *clogName); 730 731 /* ReadClogFile reads a Contents Log named clogName and makes file 732 look like the description therein. (CLopen with a separate file.) 733 This is completely independent of the file->contentsLog, if any. */ 734 PLUG_API int ReadClogFile(IOStream *file, const char *clogName); 735 736 /* functions to manage file->pointeeList */ 737 PLUG_API void ReadPointees(IOStream *file); 738 PLUG_API void WritePointees(IOStream *file); 739 PLUG_API void ClearPointees(IOStream *file, int writing); 740 741 /* functions to manage FPLayouts */ 742 PLUG_API FPLayout *MakeFPLayout(FPLayout *model, long size); 743 PLUG_API void FreeFPLayout(FPLayout *layout); 744 PLUG_API int SameFPLayout(FPLayout *l, FPLayout *m); 745 746 /* ------------------------------------------------------------------------ */ 747 748 /* YError and YWarning must be supplied by user of binary file package. 749 YError should longjump or exit, YWarning may return. */ 750 PLUG_API void YWarning(const char *msg); 751 PLUG_API void YError(const char *msg); 752 753 /* ------------------------------------------------------------------------ */ 754 755 #endif 756