Working on a library: request for code review
Rene Zwanenburg via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu Jun 12 12:30:05 PDT 2014
On Wednesday, 11 June 2014 at 18:29:27 UTC, Mike wrote:
> Here's the link to the repo: http://bit.ly/1mIuGhv
I usually don't trust shortened URL's. Can you please post full
URL's when not constrained by a character limit?
> Any feedback would be great!
First of all, I like your coding style. It's nice and readable :)
https://github.com/emesx/TGA/blob/develop/source/tga/model/utils.d
All those functions can be marked pure. Pure is D is a bit
different than in other languages. I can recommend the following
article as a good explanation:
http://klickverbot.at/blog/2012/05/purity-in-d/
Also, depending on your preference, you may want to put those
functions in a
pure nothrow
{
}
block, or put
pure nothrow:
at the top of the source file. I'm not sure if all those
functions can be nothrow though.
https://github.com/emesx/TGA/blob/develop/source/tga/model/utils.d#L8
These array literals will be allocated every time the function is
called. 'only' can be used instead:
only(16, 32).canFind // etc..
http://dlang.org/library/std/range/only.html
I remember a function which does something like only only +
canFind on one go. It would look something like
header.colorMapDepth.among(16, 32);
but I can't find it right now.. Maybe it was only proposed but
never added.
https://github.com/emesx/TGA/blob/develop/source/tga/model/utils.d#L101
This has a pretty bad time complexity. In the worst case this is
O(n^2), I think. You could use a hashmap to build the table, then
convert to an array. Or even only use hashmaps as color tables
internally to improve performance across the board.
https://github.com/emesx/TGA/blob/develop/source/tga/model/types.d#L11
Depending on your taste, a union + anonymous struct could be used:
struct Pixel
{
union
{
ubyte[4] bytes;
struct
{
ubyte b, g, r, a;
}
}
}
https://github.com/emesx/TGA/blob/develop/source/tga/model/validation.d#L47
to!string is so common it has a special alias: text. It's placed
in std.conv so you still need to import that.
"Invalid color map pixel depth: " ~ header.colorMapDepth.text
https://github.com/emesx/TGA/blob/develop/source/tga/io/readers.d#L24
Yeah, we need something to read an entire struct from a file and
convert it to the correct endianness..
https://github.com/emesx/TGA/blob/develop/source/tga/io/readers.d#L24
https://github.com/emesx/TGA/blob/develop/source/tga/io/readers.d#L91
Unnecessary GC allocation in a hot loop == :(
Make a buffer outside the loop and call the normal rawRead:
auto buffer = new ubyte[colorMapByteDepth];
foreach(i; 0 .. (header.colorMapLength - header.colorMapOffset))
{
file.rawRead(buffer);
colorMap[i] = pixelReader(buffer);
}
Even better, use a static array with the max byte depth, then
slice to the correct length:
ubyte[MaxByteDepth] buffer;
foreach(i; 0 .. (header.colorMapLength - header.colorMapOffset))
{
colorMap[i] = file.rawRead(buffer[0 ..
colorMapByteDepth]).pixelReader;
}
Do the same thing here:
https://github.com/emesx/TGA/blob/develop/source/tga/io/utils.d#L5
T read(T)(File file) if(isNumeric!T){
ubyte[T.sizeof] bytes;
file.rawRead(s[]);
return littleEndianToNative!T(bytes);
}
https://github.com/emesx/TGA/blob/develop/source/tga/io/readers.d#L144
Depending on your taste. The first is built in, the other needs
std.algorithm.
pixel.bytes[] = chunk[];
chunk.copy(pixel.bytes);
https://github.com/emesx/TGA/blob/develop/source/tga/io/utils.d#L40
There's a version in std.algorithm:
http://dlang.org/phobos/std_algorithm.html#min
I need to go. Please don't mind any typo's and untested code ;).
Didn't take a look at writers yet, readers and util need some
more scrutiny, but the main theme is: eliminate unnecessary
temporary GC allocations.
More information about the Digitalmars-d-learn
mailing list