Created
July 18, 2017 19:03
-
-
Save UplinkCoder/b3501425a4fb4992c6cf1c77d6c3638a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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