"Fossies" - the Fresh Open Source Software Archive

Member "dmd2/src/phobos/std/digest/crc.d" (20 Nov 2020, 21959 Bytes) of package /linux/misc/dmd.2.094.2.linux.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) D source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 /**
    2 Cyclic Redundancy Check (32-bit) implementation.
    3 
    4 $(SCRIPT inhibitQuickIndex = 1;)
    5 
    6 $(DIVC quickindex,
    7 $(BOOKTABLE ,
    8 $(TR $(TH Category) $(TH Functions)
    9 )
   10 $(TR $(TDNW Template API) $(TD $(MYREF CRC) $(MYREF CRC32) $(MYREF CRC64ECMA) $(MYREF CRC64ISO)
   11 )
   12 )
   13 $(TR $(TDNW OOP API) $(TD $(MYREF CRC32Digest) $(MYREF CRC64ECMADigest) $(MYREF CRC64ISODigest))
   14 )
   15 $(TR $(TDNW Helpers) $(TD $(MYREF crcHexString) $(MYREF crc32Of) $(MYREF crc64ECMAOf) $(MYREF crc64ISOOf))
   16 )
   17 )
   18 )
   19 
   20  *
   21  * This module conforms to the APIs defined in `std.digest`. To understand the
   22  * differences between the template and the OOP API, see $(MREF std, digest).
   23  *
   24  * This module publicly imports $(MREF std, digest) and can be used as a stand-alone
   25  * module.
   26  *
   27  * Note:
   28  * CRCs are usually printed with the MSB first. When using
   29  * $(REF toHexString, std,digest) the result will be in an unexpected
   30  * order. Use $(REF toHexString, std,digest)'s optional order parameter
   31  * to specify decreasing order for the correct result. The $(LREF crcHexString)
   32  * alias can also be used for this purpose.
   33  *
   34  * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
   35  *
   36  * Authors:   Pavel "EvilOne" Minayev, Alex Rønne Petersen, Johannes Pfau
   37  *
   38  * References:
   39  *      $(LINK2 http://en.wikipedia.org/wiki/Cyclic_redundancy_check, Wikipedia on CRC)
   40  *
   41  * Source: $(PHOBOSSRC std/digest/crc.d)
   42  *
   43  * Standards:
   44  * Implements the 'common' IEEE CRC32 variant
   45  * (LSB-first order, Initial value uint.max, complement result)
   46  *
   47  * CTFE:
   48  * Digests do not work in CTFE
   49  */
   50 /*
   51  * Copyright (c) 2001 - 2002
   52  * Pavel "EvilOne" Minayev
   53  * Copyright (c) 2012
   54  * Alex Rønne Petersen
   55  * Distributed under the Boost Software License, Version 1.0.
   56  *    (See accompanying file LICENSE_1_0.txt or copy at
   57  *          http://www.boost.org/LICENSE_1_0.txt)
   58  */
   59 module std.digest.crc;
   60 
   61 public import std.digest;
   62 
   63 ///
   64 @safe unittest
   65 {
   66     //Template API
   67     import std.digest.crc;
   68 
   69     ubyte[4] hash = crc32Of("The quick brown fox jumps over the lazy dog");
   70     assert(crcHexString(hash) == "414FA339");
   71 
   72     //Feeding data
   73     ubyte[1024] data;
   74     CRC32 crc;
   75     crc.put(data[]);
   76     crc.start(); //Start again
   77     crc.put(data[]);
   78     hash = crc.finish();
   79 }
   80 
   81 ///
   82 @safe unittest
   83 {
   84     //OOP API
   85     import std.digest.crc;
   86 
   87     auto crc = new CRC32Digest();
   88     ubyte[] hash = crc.digest("The quick brown fox jumps over the lazy dog");
   89     assert(crcHexString(hash) == "414FA339"); //352441c2
   90 
   91     //Feeding data
   92     ubyte[1024] data;
   93     crc.put(data[]);
   94     crc.reset(); //Start again
   95     crc.put(data[]);
   96     hash = crc.finish();
   97 }
   98 
   99 private T[256][8] genTables(T)(T polynomial)
  100 {
  101     T[256][8] res = void;
  102 
  103     foreach (i; 0 .. 0x100)
  104     {
  105         T crc = i;
  106         foreach (_; 0 .. 8)
  107             crc = (crc >> 1) ^ (-int(crc & 1) & polynomial);
  108         res[0][i] = crc;
  109     }
  110 
  111     foreach (i; 0 .. 0x100)
  112     {
  113         res[1][i] = (res[0][i] >> 8) ^ res[0][res[0][i] & 0xFF];
  114         res[2][i] = (res[1][i] >> 8) ^ res[0][res[1][i] & 0xFF];
  115         res[3][i] = (res[2][i] >> 8) ^ res[0][res[2][i] & 0xFF];
  116         res[4][i] = (res[3][i] >> 8) ^ res[0][res[3][i] & 0xFF];
  117         res[5][i] = (res[4][i] >> 8) ^ res[0][res[4][i] & 0xFF];
  118         res[6][i] = (res[5][i] >> 8) ^ res[0][res[5][i] & 0xFF];
  119         res[7][i] = (res[6][i] >> 8) ^ res[0][res[6][i] & 0xFF];
  120     }
  121     return res;
  122 }
  123 
  124 @system unittest
  125 {
  126     auto tables = genTables(0xEDB88320);
  127     assert(tables[0][0] == 0x00000000 && tables[0][$ - 1] == 0x2d02ef8d && tables[7][$ - 1] == 0x264b06e6);
  128 }
  129 
  130 /**
  131  * Template API CRC32 implementation.
  132  * See `std.digest` for differences between template and OOP API.
  133  */
  134 alias CRC32 = CRC!(32, 0xEDB88320);
  135 
  136 /**
  137  * Template API CRC64-ECMA implementation.
  138  * See `std.digest` for differences between template and OOP API.
  139  */
  140 alias CRC64ECMA = CRC!(64, 0xC96C5795D7870F42);
  141 
  142 /**
  143  * Template API CRC64-ISO implementation.
  144  * See `std.digest` for differences between template and OOP API.
  145  */
  146 alias CRC64ISO = CRC!(64, 0xD800000000000000);
  147 
  148 /**
  149  * Generic Template API used for CRC32 and CRC64 implementations.
  150  *
  151  * The N parameter indicate the size of the hash in bits.
  152  * The parameter P specify the polynomial to be used for reduction.
  153  *
  154  * You may want to use the CRC32, CRC65ECMA and CRC64ISO aliases
  155  * for convenience.
  156  *
  157  * See `std.digest` for differences between template and OOP API.
  158  */
  159 struct CRC(uint N, ulong P)
  160 if (N == 32 || N == 64)
  161 {
  162     private:
  163         static if (N == 32)
  164         {
  165             alias T = uint;
  166         }
  167         else
  168         {
  169             alias T = ulong;
  170         }
  171 
  172         static immutable T[256][8] tables = genTables!T(P);
  173 
  174         /**
  175          * Type of the finished CRC hash.
  176          * ubyte[4] if N is 32, ubyte[8] if N is 64.
  177          */
  178         alias R = ubyte[T.sizeof];
  179 
  180         // magic initialization constants
  181         T _state = T.max;
  182 
  183     public:
  184         /**
  185          * Use this to feed the digest with data.
  186          * Also implements the $(REF isOutputRange, std,range,primitives)
  187          * interface for `ubyte` and `const(ubyte)[]`.
  188          */
  189         void put(scope const(ubyte)[] data...) @trusted pure nothrow @nogc
  190         {
  191             T crc = _state;
  192             // process eight bytes at once
  193             while (data.length >= 8)
  194             {
  195                 // Use byte-wise reads to support architectures without HW support
  196                 // for unaligned reads. This can be optimized by compilers to a single
  197                 // 32-bit read if unaligned reads are supported.
  198                 // DMD is not able to do this optimization though, so explicitly
  199                 // do unaligned reads for DMD's architectures.
  200                 version (X86)
  201                     enum hasLittleEndianUnalignedReads = true;
  202                 else version (X86_64)
  203                     enum hasLittleEndianUnalignedReads = true;
  204                 else
  205                     enum hasLittleEndianUnalignedReads = false; // leave decision to optimizer
  206 
  207                 uint one = void;
  208                 uint two = void;
  209 
  210                 if (!__ctfe && hasLittleEndianUnalignedReads)
  211                 {
  212                     one = (cast(uint*) data.ptr)[0];
  213                     two = (cast(uint*) data.ptr)[1];
  214                 }
  215                 else
  216                 {
  217                     one = (data.ptr[3] << 24 | data.ptr[2] << 16 | data.ptr[1] << 8 | data.ptr[0]);
  218                     two = (data.ptr[7] << 24 | data.ptr[6] << 16 | data.ptr[5] << 8 | data.ptr[4]);
  219                 }
  220 
  221                 static if (N == 32)
  222                 {
  223                     one ^= crc;
  224                 }
  225                 else
  226                 {
  227                     one ^= (crc & 0xffffffff);
  228                     two ^= (crc >> 32);
  229                 }
  230 
  231                 crc =
  232                     tables[0][two >> 24] ^
  233                     tables[1][(two >> 16) & 0xFF] ^
  234                     tables[2][(two >>  8) & 0xFF] ^
  235                     tables[3][two & 0xFF] ^
  236                     tables[4][one >> 24] ^
  237                     tables[5][(one >> 16) & 0xFF] ^
  238                     tables[6][(one >>  8) & 0xFF] ^
  239                     tables[7][one & 0xFF];
  240 
  241                 data = data[8 .. $];
  242             }
  243             // remaining 1 to 7 bytes
  244             foreach (d; data)
  245                 crc = (crc >> 8) ^ tables[0][(crc & 0xFF) ^ d];
  246             _state = crc;
  247         }
  248 
  249         /**
  250          * Used to initialize the CRC32 digest.
  251          *
  252          * Note:
  253          * For this CRC32 Digest implementation calling start after default construction
  254          * is not necessary. Calling start is only necessary to reset the Digest.
  255          *
  256          * Generic code which deals with different Digest types should always call start though.
  257          */
  258         void start() @safe pure nothrow @nogc
  259         {
  260             this = CRC.init;
  261         }
  262 
  263         /**
  264          * Returns the finished CRC hash. This also calls $(LREF start) to
  265          * reset the internal state.
  266          */
  267         R finish() @safe pure nothrow @nogc
  268         {
  269             auto tmp = peek();
  270             start();
  271             return tmp;
  272         }
  273 
  274         /**
  275          * Works like `finish` but does not reset the internal state, so it's possible
  276          * to continue putting data into this CRC after a call to peek.
  277          */
  278         R peek() const @safe pure nothrow @nogc
  279         {
  280             import std.bitmanip : nativeToLittleEndian;
  281             //Complement, LSB first / Little Endian, see http://rosettacode.org/wiki/CRC-32
  282             return nativeToLittleEndian(~_state);
  283         }
  284 }
  285 
  286 @safe unittest
  287 {
  288     // https://issues.dlang.org/show_bug.cgi?id=13471
  289     static ubyte[4] foo(string str)
  290     {
  291         ubyte[4] result = str.crc32Of();
  292         if (result == (ubyte[4]).init)
  293             throw new Exception("this should not be thrown");
  294         return result;
  295     }
  296     enum buggy1 = foo("Hello World!");
  297     enum buggy2 = crc32Of("Hello World!");
  298     assert(buggy1 == buggy2);
  299     assert(buggy1 == "Hello World!".crc32Of());
  300 }
  301 
  302 ///
  303 @safe unittest
  304 {
  305     //Simple example, hashing a string using crc32Of helper function
  306     ubyte[4] hash32 = crc32Of("abc");
  307     //Let's get a hash string
  308     assert(crcHexString(hash32) == "352441C2");
  309     // Repeat for CRC64
  310     ubyte[8] hash64ecma = crc64ECMAOf("abc");
  311     assert(crcHexString(hash64ecma) == "2CD8094A1A277627");
  312     ubyte[8] hash64iso = crc64ISOOf("abc");
  313     assert(crcHexString(hash64iso) == "3776C42000000000");
  314 }
  315 
  316 ///
  317 @safe unittest
  318 {
  319     ubyte[1024] data;
  320     //Using the basic API
  321     CRC32 hash32;
  322     CRC64ECMA hash64ecma;
  323     CRC64ISO hash64iso;
  324     //Initialize data here...
  325     hash32.put(data);
  326     ubyte[4] result32 = hash32.finish();
  327     hash64ecma.put(data);
  328     ubyte[8] result64ecma = hash64ecma.finish();
  329     hash64iso.put(data);
  330     ubyte[8] result64iso = hash64iso.finish();
  331 }
  332 
  333 ///
  334 @safe unittest
  335 {
  336     //Let's use the template features:
  337     //Note: When passing a CRC32 to a function, it must be passed by reference!
  338     void doSomething(T)(ref T hash)
  339     if (isDigest!T)
  340     {
  341       hash.put(cast(ubyte) 0);
  342     }
  343     CRC32 crc32;
  344     crc32.start();
  345     doSomething(crc32);
  346     assert(crcHexString(crc32.finish()) == "D202EF8D");
  347     // repeat for CRC64
  348     CRC64ECMA crc64ecma;
  349     crc64ecma.start();
  350     doSomething(crc64ecma);
  351     assert(crcHexString(crc64ecma.finish()) == "1FADA17364673F59");
  352     CRC64ISO crc64iso;
  353     crc64iso.start();
  354     doSomething(crc64iso);
  355     assert(crcHexString(crc64iso.finish()) == "6F90000000000000");
  356 }
  357 
  358 @safe unittest
  359 {
  360     assert(isDigest!CRC32);
  361     assert(isDigest!CRC64ECMA);
  362     assert(isDigest!CRC64ISO);
  363 }
  364 
  365 @system unittest
  366 {
  367     import std.conv : hexString;
  368     ubyte[4] digest;
  369 
  370     CRC32 crc;
  371     crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
  372     assert(crc.peek() == cast(ubyte[]) hexString!"bd50274c");
  373     crc.start();
  374     crc.put(cast(ubyte[])"");
  375     assert(crc.finish() == cast(ubyte[]) hexString!"00000000");
  376 
  377     digest = crc32Of("");
  378     assert(digest == cast(ubyte[]) hexString!"00000000");
  379 
  380     //Test vector from http://rosettacode.org/wiki/CRC-32
  381     assert(crcHexString(crc32Of("The quick brown fox jumps over the lazy dog")) == "414FA339");
  382 
  383     digest = crc32Of("a");
  384     assert(digest == cast(ubyte[]) hexString!"43beb7e8");
  385 
  386     digest = crc32Of("abc");
  387     assert(digest == cast(ubyte[]) hexString!"c2412435");
  388 
  389     digest = crc32Of("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
  390     assert(digest == cast(ubyte[]) hexString!"5f3f1a17");
  391 
  392     digest = crc32Of("message digest");
  393     assert(digest == cast(ubyte[]) hexString!"7f9d1520");
  394 
  395     digest = crc32Of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
  396     assert(digest == cast(ubyte[]) hexString!"d2e6c21f");
  397 
  398     digest = crc32Of("1234567890123456789012345678901234567890"~
  399                     "1234567890123456789012345678901234567890");
  400     assert(digest == cast(ubyte[]) hexString!"724aa97c");
  401 
  402     enum ubyte[4] input = cast(ubyte[4]) hexString!"c3fcd3d7";
  403     assert(crcHexString(input) == "D7D3FCC3");
  404 }
  405 
  406 @system unittest
  407 {
  408     import std.conv : hexString;
  409     ubyte[8] digest;
  410 
  411     CRC64ECMA crc;
  412     crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
  413     assert(crc.peek() == cast(ubyte[]) hexString!"2f121b7575789626");
  414     crc.start();
  415     crc.put(cast(ubyte[])"");
  416     assert(crc.finish() == cast(ubyte[]) hexString!"0000000000000000");
  417     digest = crc64ECMAOf("");
  418     assert(digest == cast(ubyte[]) hexString!"0000000000000000");
  419 
  420     //Test vector from http://rosettacode.org/wiki/CRC-32
  421     assert(crcHexString(crc64ECMAOf("The quick brown fox jumps over the lazy dog")) == "5B5EB8C2E54AA1C4");
  422 
  423     digest = crc64ECMAOf("a");
  424     assert(digest == cast(ubyte[]) hexString!"052b652e77840233");
  425 
  426     digest = crc64ECMAOf("abc");
  427     assert(digest == cast(ubyte[]) hexString!"2776271a4a09d82c");
  428 
  429     digest = crc64ECMAOf("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
  430     assert(digest == cast(ubyte[]) hexString!"4b7cdce3746c449f");
  431 
  432     digest = crc64ECMAOf("message digest");
  433     assert(digest == cast(ubyte[]) hexString!"6f9b8a3156c9bc5d");
  434 
  435     digest = crc64ECMAOf("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
  436     assert(digest == cast(ubyte[]) hexString!"2656b716e1bf0503");
  437 
  438     digest = crc64ECMAOf("1234567890123456789012345678901234567890"~
  439                          "1234567890123456789012345678901234567890");
  440     assert(digest == cast(ubyte[]) hexString!"bd3eb7765d0a22ae");
  441 
  442     enum ubyte[8] input = cast(ubyte[8]) hexString!"c3fcd3d7efbeadde";
  443     assert(crcHexString(input) == "DEADBEEFD7D3FCC3");
  444 }
  445 
  446 @system unittest
  447 {
  448     import std.conv : hexString;
  449     ubyte[8] digest;
  450 
  451     CRC64ISO crc;
  452     crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
  453     assert(crc.peek() == cast(ubyte[]) hexString!"f0494ab780989b42");
  454     crc.start();
  455     crc.put(cast(ubyte[])"");
  456     assert(crc.finish() == cast(ubyte[]) hexString!"0000000000000000");
  457     digest = crc64ISOOf("");
  458     assert(digest == cast(ubyte[]) hexString!"0000000000000000");
  459 
  460     //Test vector from http://rosettacode.org/wiki/CRC-32
  461     assert(crcHexString(crc64ISOOf("The quick brown fox jumps over the lazy dog")) == "4EF14E19F4C6E28E");
  462 
  463     digest = crc64ISOOf("a");
  464     assert(digest == cast(ubyte[]) hexString!"0000000000002034");
  465 
  466     digest = crc64ISOOf("abc");
  467     assert(digest == cast(ubyte[]) hexString!"0000000020c47637");
  468 
  469     digest = crc64ISOOf("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
  470     assert(digest == cast(ubyte[]) hexString!"5173f717971365e5");
  471 
  472     digest = crc64ISOOf("message digest");
  473     assert(digest == cast(ubyte[]) hexString!"a2c355bbc0b93f86");
  474 
  475     digest = crc64ISOOf("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
  476     assert(digest == cast(ubyte[]) hexString!"598B258292E40084");
  477 
  478     digest = crc64ISOOf("1234567890123456789012345678901234567890"~
  479                         "1234567890123456789012345678901234567890");
  480     assert(digest == cast(ubyte[]) hexString!"760cd2d3588bf809");
  481 
  482     enum ubyte[8] input = cast(ubyte[8]) hexString!"c3fcd3d7efbeadde";
  483     assert(crcHexString(input) == "DEADBEEFD7D3FCC3");
  484 }
  485 
  486 /**
  487  * This is a convenience alias for $(REF digest, std,digest) using the
  488  * CRC32 implementation.
  489  *
  490  * Params:
  491  *      data = `InputRange` of `ElementType` implicitly convertible to
  492  *             `ubyte`, `ubyte[]` or `ubyte[num]` or one or more arrays
  493  *             of any type.
  494  *
  495  * Returns:
  496  *      CRC32 of data
  497  */
  498 //simple alias doesn't work here, hope this gets inlined...
  499 ubyte[4] crc32Of(T...)(T data)
  500 {
  501     return digest!(CRC32, T)(data);
  502 }
  503 
  504 ///
  505 @system unittest
  506 {
  507     ubyte[] data = [4,5,7,25];
  508     assert(data.crc32Of == [167, 180, 199, 131]);
  509 
  510     import std.utf : byChar;
  511     assert("hello"d.byChar.crc32Of == [134, 166, 16, 54]);
  512 
  513     ubyte[4] hash = "abc".crc32Of();
  514     assert(hash == digest!CRC32("ab", "c"));
  515 
  516     import std.range : iota;
  517     enum ubyte S = 5, F = 66;
  518     assert(iota(S, F).crc32Of == [59, 140, 234, 154]);
  519 }
  520 
  521 /**
  522  * This is a convenience alias for $(REF digest, std,digest) using the
  523  * CRC64-ECMA implementation.
  524  *
  525  * Params:
  526  *      data = `InputRange` of `ElementType` implicitly convertible to
  527  *             `ubyte`, `ubyte[]` or `ubyte[num]` or one or more arrays
  528  *             of any type.
  529  *
  530  * Returns:
  531  *      CRC64-ECMA of data
  532  */
  533 //simple alias doesn't work here, hope this gets inlined...
  534 ubyte[8] crc64ECMAOf(T...)(T data)
  535 {
  536     return digest!(CRC64ECMA, T)(data);
  537 }
  538 
  539 ///
  540 @system unittest
  541 {
  542     ubyte[] data = [4,5,7,25];
  543     assert(data.crc64ECMAOf == [58, 142, 220, 214, 118, 98, 105, 69]);
  544 
  545     import std.utf : byChar;
  546     assert("hello"d.byChar.crc64ECMAOf == [177, 55, 185, 219, 229, 218, 30, 155]);
  547 
  548     ubyte[8] hash = "abc".crc64ECMAOf();
  549     assert("abc".crc64ECMAOf == [39, 118, 39, 26, 74, 9, 216, 44]);
  550     assert(hash == digest!CRC64ECMA("ab", "c"));
  551 
  552     import std.range : iota;
  553     enum ubyte S = 5, F = 66;
  554     assert(iota(S, F).crc64ECMAOf == [6, 184, 91, 238, 46, 213, 127, 188]);
  555 }
  556 
  557 /**
  558  * This is a convenience alias for $(REF digest, std,digest,digest) using the
  559  * CRC64-ISO implementation.
  560  *
  561  * Params:
  562  *      data = `InputRange` of `ElementType` implicitly convertible to
  563  *             `ubyte`, `ubyte[]` or `ubyte[num]` or one or more arrays
  564  *             of any type.
  565  *
  566  * Returns:
  567  *      CRC64-ISO of data
  568  */
  569 //simple alias doesn't work here, hope this gets inlined...
  570 ubyte[8] crc64ISOOf(T...)(T data)
  571 {
  572     return digest!(CRC64ISO, T)(data);
  573 }
  574 
  575 ///
  576 @system unittest
  577 {
  578     ubyte[] data = [4,5,7,25];
  579     assert(data.crc64ISOOf == [0, 0, 0, 80, 137, 232, 203, 120]);
  580 
  581     import std.utf : byChar;
  582     assert("hello"d.byChar.crc64ISOOf == [0, 0, 16, 216, 226, 238, 62, 60]);
  583 
  584     ubyte[8] hash = "abc".crc64ISOOf();
  585     assert("abc".crc64ISOOf == [0, 0, 0, 0, 32, 196, 118, 55]);
  586     assert(hash == digest!CRC64ISO("ab", "c"));
  587 
  588     import std.range : iota;
  589     enum ubyte S = 5, F = 66;
  590 
  591     assert(iota(S, F).crc64ISOOf == [21, 185, 116, 95, 219, 11, 54, 7]);
  592 }
  593 
  594 /**
  595  * producing the usual CRC32 string output.
  596  */
  597 public alias crcHexString = toHexString!(Order.decreasing);
  598 ///ditto
  599 public alias crcHexString = toHexString!(Order.decreasing, 16);
  600 
  601 /**
  602  * OOP API CRC32 implementation.
  603  * See `std.digest` for differences between template and OOP API.
  604  *
  605  * This is an alias for $(D $(REF WrapperDigest, std,digest)!CRC32), see
  606  * there for more information.
  607  */
  608 alias CRC32Digest = WrapperDigest!CRC32;
  609 
  610 /**
  611  * OOP API CRC64-ECMA implementation.
  612  * See `std.digest` for differences between template and OOP API.
  613  *
  614  * This is an alias for $(D $(REF WrapperDigest, std,digest,digest)!CRC64ECMA),
  615  * see there for more information.
  616  */
  617 alias CRC64ECMADigest = WrapperDigest!CRC64ECMA;
  618 
  619 /**
  620  * OOP API CRC64-ISO implementation.
  621  * See `std.digest` for differences between template and OOP API.
  622  *
  623  * This is an alias for $(D $(REF WrapperDigest, std,digest,digest)!CRC64ISO),
  624  * see there for more information.
  625  */
  626 alias CRC64ISODigest = WrapperDigest!CRC64ISO;
  627 
  628 ///
  629 @safe unittest
  630 {
  631     //Simple example, hashing a string using Digest.digest helper function
  632     auto crc = new CRC32Digest();
  633     ubyte[] hash = crc.digest("abc");
  634     //Let's get a hash string
  635     assert(crcHexString(hash) == "352441C2");
  636 }
  637 
  638 ///
  639 @system unittest
  640 {
  641      //Let's use the OOP features:
  642     void test(Digest dig)
  643     {
  644       dig.put(cast(ubyte) 0);
  645     }
  646     auto crc = new CRC32Digest();
  647     test(crc);
  648 
  649     //Let's use a custom buffer:
  650     ubyte[4] buf;
  651     ubyte[] result = crc.finish(buf[]);
  652     assert(crcHexString(result) == "D202EF8D");
  653 }
  654 
  655 ///
  656 @safe unittest
  657 {
  658     //Simple example
  659     auto hash = new CRC32Digest();
  660     hash.put(cast(ubyte) 0);
  661     ubyte[] result = hash.finish();
  662 }
  663 
  664 ///
  665 @system unittest
  666 {
  667     //using a supplied buffer
  668     ubyte[4] buf;
  669     auto hash = new CRC32Digest();
  670     hash.put(cast(ubyte) 0);
  671     ubyte[] result = hash.finish(buf[]);
  672     //The result is now in result (and in buf. If you pass a buffer which is bigger than
  673     //necessary, result will have the correct length, but buf will still have it's original
  674     //length)
  675 }
  676 
  677 @system unittest
  678 {
  679     import std.conv : hexString;
  680     import std.range;
  681     import std.exception;
  682 
  683     auto crc = new CRC32Digest();
  684 
  685     crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
  686     assert(crc.peek() == cast(ubyte[]) hexString!"bd50274c");
  687     crc.reset();
  688     crc.put(cast(ubyte[])"");
  689     assert(crc.finish() == cast(ubyte[]) hexString!"00000000");
  690 
  691     crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
  692     ubyte[20] result;
  693     auto result2 = crc.finish(result[]);
  694     assert(result[0 .. 4] == result2 && result2 == cast(ubyte[]) hexString!"bd50274c");
  695 
  696     debug
  697         assertThrown!Error(crc.finish(result[0 .. 3]));
  698 
  699     assert(crc.length == 4);
  700 
  701     assert(crc.digest("") == cast(ubyte[]) hexString!"00000000");
  702 
  703     assert(crc.digest("a") == cast(ubyte[]) hexString!"43beb7e8");
  704 
  705     assert(crc.digest("abc") == cast(ubyte[]) hexString!"c2412435");
  706 
  707     assert(crc.digest("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
  708            == cast(ubyte[]) hexString!"5f3f1a17");
  709 
  710     assert(crc.digest("message digest") == cast(ubyte[]) hexString!"7f9d1520");
  711 
  712     assert(crc.digest("abcdefghijklmnopqrstuvwxyz")
  713            == cast(ubyte[]) hexString!"bd50274c");
  714 
  715     assert(crc.digest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
  716            == cast(ubyte[]) hexString!"d2e6c21f");
  717 
  718     assert(crc.digest("1234567890123456789012345678901234567890",
  719                                    "1234567890123456789012345678901234567890")
  720            == cast(ubyte[]) hexString!"724aa97c");
  721 
  722     ubyte[] onemilliona = new ubyte[1000000];
  723     onemilliona[] = 'a';
  724     auto digest = crc32Of(onemilliona);
  725     assert(digest == cast(ubyte[]) hexString!"BCBF25DC");
  726 
  727     auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
  728     digest = crc32Of(oneMillionRange);
  729     assert(digest == cast(ubyte[]) hexString!"BCBF25DC");
  730 }