Skip to content

Instantly share code, notes, and snippets.

@UplinkCoder
Created July 18, 2017 19:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save UplinkCoder/b3501425a4fb4992c6cf1c77d6c3638a to your computer and use it in GitHub Desktop.
Save UplinkCoder/b3501425a4fb4992c6cf1c77d6c3638a to your computer and use it in GitHub Desktop.
module fastFields;
static public enum Type
{
Bool = "bool",
Ubyte = "ubyte",
Byte = "byte",
Ushort = "ushort",
Short = "short",
Int = "int",
Uint = "uint",
Long = "long",
Ulong = "ulong"
}
uint TypeBitLength(const Type type) pure nothrow @safe
{
final switch(type) with (Type)
{
case Bool :
return 1;
case Byte :
case Ubyte :
return 8;
case Short: case Ushort :
return 16;
case Int : case Uint :
return 32;
case Long : case Ulong :
return 64;
}
}
struct BitFieldDesc
{
Type type;
string fieldName;
uint bitSize;
}
char[2] TwoDigitNumber(uint v) pure nothrow
{
char[2] result = " ";
assert(v <= 99);
if (v >= 10)
{
result[0] = cast(char)('0' + (v / 10));
v %= 10;
}
result[1] = cast(char)('0' + (v));
return result;
}
string bitfieldString(BitFieldDesc[] fieldDescriptors) pure
{
enum indent = " ";
enum indent2 = " ";
enum attribs = "pure nothrow @safe @property ";
string storeName = "";
string result = indent;
{
// deterimine type/size of store and name of store
uint size;
foreach (fd; fieldDescriptors)
{
storeName ~= "_" ~ fd.fieldName;
size += fd.bitSize;
}
switch(size)
{
case 8 :
result ~= "ubyte ";
break;
case 16 :
result ~= "ushort ";
break;
case 32 :
result ~= "uint ";
break;
case 64 :
result ~= "ulong ";
break;
default :
assert(0, "All bitfield-Members must occupy exactly 8, 16, 32 or 64 bit in total");
}
result ~= storeName ~ ";\n\n";
}
uint offset;
foreach (fd; fieldDescriptors)
{
string sizeMask = cast(string)(`((1UL << ` ~ TwoDigitNumber(fd.bitSize) ~ `) -1)`);
string mask = cast(string)(sizeMask ~ ` << ` ~ TwoDigitNumber(offset));
if (TypeBitLength(fd.type) < fd.bitSize)
{
assert(0, fd.fieldName ~ ": cannot hold the required number of bits");
}
// write setter
// TODO FIXME: write overflow and underflow checks
string maxCheck = "1";
string minCheck = "1";
result ~= indent ~ attribs ~ "void " ~ fd.fieldName ~ "(" ~ fd.type ~ " _" ~ fd.fieldName ~ ")\n"
~ indent ~ "{\n"
~ indent2 ~ "assert(" ~ minCheck ~ ", \"number exceeds minimum\");\n"
~ indent2 ~ "assert(" ~ maxCheck ~ ", \"number exceeds maximum\");\n"
~ indent2 ~ storeName ~ " &= ~" ~ mask ~ ";\n"
~ indent2 ~ storeName ~ " |= (cast(ulong)_" ~ fd.fieldName ~ " << " ~ TwoDigitNumber(offset) ~ ");\n"
~ indent ~ "}\n\n";
// write getter
result ~= indent ~ attribs ~ fd.type ~ " " ~ fd.fieldName ~ "()\n"
~ indent ~ "{\n"
~ indent2 ~ "return (" ~ storeName ~ " & " ~ mask ~ ") >> " ~ TwoDigitNumber(offset) ~ ";\n"
~ indent ~ "}\n\n";
offset += fd.bitSize;
}
return result;
}
void main()
{
struct DblRep
{
mixin(bitfieldString([
BitFieldDesc(Type.Ulong, "fraction", 23),
BitFieldDesc(Type.Ushort, "exponent", 8),
BitFieldDesc(Type.Bool, "sign", 1)
]));
}
}
//pragma(msg, bitfieldString([BitFieldDesc(Type.Long, "someName", 3),
// BitFieldDesc(Type.Long, "someName2", 5),]));
//Type Name() { return getter }
//void Name(Type _bla) { setter }
/*
string bitfieldString(string desc)
{
enum Part {Type, Name, bitSize}
enum BitField
string result;
Part part;
string[] Names;
Type[] types
foreach(c;desc)
{
}
}
*/
/*
static immutable = bitfieldString(q{
});
*/
/+
pragma(msg, bitfields!(
ulong, "fraction", 52,
ushort, "exponent", 11,
bool, "sign", 1)
);
+/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment