| Category | Functions |
|---|---|
| Template API | CRC CRC32 CRC64ECMA CRC64ISO |
| OOP API | CRC32Digest CRC64ECMADigest CRC64ISODigest |
| Helpers | crcHexString crc32Of crc64ECMAOf crc64ISOOf |
NoteCRCs are usually printed with the MSB first. When usingstd.digest.toHexString the result will be in an unexpected order. Usestd.digest.toHexString's optional order parameter to specify decreasing order for the correct result. ThecrcHexString alias can also be used for this purpose.
ReferencesWikipedia on CRC
Sourcestd/digest/crc.d
CTFEDigests do not work in CTFE
//Template APIimport std.digest.crc;ubyte[4] hash = crc32Of("The quick brown fox jumps over the lazy dog");writeln(crcHexString(hash));// "414FA339"//Feeding dataubyte[1024] data;CRC32crc;crc.put(data[]);crc.start();//Start againcrc.put(data[]);hash =crc.finish();
//OOP APIimport std.digest.crc;autocrc =new CRC32Digest();ubyte[] hash =crc.digest("The quick brown fox jumps over the lazy dog");assert(crcHexString(hash) =="414FA339");//352441c2//Feeding dataubyte[1024] data;crc.put(data[]);crc.reset();//Start againcrc.put(data[]);hash =crc.finish();
CRC32 = CRC!(32u, 3988292384LU).CRC;CRC64ECMA = CRC!(64u, 14514072000185962306LU).CRC;CRC64ISO = CRC!(64u, 15564440312192434176LU).CRC;CRC(uint N, ulong P) if (N == 32 || N == 64);//Simple example, hashing a string using crc32Of helper functionubyte[4] hash32 = crc32Of("abc");//Let's get a hash stringwriteln(crcHexString(hash32));// "352441C2"// Repeat for CRC64ubyte[8] hash64ecma = crc64ECMAOf("abc");writeln(crcHexString(hash64ecma));// "2CD8094A1A277627"ubyte[8] hash64iso = crc64ISOOf("abc");writeln(crcHexString(hash64iso));// "3776C42000000000"
ubyte[1024] data;//Using the basic APICRC32 hash32;CRC64ECMA hash64ecma;CRC64ISO hash64iso;//Initialize data here...hash32.put(data);ubyte[4] result32 = hash32.finish();hash64ecma.put(data);ubyte[8] result64ecma = hash64ecma.finish();hash64iso.put(data);ubyte[8] result64iso = hash64iso.finish();
//Let's use the template features://Note: When passing a CRC32 to a function, it must be passed by reference!void doSomething(T)(ref T hash)if (isDigest!T){ hash.put(cast(ubyte) 0);}CRC32 crc32;crc32.start();doSomething(crc32);writeln(crcHexString(crc32.finish()));// "D202EF8D"// repeat for CRC64CRC64ECMA crc64ecma;crc64ecma.start();doSomething(crc64ecma);writeln(crcHexString(crc64ecma.finish()));// "1FADA17364673F59"CRC64ISO crc64iso;crc64iso.start();doSomething(crc64iso);writeln(crcHexString(crc64iso.finish()));// "6F90000000000000"
put(scope const(ubyte)[]data...);start();NoteFor this CRC32 Digest implementation calling start after default construction is not necessary. Calling start is only necessary to reset the Digest.
Generic code which deals with different Digest types should always call start though.finish();peek() const;crc32Of(T...)(Tdata);Tdata | InputRange ofElementType implicitly convertible toubyte,ubyte[] orubyte[num] or one or more arrays of any type. |
ubyte[]data = [4,5,7,25];writeln(data.crc32Of);// [167, 180, 199, 131]import std.utf : byChar;writeln("hello"d.byChar.crc32Of);// [134, 166, 16, 54]ubyte[4] hash ="abc".crc32Of();writeln(hash);// digest!CRC32("ab", "c")import std.range : iota;enumubyte S = 5, F = 66;writeln(iota(S, F).crc32Of);// [59, 140, 234, 154]
crc64ECMAOf(T...)(Tdata);Tdata | InputRange ofElementType implicitly convertible toubyte,ubyte[] orubyte[num] or one or more arrays of any type. |
ubyte[]data = [4,5,7,25];writeln(data.crc64ECMAOf);// [58, 142, 220, 214, 118, 98, 105, 69]import std.utf : byChar;writeln("hello"d.byChar.crc64ECMAOf);// [177, 55, 185, 219, 229, 218, 30, 155]ubyte[8] hash ="abc".crc64ECMAOf();writeln("abc".crc64ECMAOf);// [39, 118, 39, 26, 74, 9, 216, 44]writeln(hash);// digest!CRC64ECMA("ab", "c")import std.range : iota;enumubyte S = 5, F = 66;writeln(iota(S, F).crc64ECMAOf);// [6, 184, 91, 238, 46, 213, 127, 188]
crc64ISOOf(T...)(Tdata);Tdata | InputRange ofElementType implicitly convertible toubyte,ubyte[] orubyte[num] or one or more arrays of any type. |
ubyte[]data = [4,5,7,25];writeln(data.crc64ISOOf);// [0, 0, 0, 80, 137, 232, 203, 120]import std.utf : byChar;writeln("hello"d.byChar.crc64ISOOf);// [0, 0, 16, 216, 226, 238, 62, 60]ubyte[8] hash ="abc".crc64ISOOf();writeln("abc".crc64ISOOf);// [0, 0, 0, 0, 32, 196, 118, 55]writeln(hash);// digest!CRC64ISO("ab", "c")import std.range : iota;enumubyte S = 5, F = 66;writeln(iota(S, F).crc64ISOOf);// [21, 185, 116, 95, 219, 11, 54, 7]
crcHexString =crcHexString;crcHexString = std.digest.toHexString!(Order.decreasing, 16LU, LetterCase.upper).toHexString;CRC32Digest = std.digest.WrapperDigest!(CRC!(32u, 3988292384LU)).WrapperDigest;CRC64ECMADigest = std.digest.WrapperDigest!(CRC!(64u, 14514072000185962306LU)).WrapperDigest;CRC64ISODigest = std.digest.WrapperDigest!(CRC!(64u, 15564440312192434176LU)).WrapperDigest;//Simple example, hashing a string using CRC32Digest.digest helper functionauto crc =new CRC32Digest();ubyte[] hash = crc.digest("abc");//Let's get a hash stringwriteln(crcHexString(hash));// "352441C2"
//Let's use the OOP features:void test(Digest dig){ dig.put(cast(ubyte) 0);}auto crc =new CRC32Digest();test(crc);//Let's use a custom buffer:ubyte[4] buf;ubyte[] result = crc.finish(buf[]);writeln(crcHexString(result));// "D202EF8D"
//Simple exampleauto hash =new CRC32Digest();hash.put(cast(ubyte) 0);ubyte[] result = hash.finish();
//using a supplied bufferubyte[4] buf;auto hash =new CRC32Digest();hash.put(cast(ubyte) 0);ubyte[] result = hash.finish(buf[]);//The result is now in result (and in buf. If you pass a buffer which is bigger than//necessary, result will have the correct length, but buf will still have it's original//length)