467 lines
15 KiB
C
467 lines
15 KiB
C
/*
|
||
** 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<6E><67>8<EFBFBD><38><EFBFBD>ֽ<EFBFBD>
|
||
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 <poppack.h>
|
||
//#elif _MSC_VER
|
||
// #pragma pack( pop )
|
||
//#else
|
||
// #pragma pack()
|
||
//#endif
|
||
#pragma pack( )
|
||
#endif // PQDIF_PH_H
|