aboutsummaryrefslogtreecommitdiff
path: root/libphobos/src/std/digest/crc.d
diff options
context:
space:
mode:
authorIain Buclaw <ibuclaw@gcc.gnu.org>2018-10-28 19:51:47 +0000
committerIain Buclaw <ibuclaw@gcc.gnu.org>2018-10-28 19:51:47 +0000
commitb4c522fabd0df7be08882d2207df8b2765026110 (patch)
treeb5ffc312b0a441c1ba24323152aec463fdbe5e9f /libphobos/src/std/digest/crc.d
parent01ce9e31a02c8039d88e90f983735104417bf034 (diff)
downloadgcc-b4c522fabd0df7be08882d2207df8b2765026110.zip
gcc-b4c522fabd0df7be08882d2207df8b2765026110.tar.gz
gcc-b4c522fabd0df7be08882d2207df8b2765026110.tar.bz2
Add D front-end, libphobos library, and D2 testsuite.
ChangeLog: * Makefile.def (target_modules): Add libphobos. (flags_to_pass): Add GDC, GDCFLAGS, GDC_FOR_TARGET and GDCFLAGS_FOR_TARGET. (dependencies): Make libphobos depend on libatomic, libbacktrace configure, and zlib configure. (language): Add language d. * Makefile.in: Rebuild. * Makefile.tpl (BUILD_EXPORTS): Add GDC and GDCFLAGS. (HOST_EXPORTS): Add GDC. (POSTSTAGE1_HOST_EXPORTS): Add GDC and GDC_FOR_BUILD. (BASE_TARGET_EXPORTS): Add GDC. (GDC_FOR_BUILD, GDC, GDCFLAGS): New variables. (GDC_FOR_TARGET, GDC_FLAGS_FOR_TARGET): New variables. (EXTRA_HOST_FLAGS): Add GDC. (STAGE1_FLAGS_TO_PASS): Add GDC. (EXTRA_TARGET_FLAGS): Add GDC and GDCFLAGS. * config-ml.in: Treat GDC and GDCFLAGS like other compiler/flag environment variables. * configure: Rebuild. * configure.ac: Add target-libphobos to target_libraries. Set and substitute GDC_FOR_BUILD and GDC_FOR_TARGET. config/ChangeLog: * multi.m4: Set GDC. gcc/ChangeLog: * Makefile.in (tm_d_file_list, tm_d_include_list): New variables. (TM_D_H, D_TARGET_DEF, D_TARGET_H, D_TARGET_OBJS): New variables. (tm_d.h, cs-tm_d.h, default-d.o): New rules. (d/d-target-hooks-def.h, s-d-target-hooks-def-h): New rules. (s-tm-texi): Also check timestamp on d-target.def. (generated_files): Add TM_D_H and d-target-hooks-def.h. (build/genhooks.o): Also depend on D_TARGET_DEF. * config.gcc (tm_d_file, d_target_objs, target_has_targetdm): New variables. * config/aarch64/aarch64-d.c: New file. * config/aarch64/aarch64-linux.h (GNU_USER_TARGET_D_CRITSEC_SIZE): Define. * config/aarch64/aarch64-protos.h (aarch64_d_target_versions): New prototype. * config/aarch64/aarch64.h (TARGET_D_CPU_VERSIONS): Define. * config/aarch64/t-aarch64 (aarch64-d.o): New rule. * config/arm/arm-d.c: New file. * config/arm/arm-protos.h (arm_d_target_versions): New prototype. * config/arm/arm.h (TARGET_D_CPU_VERSIONS): Define. * config/arm/linux-eabi.h (EXTRA_TARGET_D_OS_VERSIONS): Define. * config/arm/t-arm (arm-d.o): New rule. * config/default-d.c: New file. * config/glibc-d.c: New file. * config/gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/i386/i386-d.c: New file. * config/i386/i386-protos.h (ix86_d_target_versions): New prototype. * config/i386/i386.h (TARGET_D_CPU_VERSIONS): Define. * config/i386/linux-common.h (EXTRA_TARGET_D_OS_VERSIONS): Define. (GNU_USER_TARGET_D_CRITSEC_SIZE): Define. * config/i386/t-i386 (i386-d.o): New rule. * config/kfreebsd-gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/kopensolaris-gnu.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/linux-android.h (ANDROID_TARGET_D_OS_VERSIONS): Define. * config/linux.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/mips/linux-common.h (EXTRA_TARGET_D_OS_VERSIONS): Define. * config/mips/mips-d.c: New file. * config/mips/mips-protos.h (mips_d_target_versions): New prototype. * config/mips/mips.h (TARGET_D_CPU_VERSIONS): Define. * config/mips/t-mips (mips-d.o): New rule. * config/powerpcspe/linux.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/powerpcspe/linux64.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/powerpcspe/powerpcspe-d.c: New file. * config/powerpcspe/powerpcspe-protos.h (rs6000_d_target_versions): New prototype. * config/powerpcspe/powerpcspe.c (rs6000_output_function_epilogue): Support GNU D by using 0 as the language type. * config/powerpcspe/powerpcspe.h (TARGET_D_CPU_VERSIONS): Define. * config/powerpcspe/t-powerpcspe (powerpcspe-d.o): New rule. * config/riscv/riscv-d.c: New file. * config/riscv/riscv-protos.h (riscv_d_target_versions): New prototype. * config/riscv/riscv.h (TARGET_D_CPU_VERSIONS): Define. * config/riscv/t-riscv (riscv-d.o): New rule. * config/rs6000/linux.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/rs6000/linux64.h (GNU_USER_TARGET_D_OS_VERSIONS): Define. * config/rs6000/rs6000-d.c: New file. * config/rs6000/rs6000-protos.h (rs6000_d_target_versions): New prototype. * config/rs6000/rs6000.c (rs6000_output_function_epilogue): Support GNU D by using 0 as the language type. * config/rs6000/rs6000.h (TARGET_D_CPU_VERSIONS): Define. * config/rs6000/t-rs6000 (rs6000-d.o): New rule. * config/s390/s390-d.c: New file. * config/s390/s390-protos.h (s390_d_target_versions): New prototype. * config/s390/s390.h (TARGET_D_CPU_VERSIONS): Define. * config/s390/t-s390 (s390-d.o): New rule. * config/sparc/sparc-d.c: New file. * config/sparc/sparc-protos.h (sparc_d_target_versions): New prototype. * config/sparc/sparc.h (TARGET_D_CPU_VERSIONS): Define. * config/sparc/t-sparc (sparc-d.o): New rule. * config/t-glibc (glibc-d.o): New rule. * configure: Regenerated. * configure.ac (tm_d_file): New variable. (tm_d_file_list, tm_d_include_list, d_target_objs): Add substitutes. * doc/contrib.texi (Contributors): Add self for the D frontend. * doc/frontends.texi (G++ and GCC): Mention D as a supported language. * doc/install.texi (Configuration): Mention libphobos as an option for --enable-shared. Mention d as an option for --enable-languages. (Testing): Mention check-d as a target. * doc/invoke.texi (Overall Options): Mention .d, .dd, and .di as file name suffixes. Mention d as a -x option. * doc/sourcebuild.texi (Top Level): Mention libphobos. * doc/standards.texi (Standards): Add section on D language. * doc/tm.texi: Regenerated. * doc/tm.texi.in: Add @node for D language and ABI, and @hook for TARGET_CPU_VERSIONS, TARGET_D_OS_VERSIONS, and TARGET_D_CRITSEC_SIZE. * dwarf2out.c (is_dlang): New function. (gen_compile_unit_die): Use DW_LANG_D for D. (declare_in_namespace): Return module die for D, instead of adding extra declarations into the namespace. (gen_namespace_die): Generate DW_TAG_module for D. (gen_decl_die): Handle CONST_DECLSs for D. (dwarf2out_decl): Likewise. (prune_unused_types_walk_local_classes): Handle DW_tag_interface_type. (prune_unused_types_walk): Handle DW_tag_interface_type same as other kinds of aggregates. * gcc.c (default_compilers): Add entries for .d, .dd and .di. * genhooks.c: Include d/d-target.def. gcc/po/ChangeLog: * EXCLUDES: Add sources from d/dmd. gcc/testsuite/ChangeLog: * gcc.misc-tests/help.exp: Add D to option descriptions check. * gdc.dg/asan/asan.exp: New file. * gdc.dg/asan/gdc272.d: New test. * gdc.dg/compilable.d: New test. * gdc.dg/dg.exp: New file. * gdc.dg/gdc254.d: New test. * gdc.dg/gdc260.d: New test. * gdc.dg/gdc270a.d: New test. * gdc.dg/gdc270b.d: New test. * gdc.dg/gdc282.d: New test. * gdc.dg/gdc283.d: New test. * gdc.dg/imports/gdc170.d: New test. * gdc.dg/imports/gdc231.d: New test. * gdc.dg/imports/gdc239.d: New test. * gdc.dg/imports/gdc241a.d: New test. * gdc.dg/imports/gdc241b.d: New test. * gdc.dg/imports/gdc251a.d: New test. * gdc.dg/imports/gdc251b.d: New test. * gdc.dg/imports/gdc253.d: New test. * gdc.dg/imports/gdc254a.d: New test. * gdc.dg/imports/gdc256.d: New test. * gdc.dg/imports/gdc27.d: New test. * gdc.dg/imports/gdcpkg256/package.d: New test. * gdc.dg/imports/runnable.d: New test. * gdc.dg/link.d: New test. * gdc.dg/lto/lto.exp: New file. * gdc.dg/lto/ltotests_0.d: New test. * gdc.dg/lto/ltotests_1.d: New test. * gdc.dg/runnable.d: New test. * gdc.dg/simd.d: New test. * gdc.test/gdc-test.exp: New file. * lib/gdc-dg.exp: New file. * lib/gdc.exp: New file. libphobos/ChangeLog: * Makefile.am: New file. * Makefile.in: New file. * acinclude.m4: New file. * aclocal.m4: New file. * config.h.in: New file. * configure: New file. * configure.ac: New file. * d_rules.am: New file. * libdruntime/Makefile.am: New file. * libdruntime/Makefile.in: New file. * libdruntime/__entrypoint.di: New file. * libdruntime/__main.di: New file. * libdruntime/gcc/attribute.d: New file. * libdruntime/gcc/backtrace.d: New file. * libdruntime/gcc/builtins.d: New file. * libdruntime/gcc/config.d.in: New file. * libdruntime/gcc/deh.d: New file. * libdruntime/gcc/libbacktrace.d.in: New file. * libdruntime/gcc/unwind/arm.d: New file. * libdruntime/gcc/unwind/arm_common.d: New file. * libdruntime/gcc/unwind/c6x.d: New file. * libdruntime/gcc/unwind/generic.d: New file. * libdruntime/gcc/unwind/package.d: New file. * libdruntime/gcc/unwind/pe.d: New file. * m4/autoconf.m4: New file. * m4/druntime.m4: New file. * m4/druntime/cpu.m4: New file. * m4/druntime/libraries.m4: New file. * m4/druntime/os.m4: New file. * m4/gcc_support.m4: New file. * m4/gdc.m4: New file. * m4/libtool.m4: New file. * src/Makefile.am: New file. * src/Makefile.in: New file. * src/libgphobos.spec.in: New file. * testsuite/Makefile.am: New file. * testsuite/Makefile.in: New file. * testsuite/config/default.exp: New file. * testsuite/lib/libphobos-dg.exp: New file. * testsuite/lib/libphobos.exp: New file. * testsuite/testsuite_flags.in: New file. From-SVN: r265573
Diffstat (limited to 'libphobos/src/std/digest/crc.d')
-rw-r--r--libphobos/src/std/digest/crc.d705
1 files changed, 705 insertions, 0 deletions
diff --git a/libphobos/src/std/digest/crc.d b/libphobos/src/std/digest/crc.d
new file mode 100644
index 0000000..c606f4c
--- /dev/null
+++ b/libphobos/src/std/digest/crc.d
@@ -0,0 +1,705 @@
+/**
+Cyclic Redundancy Check (32-bit) implementation.
+
+$(SCRIPT inhibitQuickIndex = 1;)
+
+$(DIVC quickindex,
+$(BOOKTABLE ,
+$(TR $(TH Category) $(TH Functions)
+)
+$(TR $(TDNW Template API) $(TD $(MYREF CRC) $(MYREF CRC32) $(MYREF CRC64ECMA) $(MYREF CRC64ISO)
+)
+)
+$(TR $(TDNW OOP API) $(TD $(MYREF CRC32Digest) $(MYREF CRC64ECMADigest) $(MYREF CRC64ISODigest))
+)
+$(TR $(TDNW Helpers) $(TD $(MYREF crcHexString) $(MYREF crc32Of) $(MYREF crc64ECMAOf) $(MYREF crc64ISOOf))
+)
+)
+)
+
+ *
+ * This module conforms to the APIs defined in $(D std.digest). To understand the
+ * differences between the template and the OOP API, see $(MREF std, digest).
+ *
+ * This module publicly imports $(MREF std, digest) and can be used as a stand-alone
+ * module.
+ *
+ * Note:
+ * CRCs are usually printed with the MSB first. When using
+ * $(REF toHexString, std,digest) the result will be in an unexpected
+ * order. Use $(REF toHexString, std,digest)'s optional order parameter
+ * to specify decreasing order for the correct result. The $(LREF crcHexString)
+ * alias can also be used for this purpose.
+ *
+ * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
+ *
+ * Authors: Pavel "EvilOne" Minayev, Alex Rønne Petersen, Johannes Pfau
+ *
+ * References:
+ * $(LINK2 http://en.wikipedia.org/wiki/Cyclic_redundancy_check, Wikipedia on CRC)
+ *
+ * Source: $(PHOBOSSRC std/digest/_crc.d)
+ *
+ * Standards:
+ * Implements the 'common' IEEE CRC32 variant
+ * (LSB-first order, Initial value uint.max, complement result)
+ *
+ * CTFE:
+ * Digests do not work in CTFE
+ */
+/*
+ * Copyright (c) 2001 - 2002
+ * Pavel "EvilOne" Minayev
+ * Copyright (c) 2012
+ * Alex Rønne Petersen
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ */
+module std.digest.crc;
+
+public import std.digest;
+
+version (unittest)
+ import std.exception;
+
+
+///
+@safe unittest
+{
+ //Template API
+ import std.digest.crc;
+
+ ubyte[4] hash = crc32Of("The quick brown fox jumps over the lazy dog");
+ assert(crcHexString(hash) == "414FA339");
+
+ //Feeding data
+ ubyte[1024] data;
+ CRC32 crc;
+ crc.put(data[]);
+ crc.start(); //Start again
+ crc.put(data[]);
+ hash = crc.finish();
+}
+
+///
+@safe unittest
+{
+ //OOP API
+ import std.digest.crc;
+
+ auto crc = new CRC32Digest();
+ ubyte[] hash = crc.digest("The quick brown fox jumps over the lazy dog");
+ assert(crcHexString(hash) == "414FA339"); //352441c2
+
+ //Feeding data
+ ubyte[1024] data;
+ crc.put(data[]);
+ crc.reset(); //Start again
+ crc.put(data[]);
+ hash = crc.finish();
+}
+
+private T[256][8] genTables(T)(T polynomial)
+{
+ T[256][8] res = void;
+
+ foreach (i; 0 .. 0x100)
+ {
+ T crc = i;
+ foreach (_; 0 .. 8)
+ crc = (crc >> 1) ^ (-int(crc & 1) & polynomial);
+ res[0][i] = crc;
+ }
+
+ foreach (i; 0 .. 0x100)
+ {
+ res[1][i] = (res[0][i] >> 8) ^ res[0][res[0][i] & 0xFF];
+ res[2][i] = (res[1][i] >> 8) ^ res[0][res[1][i] & 0xFF];
+ res[3][i] = (res[2][i] >> 8) ^ res[0][res[2][i] & 0xFF];
+ res[4][i] = (res[3][i] >> 8) ^ res[0][res[3][i] & 0xFF];
+ res[5][i] = (res[4][i] >> 8) ^ res[0][res[4][i] & 0xFF];
+ res[6][i] = (res[5][i] >> 8) ^ res[0][res[5][i] & 0xFF];
+ res[7][i] = (res[6][i] >> 8) ^ res[0][res[6][i] & 0xFF];
+ }
+ return res;
+}
+
+@system unittest
+{
+ auto tables = genTables(0xEDB88320);
+ assert(tables[0][0] == 0x00000000 && tables[0][$ - 1] == 0x2d02ef8d && tables[7][$ - 1] == 0x264b06e6);
+}
+
+/**
+ * Template API CRC32 implementation.
+ * See $(D std.digest) for differences between template and OOP API.
+ */
+alias CRC32 = CRC!(32, 0xEDB88320);
+
+/**
+ * Template API CRC64-ECMA implementation.
+ * See $(D std.digest.digest) for differences between template and OOP API.
+ */
+alias CRC64ECMA = CRC!(64, 0xC96C5795D7870F42);
+
+/**
+ * Template API CRC64-ISO implementation.
+ * See $(D std.digest.digest) for differences between template and OOP API.
+ */
+alias CRC64ISO = CRC!(64, 0xD800000000000000);
+
+/**
+ * Generic Template API used for CRC32 and CRC64 implementations.
+ *
+ * The N parameter indicate the size of the hash in bits.
+ * The parameter P specify the polynomial to be used for reduction.
+ *
+ * You may want to use the CRC32, CRC65ECMA and CRC64ISO aliases
+ * for convenience.
+ *
+ * See $(D std.digest.digest) for differences between template and OOP API.
+ */
+struct CRC(uint N, ulong P) if (N == 32 || N == 64)
+{
+ private:
+ static if (N == 32)
+ {
+ alias T = uint;
+ }
+ else
+ {
+ alias T = ulong;
+ }
+
+ static immutable T[256][8] tables = genTables!T(P);
+
+ /**
+ * Type of the finished CRC hash.
+ * ubyte[4] if N is 32, ubyte[8] if N is 64.
+ */
+ alias R = ubyte[T.sizeof];
+
+ // magic initialization constants
+ T _state = T.max;
+
+ public:
+ /**
+ * Use this to feed the digest with data.
+ * Also implements the $(REF isOutputRange, std,range,primitives)
+ * interface for $(D ubyte) and $(D const(ubyte)[]).
+ */
+ void put(scope const(ubyte)[] data...) @trusted pure nothrow @nogc
+ {
+ T crc = _state;
+ // process eight bytes at once
+ while (data.length >= 8)
+ {
+ // Use byte-wise reads to support architectures without HW support
+ // for unaligned reads. This can be optimized by compilers to a single
+ // 32-bit read if unaligned reads are supported.
+ // DMD is not able to do this optimization though, so explicitly
+ // do unaligned reads for DMD's architectures.
+ version (X86)
+ enum hasLittleEndianUnalignedReads = true;
+ else version (X86_64)
+ enum hasLittleEndianUnalignedReads = true;
+ else
+ enum hasLittleEndianUnalignedReads = false; // leave decision to optimizer
+ static if (hasLittleEndianUnalignedReads)
+ {
+ uint one = (cast(uint*) data.ptr)[0];
+ uint two = (cast(uint*) data.ptr)[1];
+ }
+ else
+ {
+ uint one = (data.ptr[3] << 24 | data.ptr[2] << 16 | data.ptr[1] << 8 | data.ptr[0]);
+ uint two = (data.ptr[7] << 24 | data.ptr[6] << 16 | data.ptr[5] << 8 | data.ptr[4]);
+ }
+
+ static if (N == 32)
+ {
+ one ^= crc;
+ }
+ else
+ {
+ one ^= (crc & 0xffffffff);
+ two ^= (crc >> 32);
+ }
+
+ crc =
+ tables[0][two >> 24] ^
+ tables[1][(two >> 16) & 0xFF] ^
+ tables[2][(two >> 8) & 0xFF] ^
+ tables[3][two & 0xFF] ^
+ tables[4][one >> 24] ^
+ tables[5][(one >> 16) & 0xFF] ^
+ tables[6][(one >> 8) & 0xFF] ^
+ tables[7][one & 0xFF];
+
+ data = data[8 .. $];
+ }
+ // remaining 1 to 7 bytes
+ foreach (d; data)
+ crc = (crc >> 8) ^ tables[0][(crc & 0xFF) ^ d];
+ _state = crc;
+ }
+
+ /**
+ * Used to initialize the CRC32 digest.
+ *
+ * Note:
+ * For 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.
+ */
+ void start() @safe pure nothrow @nogc
+ {
+ this = CRC.init;
+ }
+
+ /**
+ * Returns the finished CRC hash. This also calls $(LREF start) to
+ * reset the internal state.
+ */
+ R finish() @safe pure nothrow @nogc
+ {
+ auto tmp = peek();
+ start();
+ return tmp;
+ }
+
+ /**
+ * Works like $(D finish) but does not reset the internal state, so it's possible
+ * to continue putting data into this CRC after a call to peek.
+ */
+ R peek() const @safe pure nothrow @nogc
+ {
+ import std.bitmanip : nativeToLittleEndian;
+ //Complement, LSB first / Little Endian, see http://rosettacode.org/wiki/CRC-32
+ return nativeToLittleEndian(~_state);
+ }
+}
+
+///
+@safe unittest
+{
+ //Simple example, hashing a string using crc32Of helper function
+ ubyte[4] hash32 = crc32Of("abc");
+ //Let's get a hash string
+ assert(crcHexString(hash32) == "352441C2");
+ // Repeat for CRC64
+ ubyte[8] hash64ecma = crc64ECMAOf("abc");
+ assert(crcHexString(hash64ecma) == "2CD8094A1A277627");
+ ubyte[8] hash64iso = crc64ISOOf("abc");
+ assert(crcHexString(hash64iso) == "3776C42000000000");
+}
+
+///
+@safe unittest
+{
+ ubyte[1024] data;
+ //Using the basic API
+ CRC32 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();
+}
+
+///
+@safe unittest
+{
+ //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);
+ assert(crcHexString(crc32.finish()) == "D202EF8D");
+ // repeat for CRC64
+ CRC64ECMA crc64ecma;
+ crc64ecma.start();
+ doSomething(crc64ecma);
+ assert(crcHexString(crc64ecma.finish()) == "1FADA17364673F59");
+ CRC64ISO crc64iso;
+ crc64iso.start();
+ doSomething(crc64iso);
+ assert(crcHexString(crc64iso.finish()) == "6F90000000000000");
+}
+
+@safe unittest
+{
+ assert(isDigest!CRC32);
+ assert(isDigest!CRC64ECMA);
+ assert(isDigest!CRC64ISO);
+}
+
+@system unittest
+{
+ ubyte[4] digest;
+
+ CRC32 crc;
+ crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
+ assert(crc.peek() == cast(ubyte[]) x"bd50274c");
+ crc.start();
+ crc.put(cast(ubyte[])"");
+ assert(crc.finish() == cast(ubyte[]) x"00000000");
+
+ digest = crc32Of("");
+ assert(digest == cast(ubyte[]) x"00000000");
+
+ //Test vector from http://rosettacode.org/wiki/CRC-32
+ assert(crcHexString(crc32Of("The quick brown fox jumps over the lazy dog")) == "414FA339");
+
+ digest = crc32Of("a");
+ assert(digest == cast(ubyte[]) x"43beb7e8");
+
+ digest = crc32Of("abc");
+ assert(digest == cast(ubyte[]) x"c2412435");
+
+ digest = crc32Of("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
+ assert(digest == cast(ubyte[]) x"5f3f1a17");
+
+ digest = crc32Of("message digest");
+ assert(digest == cast(ubyte[]) x"7f9d1520");
+
+ digest = crc32Of("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ assert(digest == cast(ubyte[]) x"d2e6c21f");
+
+ digest = crc32Of("1234567890123456789012345678901234567890"~
+ "1234567890123456789012345678901234567890");
+ assert(digest == cast(ubyte[]) x"724aa97c");
+
+ assert(crcHexString(cast(ubyte[4]) x"c3fcd3d7") == "D7D3FCC3");
+}
+
+@system unittest
+{
+ ubyte[8] digest;
+
+ CRC64ECMA crc;
+ crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
+ assert(crc.peek() == cast(ubyte[]) x"2f121b7575789626");
+ crc.start();
+ crc.put(cast(ubyte[])"");
+ assert(crc.finish() == cast(ubyte[]) x"0000000000000000");
+ digest = crc64ECMAOf("");
+ assert(digest == cast(ubyte[]) x"0000000000000000");
+
+ //Test vector from http://rosettacode.org/wiki/CRC-32
+ assert(crcHexString(crc64ECMAOf("The quick brown fox jumps over the lazy dog")) == "5B5EB8C2E54AA1C4");
+
+ digest = crc64ECMAOf("a");
+ assert(digest == cast(ubyte[]) x"052b652e77840233");
+
+ digest = crc64ECMAOf("abc");
+ assert(digest == cast(ubyte[]) x"2776271a4a09d82c");
+
+ digest = crc64ECMAOf("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
+ assert(digest == cast(ubyte[]) x"4b7cdce3746c449f");
+
+ digest = crc64ECMAOf("message digest");
+ assert(digest == cast(ubyte[]) x"6f9b8a3156c9bc5d");
+
+ digest = crc64ECMAOf("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ assert(digest == cast(ubyte[]) x"2656b716e1bf0503");
+
+ digest = crc64ECMAOf("1234567890123456789012345678901234567890"~
+ "1234567890123456789012345678901234567890");
+ assert(digest == cast(ubyte[]) x"bd3eb7765d0a22ae");
+
+ assert(crcHexString(cast(ubyte[8]) x"c3fcd3d7efbeadde") == "DEADBEEFD7D3FCC3");
+}
+
+@system unittest
+{
+ ubyte[8] digest;
+
+ CRC64ISO crc;
+ crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
+ assert(crc.peek() == cast(ubyte[]) x"f0494ab780989b42");
+ crc.start();
+ crc.put(cast(ubyte[])"");
+ assert(crc.finish() == cast(ubyte[]) x"0000000000000000");
+ digest = crc64ISOOf("");
+ assert(digest == cast(ubyte[]) x"0000000000000000");
+
+ //Test vector from http://rosettacode.org/wiki/CRC-32
+ assert(crcHexString(crc64ISOOf("The quick brown fox jumps over the lazy dog")) == "4EF14E19F4C6E28E");
+
+ digest = crc64ISOOf("a");
+ assert(digest == cast(ubyte[]) x"0000000000002034");
+
+ digest = crc64ISOOf("abc");
+ assert(digest == cast(ubyte[]) x"0000000020c47637");
+
+ digest = crc64ISOOf("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
+ assert(digest == cast(ubyte[]) x"5173f717971365e5");
+
+ digest = crc64ISOOf("message digest");
+ assert(digest == cast(ubyte[]) x"a2c355bbc0b93f86");
+
+ digest = crc64ISOOf("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
+ assert(digest == cast(ubyte[]) x"598B258292E40084");
+
+ digest = crc64ISOOf("1234567890123456789012345678901234567890"~
+ "1234567890123456789012345678901234567890");
+ assert(digest == cast(ubyte[]) x"760cd2d3588bf809");
+
+ assert(crcHexString(cast(ubyte[8]) x"c3fcd3d7efbeadde") == "DEADBEEFD7D3FCC3");
+}
+
+/**
+ * This is a convenience alias for $(REF digest, std,digest) using the
+ * CRC32 implementation.
+ *
+ * Params:
+ * data = $(D InputRange) of $(D ElementType) implicitly convertible to
+ * $(D ubyte), $(D ubyte[]) or $(D ubyte[num]) or one or more arrays
+ * of any type.
+ *
+ * Returns:
+ * CRC32 of data
+ */
+//simple alias doesn't work here, hope this gets inlined...
+ubyte[4] crc32Of(T...)(T data)
+{
+ return digest!(CRC32, T)(data);
+}
+
+///
+@system unittest
+{
+ ubyte[] data = [4,5,7,25];
+ assert(data.crc32Of == [167, 180, 199, 131]);
+
+ import std.utf : byChar;
+ assert("hello"d.byChar.crc32Of == [134, 166, 16, 54]);
+
+ ubyte[4] hash = "abc".crc32Of();
+ assert(hash == digest!CRC32("ab", "c"));
+
+ import std.range : iota;
+ enum ubyte S = 5, F = 66;
+ assert(iota(S, F).crc32Of == [59, 140, 234, 154]);
+}
+
+/**
+ * This is a convenience alias for $(REF digest, std,digest) using the
+ * CRC64-ECMA implementation.
+ *
+ * Params:
+ * data = $(D InputRange) of $(D ElementType) implicitly convertible to
+ * $(D ubyte), $(D ubyte[]) or $(D ubyte[num]) or one or more arrays
+ * of any type.
+ *
+ * Returns:
+ * CRC64-ECMA of data
+ */
+//simple alias doesn't work here, hope this gets inlined...
+ubyte[8] crc64ECMAOf(T...)(T data)
+{
+ return digest!(CRC64ECMA, T)(data);
+}
+
+///
+@system unittest
+{
+ ubyte[] data = [4,5,7,25];
+ assert(data.crc64ECMAOf == [58, 142, 220, 214, 118, 98, 105, 69]);
+
+ import std.utf : byChar;
+ assert("hello"d.byChar.crc64ECMAOf == [177, 55, 185, 219, 229, 218, 30, 155]);
+
+ ubyte[8] hash = "abc".crc64ECMAOf();
+ assert("abc".crc64ECMAOf == [39, 118, 39, 26, 74, 9, 216, 44]);
+ assert(hash == digest!CRC64ECMA("ab", "c"));
+
+ import std.range : iota;
+ enum ubyte S = 5, F = 66;
+ assert(iota(S, F).crc64ECMAOf == [6, 184, 91, 238, 46, 213, 127, 188]);
+}
+
+/**
+ * This is a convenience alias for $(REF digest, std,digest,digest) using the
+ * CRC64-ISO implementation.
+ *
+ * Params:
+ * data = $(D InputRange) of $(D ElementType) implicitly convertible to
+ * $(D ubyte), $(D ubyte[]) or $(D ubyte[num]) or one or more arrays
+ * of any type.
+ *
+ * Returns:
+ * CRC64-ISO of data
+ */
+//simple alias doesn't work here, hope this gets inlined...
+ubyte[8] crc64ISOOf(T...)(T data)
+{
+ return digest!(CRC64ISO, T)(data);
+}
+
+///
+@system unittest
+{
+ ubyte[] data = [4,5,7,25];
+ assert(data.crc64ISOOf == [0, 0, 0, 80, 137, 232, 203, 120]);
+
+ import std.utf : byChar;
+ assert("hello"d.byChar.crc64ISOOf == [0, 0, 16, 216, 226, 238, 62, 60]);
+
+ ubyte[8] hash = "abc".crc64ISOOf();
+ assert("abc".crc64ISOOf == [0, 0, 0, 0, 32, 196, 118, 55]);
+ assert(hash == digest!CRC64ISO("ab", "c"));
+
+ import std.range : iota;
+ enum ubyte S = 5, F = 66;
+
+ assert(iota(S, F).crc64ISOOf == [21, 185, 116, 95, 219, 11, 54, 7]);
+}
+
+/**
+ * producing the usual CRC32 string output.
+ */
+public alias crcHexString = toHexString!(Order.decreasing);
+///ditto
+public alias crcHexString = toHexString!(Order.decreasing, 16);
+
+/**
+ * OOP API CRC32 implementation.
+ * See $(D std.digest) for differences between template and OOP API.
+ *
+ * This is an alias for $(D $(REF WrapperDigest, std,digest)!CRC32), see
+ * there for more information.
+ */
+alias CRC32Digest = WrapperDigest!CRC32;
+
+/**
+ * OOP API CRC64-ECMA implementation.
+ * See $(D std.digest.digest) for differences between template and OOP API.
+ *
+ * This is an alias for $(D $(REF WrapperDigest, std,digest,digest)!CRC64ECMA),
+ * see there for more information.
+ */
+alias CRC64ECMADigest = WrapperDigest!CRC64ECMA;
+
+/**
+ * OOP API CRC64-ISO implementation.
+ * See $(D std.digest.digest) for differences between template and OOP API.
+ *
+ * This is an alias for $(D $(REF WrapperDigest, std,digest,digest)!CRC64ISO),
+ * see there for more information.
+ */
+alias CRC64ISODigest = WrapperDigest!CRC64ISO;
+
+///
+@safe unittest
+{
+ //Simple example, hashing a string using Digest.digest helper function
+ auto crc = new CRC32Digest();
+ ubyte[] hash = crc.digest("abc");
+ //Let's get a hash string
+ assert(crcHexString(hash) == "352441C2");
+}
+
+///
+@system unittest
+{
+ //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[]);
+ assert(crcHexString(result) == "D202EF8D");
+}
+
+///
+@safe unittest
+{
+ //Simple example
+ auto hash = new CRC32Digest();
+ hash.put(cast(ubyte) 0);
+ ubyte[] result = hash.finish();
+}
+
+///
+@system unittest
+{
+ //using a supplied buffer
+ ubyte[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)
+}
+
+@system unittest
+{
+ import std.range;
+
+ auto crc = new CRC32Digest();
+
+ crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
+ assert(crc.peek() == cast(ubyte[]) x"bd50274c");
+ crc.reset();
+ crc.put(cast(ubyte[])"");
+ assert(crc.finish() == cast(ubyte[]) x"00000000");
+
+ crc.put(cast(ubyte[])"abcdefghijklmnopqrstuvwxyz");
+ ubyte[20] result;
+ auto result2 = crc.finish(result[]);
+ assert(result[0 .. 4] == result2 && result2 == cast(ubyte[]) x"bd50274c");
+
+ debug
+ assertThrown!Error(crc.finish(result[0 .. 3]));
+
+ assert(crc.length == 4);
+
+ assert(crc.digest("") == cast(ubyte[]) x"00000000");
+
+ assert(crc.digest("a") == cast(ubyte[]) x"43beb7e8");
+
+ assert(crc.digest("abc") == cast(ubyte[]) x"c2412435");
+
+ assert(crc.digest("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq")
+ == cast(ubyte[]) x"5f3f1a17");
+
+ assert(crc.digest("message digest") == cast(ubyte[]) x"7f9d1520");
+
+ assert(crc.digest("abcdefghijklmnopqrstuvwxyz")
+ == cast(ubyte[]) x"bd50274c");
+
+ assert(crc.digest("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
+ == cast(ubyte[]) x"d2e6c21f");
+
+ assert(crc.digest("1234567890123456789012345678901234567890",
+ "1234567890123456789012345678901234567890")
+ == cast(ubyte[]) x"724aa97c");
+
+ ubyte[] onemilliona = new ubyte[1000000];
+ onemilliona[] = 'a';
+ auto digest = crc32Of(onemilliona);
+ assert(digest == cast(ubyte[]) x"BCBF25DC");
+
+ auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
+ digest = crc32Of(oneMillionRange);
+ assert(digest == cast(ubyte[]) x"BCBF25DC");
+}