mirror of
https://github.com/xomboverlord/xomb-bare-bones.git
synced 2026-01-11 18:33:15 +01:00
384 lines
8.4 KiB
D
384 lines
8.4 KiB
D
module kernel.core.util;
|
|
|
|
/**
|
|
This method checks to see if the value stored in the bit number declared
|
|
by the input variable "bit" in the flag declared by the input
|
|
variable "flags" is set. Returns a 1 if it is set, returns a 0 if it is not set.
|
|
Params:
|
|
flags = The flags from the multiboot header the kernel wishes to check.
|
|
bit = The number of the bit the kernel would like to check for data.
|
|
Returns: Whether the bit "bit" in "flags" has a value (1 if it is set, 0 if it is not)
|
|
*/
|
|
uint CHECK_FLAG(uint flags, uint bit)
|
|
{
|
|
return ((flags) & (1 << (bit)));
|
|
}
|
|
|
|
/**
|
|
Given a struct type, gives a tuple of strings of the names of fields in the struct.
|
|
*/
|
|
public template FieldNames(S, int idx = 0)
|
|
{
|
|
static if(idx >= S.tupleof.length)
|
|
alias Tuple!() FieldNames;
|
|
else
|
|
alias Tuple!(GetLastName!(S.tupleof[idx].stringof), FieldNames!(S, idx + 1)) FieldNames;
|
|
}
|
|
|
|
private template GetLastName(char[] fullName, int idx = fullName.length - 1)
|
|
{
|
|
static if(idx < 0)
|
|
const char[] GetLastName = fullName;
|
|
else static if(fullName[idx] == '.')
|
|
const char[] GetLastName = fullName[idx + 1 .. $];
|
|
else
|
|
const char[] GetLastName = GetLastName!(fullName, idx - 1);
|
|
}
|
|
|
|
template Tuple(T...)
|
|
{
|
|
alias T Tuple;
|
|
}
|
|
|
|
template Bitfield(alias data, Args...)
|
|
{
|
|
static assert(!(Args.length & 1), "Bitfield arguments must be an even number");
|
|
const char[] Bitfield = BitfieldShim!((typeof(data)).stringof, data, Args).Ret;
|
|
}
|
|
|
|
// Odd bug in D templates -- putting "data.stringof" as a template argument gives it the
|
|
// string of the type, rather than the string of the symbol. This shim works around that.
|
|
template BitfieldShim(char[] typeStr, alias data, Args...)
|
|
{
|
|
const char[] Name = data.stringof;
|
|
const char[] Ret = BitfieldImpl!(typeStr, Name, 0, Args).Ret;
|
|
}
|
|
|
|
template BitfieldImpl(char[] typeStr, char[] nameStr, int offset, Args...)
|
|
{
|
|
static if(Args.length == 0)
|
|
const char[] Ret = "";
|
|
else
|
|
{
|
|
const Name = Args[0];
|
|
const Size = Args[1];
|
|
const Mask = Bitmask!(Size);
|
|
|
|
const char[] Getter = "public " ~ typeStr ~ " " ~ Name ~ "() { return ( " ~
|
|
nameStr ~ " >> " ~ Itoh!(offset) ~ " ) & " ~ Itoh!(Mask) ~ "; }";
|
|
|
|
const char[] Setter = "public void " ~ Name ~ "(" ~ typeStr ~ " val) { " ~
|
|
nameStr ~ " = (" ~ nameStr ~ " & " ~ Itoh!(~(Mask << offset)) ~ ") | ((val & " ~
|
|
Itoh!(Mask) ~ ") << " ~ Itoh!(offset) ~ "); }";
|
|
|
|
const char[] Ret = Getter ~ Setter ~ BitfieldImpl!(typeStr, nameStr, offset + Size, Args[2 .. $]).Ret;
|
|
}
|
|
}
|
|
|
|
template Itoa(long i)
|
|
{
|
|
static if(i < 0)
|
|
const char[] Itoa = "-" ~ IntToStr!(-i, 10);
|
|
else
|
|
const char[] Itoa = IntToStr!(i, 10);
|
|
}
|
|
|
|
template Itoh(long i)
|
|
{
|
|
const char[] Itoh = "0x" ~ IntToStr!(i, 16);
|
|
}
|
|
|
|
template Digits(long i)
|
|
{
|
|
const char[] Digits = "0123456789abcdefghijklmnopqrstuvwxyz"[0 .. i];
|
|
}
|
|
|
|
template IntToStr(ulong i, int base)
|
|
{
|
|
static if(i >= base)
|
|
const char[] IntToStr = IntToStr!(i / base, base) ~ Digits!(base)[i % base];
|
|
else
|
|
const char[] IntToStr = "" ~ Digits!(base)[i % base];
|
|
}
|
|
|
|
template Bitmask(long size)
|
|
{
|
|
const long Bitmask = (1L << size) - 1;
|
|
}
|
|
|
|
template isStringType(T)
|
|
{
|
|
const bool isStringType = is(T : char[]) || is(T : wchar[]) || is(T : dchar[]);
|
|
}
|
|
|
|
/**
|
|
Sees if a type is char, wchar, or dchar.
|
|
*/
|
|
template isCharType(T)
|
|
{
|
|
const bool isCharType = is(T == char) || is(T == wchar) || is(T == dchar);
|
|
}
|
|
|
|
/**
|
|
Sees if a type is a signed or unsigned byte, short, int, or long.
|
|
*/
|
|
template isIntType(T)
|
|
{
|
|
const bool isIntType = is(T == int) || is(T == uint) || is(T == long) || is(T == ulong) ||
|
|
is(T == short) || is(T == ushort) || is(T == byte) || is(T == ubyte) /* || is(T == cent) || is(T == ucent) */;
|
|
}
|
|
|
|
/**
|
|
Sees if a type is a signed or unsigned byte, short, int, or long.
|
|
*/
|
|
template isUnsignedIntType(T)
|
|
{
|
|
const bool isUnsignedIntType = is(T == uint) || is(T == ulong) ||
|
|
is(T == ushort) || is(T == ubyte) /* || is(T == ucent) */;
|
|
}
|
|
|
|
/**
|
|
Sees if a type is a signed or unsigned byte, short, int, or long.
|
|
*/
|
|
template isSignedIntType(T)
|
|
{
|
|
const bool isSignedIntType = is(T == int) || is(T == long) ||
|
|
is(T == short) || is(T == byte) /* || is(T == cent) */;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
Sees if a type is float, double, or real.
|
|
*/
|
|
template isFloatType(T)
|
|
{
|
|
const bool isFloatType = is(T == float) || is(T == double) || is(T == real);
|
|
}
|
|
|
|
/**
|
|
Sees if a type is an array.
|
|
*/
|
|
template isArrayType(T)
|
|
{
|
|
const bool isArrayType = false;
|
|
}
|
|
|
|
template isArrayType(T : T[])
|
|
{
|
|
const bool isArrayType = true;
|
|
}
|
|
|
|
/**
|
|
Sees if a type is an associative array.
|
|
*/
|
|
template isAAType(T)
|
|
{
|
|
const bool isAAType = is(typeof(T.init.values[0])[typeof(T.init.keys[0])] == T);
|
|
}
|
|
|
|
/**
|
|
Sees if a type is a pointer.
|
|
*/
|
|
template isPointerType(T)
|
|
{
|
|
const bool isPointerType = false;
|
|
}
|
|
|
|
template isPointerType(T : T*)
|
|
{
|
|
const bool isPointerType = true;
|
|
}
|
|
|
|
/**
|
|
Get to the bottom of any chain of typedefs! Returns the first non-typedef'ed type.
|
|
*/
|
|
template realType(T)
|
|
{
|
|
static if(is(T Base == typedef) || is(T Base == enum))
|
|
alias realType!(Base) realType;
|
|
else
|
|
alias T realType;
|
|
}
|
|
|
|
/**
|
|
See if a character is a lowercase character.
|
|
*/
|
|
template IsLower(char c)
|
|
{
|
|
const bool IsLower = c >= 'a' && c <= 'z';
|
|
}
|
|
|
|
/**
|
|
See if a character is an uppercase character.
|
|
*/
|
|
template IsUpper(char c)
|
|
{
|
|
const bool IsUpper = c >= 'A' && c <= 'Z';
|
|
}
|
|
|
|
/**
|
|
Convert a character or string to lowercase.
|
|
*/
|
|
template ToLower(char c)
|
|
{
|
|
const char ToLower = IsUpper!(c) ? c + ('a' - 'A') : c;
|
|
}
|
|
|
|
/// ditto
|
|
template ToLower(char[] s)
|
|
{
|
|
static if(s.length == 0)
|
|
const ToLower = ""c;
|
|
else
|
|
const ToLower = ToLower!(s[0]) ~ s[1 .. $];
|
|
}
|
|
|
|
/**
|
|
Convert a character or string to uppercase.
|
|
*/
|
|
template ToUpper(char c)
|
|
{
|
|
const char ToUpper = IsLower!(c) ? c - ('a' - 'A') : c;
|
|
}
|
|
|
|
/// ditto
|
|
template ToUpper(char[] s)
|
|
{
|
|
static if(s.length == 0)
|
|
const ToUpper = ""c;
|
|
else
|
|
const ToUpper = ToUpper!(s[0]) ~ s[1 .. $];
|
|
}
|
|
|
|
/**
|
|
Capitalize a word so that the first letter is capital.
|
|
*/
|
|
template Capitalize(char[] s)
|
|
{
|
|
static if(s.length == 0)
|
|
const char[] Capitalize = ""c;
|
|
else
|
|
const char[] Capitalize = ToUpper!(s[0]) ~ ToLower!(s[1 .. $]);
|
|
}
|
|
|
|
/**
|
|
Compile-time map. Takes a template "function" which should take a single argument
|
|
of the type of the elements of the list of values that follows. Resolves to a tuple.
|
|
*/
|
|
template Map(alias Templ, List...)
|
|
{
|
|
static if(List.length == 0)
|
|
alias Tuple!() Map;
|
|
else
|
|
alias Tuple!(Templ!(List[0]), Map!(Templ, List[1 .. $])) Map;
|
|
}
|
|
|
|
/**
|
|
Compile-time reduce. Takes a template "function" that should take two arguments of the type
|
|
of the elements of the list of values that follows. The list must be at least one element
|
|
long. Resolves to a single value of the type that the template function returns.
|
|
*/
|
|
template Reduce(alias Templ, List...)
|
|
{
|
|
static assert(List.length > 0, "Reduce must be called on a list of at least one element");
|
|
|
|
static if(is(List[0]))
|
|
{
|
|
static if(List.length == 1)
|
|
alias List[0] Reduce;
|
|
else
|
|
alias Reduce!(Templ, Tuple!(Templ!(List[0], List[1]), List[2 .. $])) Reduce;
|
|
}
|
|
else
|
|
{
|
|
static if(List.length == 1)
|
|
const Reduce = List[0];
|
|
else
|
|
const Reduce = Reduce!(Templ, Tuple!(Templ!(List[0], List[1]), List[2 .. $]));
|
|
}
|
|
}
|
|
|
|
/**
|
|
Compile-time range. Given lower and upper bound, yields a tuple of integers in the
|
|
range [min, max).
|
|
*/
|
|
template Range(uint min, uint max)
|
|
{
|
|
static if(min >= max)
|
|
alias Tuple!() Range;
|
|
else
|
|
alias Tuple!(min, Range!(min + 1, max)) Range;
|
|
}
|
|
|
|
/// ditto
|
|
template Range(uint max)
|
|
{
|
|
alias Range!(0, max) Range;
|
|
}
|
|
|
|
/**
|
|
Compile time metafunction meant to be used with Reduce. Concatenates its first two
|
|
arguments and resolves to the result of that concatentation.
|
|
*/
|
|
template Cat(T...)
|
|
{
|
|
const Cat = T[0] ~ T[1];
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// standard functions
|
|
|
|
|
|
/**
|
|
This function converts an integer to a string, depending on the base passed in.
|
|
Params:
|
|
buf = The function will save the translated string into this character array.
|
|
base = The base of the integer value. If "d," it will be assumed to be decimal. If "x," the integer
|
|
will be hexadecimal.
|
|
d = The integer to translate.
|
|
Returns: The translated string in a character array.
|
|
*/
|
|
char[] itoa(char[] buf, char base, long d)
|
|
{
|
|
size_t p = buf.length - 1;
|
|
size_t startIdx = 0;
|
|
ulong ud = d;
|
|
bool negative = false;
|
|
|
|
int divisor = 10;
|
|
|
|
// If %d is specified and D is minus, put `-' in the head.
|
|
if(base == 'd' && d < 0)
|
|
{
|
|
negative = true;
|
|
ud = 0 - d;
|
|
}
|
|
else if(base == 'x')
|
|
divisor = 16;
|
|
|
|
// Divide UD by DIVISOR until UD == 0.
|
|
do
|
|
{
|
|
int remainder = ud % divisor;
|
|
buf[p--] = (remainder < 10) ? remainder + '0' : remainder + 'a' - 10;
|
|
}
|
|
while (ud /= divisor)
|
|
|
|
if(negative)
|
|
buf[p--] = '-';
|
|
|
|
return buf[p + 1 .. $];
|
|
}
|