Vajhoej.Record Namespace

Library for reading and writing binary native structs.

Purpose

It is a library to read and write native structs from and to byte arrays by .NET programs in a way that is natural for .NET.

It's main purpose is to be used by the NISAM library.

Java port

The library is a port of a similar Java library, so an occasional Java'ism may be found.

Getting started

To use the library you need to:

  • create POCO classes that contains all the fields in the native structs
  • put annotations on the class and the fields that tell the library how the data are mapped to the native structs
  • write the code that uses the library and the new POCO classes

Note:

  • the POCO classes should have a no args constructor
  • the library does not care whether you use private fields and public properties or public fields (the first is .NET best practice)
  • all fields except static fields must have attributes defining reading/writing

Examples:

POCO class

    [Struct]
    public class Data
    {
        [StructField(N=0,Type=FieldType.INT4)]
        private int iv;
        [StructField(N=1,Type=FieldType.FP8)]
        private double xv;
        [StructField(N=2,Type=FieldType.FIXSTR,Length=8,Encoding="ISO-8859-1")]
        private String sv;
        public int Iv
        {
            get { return iv; }
            set { iv = value; }
        }
        public double Xv
        {
            get { return xv; }
            set { xv = value; }
        }
        public string Sv
        {
            get { return sv; }
            set { sv = value; }
        }
    }

The class got a [Struct] attribute. Each field in the class got a [StructField] attribute with an element N that determines the order of the fields and an element type that describes the datatype in the native struct plus some optional elements that are needed for some field types.

Code fragments

// read
StructReader sr = new StructReader(somebytearray);
Data obj = sr.Read<Data>(typeof(Data));
// write
Data obj = new Data();
...
StructWriter sw = new StructWriter();
sw.Write(obj);
byte[] ba = sw.GetBytes();

Arrays

To specify a field as an array put an @Array annotation on the field and make the .NET type an array.

Sub structs

To specify a field as a sub struct just specify Type=FieldType.STRUCT in the [StructField] attribute.

Polymorphism

The Record library supports polymorphism in records.

You must use the [Selector] attribute on the last field in the super class.

    [Struct]
    public class SuperData
    {
        [StructField(N=0,Type=FieldType.INT4)]
        private int id;
        [StructField(N=1,Type=FieldType.INT4)]
        [Selector]
        [SubType(Value=1,Type=typeof(DataX))]
        [SubType(Value=2,Type=typeof(DataY))]
        private int typ;
        public int Id
        {
            get { return id; }
            set { id = value; }
        }
        public int Typ
        {
            get { return typ; }
            set { typ = value; }
        }
    }

Usage is as simple as:

Data obj = sr.Read<Data>(typeof(Data));

This will actually read DataX or DataY instances depending on the value of the typ field.

Note that the numbering of the struct fields continue in the sub class - it does not reset to zero.

System requirements

  • .NET 2.0 or newer

License

All the C# code is licensed under the Apache License, Version 2.0.

Author, bug reports etc.

This library is written by Arne Vajhoej (arne@vajhoej.dk).

Bug reports, bug fixes and comments in general are welcome.

Since this is a hobby project, then I can not give any guarantees about timeline for new releases.

Version history:

1.0
Initial release (February 2011).
1.1
More advanced length providers and some new struct types (May 2013).
1.1
Sync up with Java version (April 2017).

Classes

ArrayFieldAttribute Annotation for arrays.
BCDUtil Class TimeUtil converts between bytes with Binary Coded Decimals ant BigDecimal objects.
FieldInfo Class FieldInfo contains information about a native struct field needed for conversions.
RecordException Class RecordException encapsulates exceptions related to record processing.
SelectorAttribute Annotation for selection of sub types.
StructAttribute Annotation for structs.
StructFieldAttribute Annotation for fields.
StructInfo Class StructInfo contains information about a native struct needed for reading and/or writing.
StructInfoCache Class StructInfoCache caches StructInfo objects in a singleton cache.
StructReader Class StructReader reads a .NET object from a byte array containing a native struct.
StructReaderStream Class StructReaderStream reads a .NET object from an input stream containing a native struct.
StructWriter Class StructWriter writes a .NET object to a byte array as a native struct.
SubClassAndPad Class SubClassAndPad contains information about class and padding for select field.
SubTypeAttribute Annotation for sub types.
TimeUtil Class TimeUtil converts between integers in various time formats and DateTime objects.
Util Utility class to process lists and to work with files instead of byte arrays.
Util2 Utility class to process lists and to work with files instead of byte arrays trying to work even with variable length structs.
VAXFloatUtil Class VAXFloatUtil converts between VAX floating point and IEEE floating point.

