diff options
author | Iain Buclaw <ibuclaw@gcc.gnu.org> | 2018-10-28 19:51:47 +0000 |
---|---|---|
committer | Iain Buclaw <ibuclaw@gcc.gnu.org> | 2018-10-28 19:51:47 +0000 |
commit | b4c522fabd0df7be08882d2207df8b2765026110 (patch) | |
tree | b5ffc312b0a441c1ba24323152aec463fdbe5e9f /libphobos/src/std/digest/crc.d | |
parent | 01ce9e31a02c8039d88e90f983735104417bf034 (diff) | |
download | gcc-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.d | 705 |
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"); +} |