/* ** PQDIF - Power Quality Data Interchange Format ** Version 1.5 ** ** File name: $Workfile: pqdif_ph.h $ ** Last modified: $Modtime: 1/07/02 3:59p $ ** Last modified by: $Author: Erich $ ** ** VCS archive path: $Archive: /PQDIF/Document/IEEE/pqdif_ph.h $ ** VCS revision: $Revision: 22 $ ** ** PHYSICAL FORMAT DEFINITIONS ** ====================================================================== ** This file contains the complete definitions for the physical ** format of a PQDIF file. It contains no information about the ** _logical_ structure, which is defined in PQDIF_LG.H ** ** ====================================================================== ** The current version of this file and related information ** can be found at URL: ** ** http://grouper.ieee.org/groups/1159/3/docs.html ** ** ====================================================================== */ #ifndef PQDIF_PH_H #define PQDIF_PH_H // The structures must be 1-byte packed. //#ifdef __BORLANDC__ // #pragma pack( 1 ) //#elif _MSC_VER // #pragma pack( push, 1 ) //#else // #pragma pack( 1 ) //#endif #pragma pack( 1 ) /* ** PHYSICAL TYPE IDs AND DEFINITIONS ** ====================================================================== ** The physical types are intended to be fully portable. ** ====================================================================== */ /* ** Physical representation IDs ** ** NOTE: Larger objects such as strings and BLOBs (Binary Large OBject) ** are represented as vectors of other primitive types. ** ** Examples ** -------- ** ASCII string Vector of ID_PHYS_TYPE_CHAR1, NULL-terminated ** (i.e., the last character must be a NULL, to ** correspond to a C-style string). ** ** Unicode string Vector of ID_PHYS_TYPE_CHAR2. ** ** BLOB vector of ID_PHYS_TYPE_INTEGER1 or ** ID_PHYS_TYPE_UNS_INTEGER1. */ #define ID_PHYS_TYPE_BOOLEAN1 1 #define ID_PHYS_TYPE_BOOLEAN2 2 #define ID_PHYS_TYPE_BOOLEAN4 3 #define ID_PHYS_TYPE_CHAR1 10 // ASCII #define ID_PHYS_TYPE_CHAR2 11 // Unicode // Signed integers #define ID_PHYS_TYPE_INTEGER1 20 #define ID_PHYS_TYPE_INTEGER2 21 #define ID_PHYS_TYPE_INTEGER4 22 // Unsigned integers #define ID_PHYS_TYPE_UNS_INTEGER1 30 #define ID_PHYS_TYPE_UNS_INTEGER2 31 #define ID_PHYS_TYPE_UNS_INTEGER4 32 // Real/complex #define ID_PHYS_TYPE_REAL4 40 #define ID_PHYS_TYPE_REAL8 41 #define ID_PHYS_TYPE_COMPLEX8 42 // Two REAL4s: real, imag #define ID_PHYS_TYPE_COMPLEX16 43 // Two REAL8s: real, imag // Date/time variations #define ID_PHYS_TYPE_TIMESTAMPPQDIF 50 // Physical: TIMESTAMPPQDIF (total 12 bytes) // GUID #define ID_PHYS_TYPE_GUID 60 // Physical: GUID (total 16 bytes) //WW 20240520 start typedef unsigned int DWORD; typedef int BOOL; typedef unsigned char BYTE; typedef unsigned short WORD; typedef float FLOAT; typedef FLOAT *PFLOAT; typedef int INT; typedef unsigned int UINT; typedef unsigned int *PUINT; /** FALSE */ #ifndef FALSE #define FALSE 0 #endif /** TRUE */ #ifndef TRUE #define TRUE (!FALSE) #endif #if (!defined(_T)) && (!defined(__T)) #ifdef STDTIME_UNICODE #define __T(x) L##x #define _T(x) __T(x) #else #define __T(x) x #define _T(x) x #endif #endif /* not defined _T and __T */ #ifdef _UNICODE #define TCHAR wchar_t #else #define TCHAR char #endif #ifndef strcmpi #define strcmpi strcasecmp #endif //WW 20240520 end /* ** Portable primitive type definitions */ typedef char BOOL1; typedef short BOOL2; typedef int BOOL4; typedef char CHAR1; // ASCII string character typedef short CHAR2; // Unicode string character typedef char INT1; typedef short INT2; typedef int INT4; typedef unsigned char UINT1; typedef unsigned short UINT2; typedef unsigned int UINT4; typedef float REAL4; typedef double REAL8; typedef struct _complex8 { REAL4 real; REAL4 image; } COMPLEX8; typedef struct _complex16 { REAL8 real; REAL8 image; } COMPLEX16; /* ** Types used in structures (but not used as primitives for elements) */ typedef int LINKABS4; typedef int LINKREL4; typedef int SIZE4; /* ** Portable physical time structure definition ** ** (Modified version of time tracking used by Excel ** Excel counts days since 1900, converts to a double ** and adds to this a number less than 1.0 that ** is the fractional day. This structure enhances ** accuracy of this method by separating out the ** days since 1900 and seconds since midnight.) */ typedef struct ts { UINT4 day; // days since January 1, 1900 UCT // 0xFFFFFFFF -> 4294967295 days -> a long time REAL8 sec; // fractional seconds since midnight of day } TIMESTAMPPQDIF; /* ** GUID (Globally Unique IDentifier) definition ** (Used for tagging sections to identify them logically) ** ** The Unique Universal Identifier (UUID) is also known ** as a Globally Unique Identifier (GUID). It is ** a randomly generated number that due to its size, ** is guaranteed to be unique in the universe. This ** guarantees that the tags will be unique and anyone ** can generate "private" tags which will never conflict ** with the standard tags. ** ** GUID tags are used to mark the header of each record, ** as well as identify the elements in the internal structures. */ #ifndef GUID_DEFINED #define GUID_DEFINED typedef struct _GUID { unsigned int Data1;//WW 20240522 64λ longÊÇ8¸ö×Ö½Ú unsigned short Data2; unsigned short Data3; unsigned char Data4[8]; } GUID; #endif /* GUID_DEFINED */ /* ** PHYSICAL TYPE HELPER INFORMATION ** ====================================================================== ** Time structure helpers ** ** The following constant is the number of days between ** 1/1/1900 and 1/1/1970. This is used to convert between ** "C Time" and Excel style day counts ** "C Time" is a 4 byte integer representing the number of ** seconds elapsed since January 1, 1970. ** Excel time is an 8 byte real number that represents ** the number of days elapsed since 1/1/1900. The fractional ** part is therefore convertable to seconds since midnight. */ #define EXCEL_DAYCOUNT_ADJUST 25569L #define SECONDS_PER_DAY 86400L /* ** Define GUID helpers */ #define PQDIF_IsEqualGUID(rguid1, rguid2) (!memcmp(&rguid1, &rguid2, sizeof(GUID))) #define PQDIF_DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \ const GUID name = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } } #define PQDIFGUID_IsEqual(rguid1, rguid2) ( rguid1.Data1==rguid2.Data1 && rguid1.Data2==rguid2.Data2 && rguid1.Data3==rguid2.Data3 \ && rguid1.Data4[0]==rguid2.Data4[0] && rguid1.Data4[1]==rguid2.Data4[1] \ && rguid1.Data4[2]==rguid2.Data4[2] && rguid1.Data4[3]==rguid2.Data4[3] \ && rguid1.Data4[4]==rguid2.Data4[4] && rguid1.Data4[5]==rguid2.Data4[5] \ && rguid1.Data4[6]==rguid2.Data4[6] && rguid1.Data4[7]==rguid2.Data4[7] ) /* ** HIGH-LEVEL FILE STRUCTURE ** ====================================================================== ** The top-level structure is a series of independent records with ** header and body sections. ** ** ====================================================================== ** Fundamental premise for file format writing: File must be capable of ** being written to incrementally. For this reason, the basic structure ** is a series of independent records. Additional records can be appended ** to the file at any time. ** ** ====================================================================== ** The top-level structure is a series of independent records with ** header and body sections: ** ** +--------------------------------+ ** | Record 0 Header | ** /---+--------------------------------+ ** | | Record 0 Body | ** | +--------------------------------+ ** \-->+--------------------------------+ ** | Record 1 Header | ** /---+--------------------------------+ ** | | Record 1 Body | ** | +--------------------------------+ ** ... ... ** \-->+--------------------------------+ ** | Record n Header | ** +--------------------------------+ ** | Record n Body | ** +--------------------------------+ ** ** ====================================================================== ** Note that each record header has a LINKABS4 -- an absolute offset in ** the file -- to the next record. This allows new records to be inserted ** in the middle of the file, and obsolete records to be deleted. ** ** ====================================================================== ** All references which are defined by the type LINKREL4 are offsets ** within the record body itself -- they are not absolute offsets to the ** entire file. Thus, each record body is independent of the others. Only ** the record header need be modified if a record is moved, deleted, or ** inserted. ** ** ====================================================================== */ /* ** Record header ** ** The header contains a GUID signature (for testing corruptness), ** header size, the size of the record that follows, record tag, and ** fill bytes to make the header 64 bytes in length */ struct c_record_mainheader { GUID guidRecordSignature; // Signature to verify a valid header GUID tagRecordType; // Tag to identify the record type // (This also identifies the first // collection in the record.) SIZE4 sizeHeader; // Size of this header in bytes SIZE4 sizeData; // Size of the body in bytes (record data // that follows header) LINKABS4 linkNextRecord; // Offset to the next record -- absolute // reference within the file. If 0, this // is the last record in the file. UINT4 checksum; // Optional checksum (such as a 32-bit CRC) // of the record body to verify decompression. UINT4 auiReserved[ 4 ]; // Reserved to fill structure to 64 bytes // -- should be filled with 0 }; /* ** RECORD BODY STRUCTURE ** ====================================================================== ** The record body always begins with a Collection element. This is ** defined below in the record structure. ** ** ====================================================================== ** The fundamental premise for the standard structures is to ** assure 4 byte alignment. All of the structures conform to this ** premise. In addition, the data values associated with scalars and ** vectors must be padded out to 4-byte multiples. This _total_ size ** will be specified in the c_collection_element structure (sizeElement). ** ** ====================================================================== ** The three main elements are: ** ** 1. Collection Holds an array of pointers to other elements ** (it could contain another collection) ** 2. Scalar Holds a single data value (of a physical type) ** 3. Vector Holds an array of data values (of a physical type) ** ====================================================================== */ #define ID_ELEMENT_TYPE_COLLECTION 1 #define ID_ELEMENT_TYPE_SCALAR 2 #define ID_ELEMENT_TYPE_VECTOR 3 /* ** The collection element ** ** ... is made by combining a c_collection with an array of ** c_collection_element, which provide pointers to the ** other elements in the collection. */ struct c_collection { SIZE4 count; // The number of elements in this // collection. // c_collection_element ceElements[]; // Array [count] of the elements // in the collection. }; struct c_collection_element { GUID tagElement; // Identifier for this element in the collection. // (4) 1-byte members keep the structure 4-byte aligned. INT1 typeElement; // Type of element (ID_ELEMENT_TYPE_COLLECTION, // _SCALAR or _VECTOR). INT1 typePhysical; // Physical type of the value which follows // (ID_PHYS_TYPE_INTEGER1, etc.). This is unused // if the element is a collection and should be // set to 0. BOOL1 isEmbedded; // FALSE (0) - use the link to find the next element // TRUE (1) - the scalar data value is embedded // (may not be used with vectors) INT1 reserved; // Fill with 0 // The following 8 bytes can point to another location in the record // or it can hold the actual data value (if it fits in 8 bytes). // This allows small scalars to be stored with much less space overhead. union { // isEmbedded What to use // ---------- ------------------------------------------------- // FALSE Use link to find the next element (and its size). // TRUE Use valueEmbedded to find the data directly. struct { LINKREL4 linkElement; // Offset to the element -- this offset // is relative within the record body. SIZE4 sizeElement; // Specifies actual size of the element // -- should be padded to even // multiples of 4 bytes } link; UINT1 valueEmbedded[ 8 ]; // The scalar data value // (less than or equal to 8 bytes) }; }; /* ** The scalar element ** ** This structure has no members, but is included ** for completeness. ** ** struct c_scalar ** { ** // (type) value; // A single value follows of variable length, ** // depending on the physical type. ** }; */ /* ** The vector element */ struct c_vector { SIZE4 count; // (type) values[]; // An array of values [count] follows of // variable length, depending on the // physical type. }; /* ** NOTE ** ====================================================================== ** For more detailed information about how to use these physical ** structures to create a PQDIF file, see the logical structure header ** file -- PQDIF_LG.H */ // Return to previous packing value //#ifdef __BORLANDC__ // #include //#elif _MSC_VER // #pragma pack( pop ) //#else // #pragma pack() //#endif #pragma pack( ) #endif // PQDIF_PH_H