Delegates

ConvertSelector Converts a selector of any type to a usable integer selector.
ElementsProvider Get number of elements in array. Note: can only be used with struct fields that are arrays.
LengthProvider Get length of field. Note: can only be used with struct fields of field types FIXSTR, FIXSTRNULTERM, PACKEDBCD and ZONEDPBCD.
MaxLengthProvider Get max length of struct. Note: can only be used with struct fields of field types FIXSTR, FIXSTRNULTERM, PACKEDBCD and ZONEDBCD.
UtilObjectHandlerProcessT Process object.
UtilTransformerConvertT1, T2 Convert object.
Util2ObjectHandlerProcessT Process object.
Util2TransformerConvertT1, T2 Convert object.

Enumerations

Alignment Enum Alignment specifies alignment within native struct.
Endian Enum Endian specifies endianess within native struct.
ExtEndian Enum ExtEndian specifies endianess in field within native struct.
FieldType Enum FieldType specifies native struct types.
Semantics:
enum valuedescriptionattributesnative implementation.NET implementation
INT18 bit signed integersbyte
INT216 bit signed integershort
INT432 bit signed integerint
INT864 bit signed integerlong
UINT18 bit unsigned integerbyte
UINT216 bit unsigned integerushort
UINT432 bit unsigned integeruint
FP432 bit IEEE floating pointfloat
FP864 bit IEEE floating pointdouble
INTXlength=<bytes used>bytesulong
FIXSTRFixed length stringlength=<length of string>
encoding=<encoding used>
(default encoding is ISO-8859-1)
sequence of bytesstring
FIXSTRNULTERMFixed length string nul terminatedlength=<length of string>
encoding=<encoding used>
(default encoding is ISO-8859-1)
sequence of bytes with nul bytes added for write and stripped for read string
VARSTRVariable length string with 2 byte length prefixencoding=<encoding used>
(default encoding is ISO-8859-1, max. length is 32767)
2 byte length + sequence of bytesstring
VARFIXSTRVariable length string with 2 byte length prefix and padded to max lengthlength=<length of string>
encoding=<encoding used>
(default encoding is ISO-8859-1, max. length is 32767)
2 byte length + sequence of bytesstring
REMSTRRemaing data stringencoding=<encoding used>
(default encoding is ISO-8859-1, max. length is 32767)
sequence of bytesstring
BOOLEANBoolean (0=false, other=true)length=<bytes used>bytesbool
BITBitslength=<bits used> (max. bits is 32)bytesint
JAVATIMEBinary time in Java format (milliseconds since 1-Jan-1970)64 bit integerSystem.DateTime
UNIXTIMEBinary time in Unix format (seconds since 1-Jan-1970) as 32 bit32 bit integerSystem.DateTime
UNIXTIME64Binary time in Unix format (seconds since 1-Jan-1970) as 64 bit64 bit integerSystem.DateTime
VMSTIMEBinary time in VMS format (100 nanoseconds since 17-Nov-1858)64 bit integerSystem.DateTime
PACKEDBCDPacked BCD (1 byte = 2 decimal digit nibbles)length=<bytes used>
decimals=<number of implied decimals>
(default decimals is 0)
sequence of bytesdecimal
ZONEDBCDZoned BCD (1 byte = 1 zone nibble + 1 decimal digit nibble)length=<bytes used>
decimals=<number of implied decimals>
zone=<zone value>
(default decimals i s0, default zone is EBCDIC)
sequence of bytesdecimal
VAXFP4VAX F floating point32 bit VAX floating pointfloat
VAXFP8VAX G floating point64 bit VAX floating pointdouble
VAXFP8OLDVAX D floating point64 bit VAX floating pointdouble
STRUCTSub struct