• R/O
  • SSH
  • HTTPS

rutsubo: コミット


コミットメタ情報

リビジョン100 (tree)
日時2016-07-31 21:55:18
作者dearblue

ログメッセージ

crc & crc-turbo:

  • CRC::BasicCRC グラスと CRC::Generator クラスを CRC クラスに統合
  • CRC.new で派生したクラスに new の 別名 [] を定義するように変更
  • CRC-64-ISO の修正
  • CRC モジュール名の整理
  • 初期値以外が同じかどうかを確認する CRC.variant? メソッドを追加
  • CRC.crc32 などの CRC して整数値を得るメソッドに引数なしで呼び出した場合、CRC モジュールを返すように変更
  • CRC#initial_crc を廃止
  • CRC.setup の別名メソッド CRC.init を追加
  • 定義が不確かな CRC モジュールを無効化
  • (実験的) 任意の CRC 値から逆算してバイト列を生成する機能 CRC.acrc (crc/acrc.rb) を追加

変更サマリ

差分

--- trunk/crc/crc-turbo/README.md (revision 99)
+++ trunk/crc/crc-turbo/README.md (revision 100)
@@ -12,12 +12,12 @@
1212 * author: dearblue (mailto:dearblue@users.osdn.me)
1313 * report issue to: <https://osdn.jp/projects/rutsubo/ticket/>
1414 * how to install: ``gem install crc-turbo``
15- * version: 0.2
15+ * version: 0.3
1616 * release quality: thechnical preview
1717 * licensing: BSD-2-Clause<br>any parts are under Creative Commons License Zero (CC0 / Public Domain).
18- * dependency gems: crc-0.2 (<https://rubygems/gems/crc>)
19- * dependency external c libraries: none
20- * bundled external c libraries: none
18+ * dependency gems: crc-0.3 (<https://rubygems/gems/crc>)
19+ * dependency external C libraries: none
20+ * bundled external C libraries: none
2121
2222
2323 ## How to usage
@@ -26,8 +26,6 @@
2626
2727 ``` shell:shell
2828 # gem install crc-turbo
29-.....
30-#
3129 ```
3230
3331 And, to do ``require "crc"``.
--- trunk/crc/crc-turbo/ext/crc/crcturbo.c (revision 99)
+++ trunk/crc/crc-turbo/ext/crc/crcturbo.c (revision 100)
@@ -16,15 +16,16 @@
1616 TABLE_NOTREADY = 0x1000,
1717 };
1818
19-#define SWITCH_BY_TYPE(FLAGS, STMT_U8, STMT_U16, STMT_U32, STMT_U64, STMT_U128) \
20- switch ((FLAGS) & TYPE_MASK) { \
21- case TYPE_UINT8_T: { STMT_U8; break; } \
22- case TYPE_UINT16_T: { STMT_U16; break; } \
23- case TYPE_UINT32_T: { STMT_U32; break; } \
24- case TYPE_UINT64_T: { STMT_U64; break; } \
25- /* case TYPE_UINT128_T: { STMT_U128; break; } */ \
26- default: { rb_bug(" [INVALID TYPE FLAGS: 0x%02X] ", (FLAGS) & TYPE_MASK); } \
27- } \
19+//#define SNNIPET(BITSIZE, AS, TYPE, TOUINT, CONVUINT)
20+#define SWITCH_BY_TYPE(TYPE, SNNIPET) \
21+ switch ((TYPE)) { \
22+ case TYPE_UINT8_T: { SNNIPET( 8, as8, uint8_t, to_uint8, conv_uint8); break; } \
23+ case TYPE_UINT16_T: { SNNIPET( 16, as16, uint16_t, to_uint16, conv_uint16); break; } \
24+ case TYPE_UINT32_T: { SNNIPET( 32, as32, uint32_t, to_uint32, conv_uint32); break; } \
25+ case TYPE_UINT64_T: { SNNIPET( 64, as64, uint64_t, to_uint64, conv_uint64); break; } \
26+ /* case TYPE_UINT128_T: { SNNIPET(128, as128, uint128_t, to_uint128, conv_uint128); break; } */ \
27+ default: { rb_bug(" [INVALID TYPE FLAGS: 0x%02X] ", (TYPE)); } \
28+ } \
2829
2930 static inline uint8_t
3031 to_uint8(VALUE num)
@@ -321,52 +322,50 @@
321322 };
322323 } anyuint_t;
323324
324-struct generator
325+struct crc_module
325326 {
326- int bitsize;
327- int flags; /* int type, refin, refout */
327+ uint32_t bitsize:10;
328+ uint32_t type:10;
329+ uint32_t reflect_input:1;
330+ uint32_t reflect_output:1;
331+
328332 anyuint_t bitmask, polynomial, initial, xorout;
329333 const void *table; /* entity is String buffer as instance variable */
330334 };
331335
332-static VALUE mCRC; /* module CRC */
336+static VALUE cCRC; /* class CRC */
333337 static VALUE mUtils; /* module CRC::Utils */
334-static VALUE cGenerator; /* class CRC::Generator */
335-static ID generator_iv_name;
336-static ID generator_iv_table_buffer;
338+static ID ext_iv_name;
339+static ID ext_iv_module;
340+static ID ext_iv_table_buffer;
337341
338-static const rb_data_type_t generator_type = {
339- .wrap_struct_name = "crc-turbo.CRC::Generator",
342+static const rb_data_type_t ext_type = {
343+ .wrap_struct_name = "crc-turbo.CRC.module",
340344 .function.dmark = NULL,
341345 .function.dsize = NULL,
342346 .function.dfree = (void *)-1,
343347 };
344348
345-static void
346-check_generator_notinit(VALUE obj)
349+static struct crc_module *
350+get_modulep(VALUE obj)
347351 {
348- struct generator *p;
349- TypedData_Get_Struct(obj, struct generator, &generator_type, p);
350- if (p) { rb_raise(rb_eArgError, "already initialized object - #<%s:0x%p>", rb_obj_classname(obj), (void *)obj); }
352+ struct crc_module *p;
353+ obj = rb_ivar_get(obj, ext_iv_module);
354+ if (NIL_P(obj)) { return NULL; }
355+ TypedData_Get_Struct(obj, struct crc_module, &ext_type, p);
356+ return p;
351357 }
352358
353-static struct generator *
354-get_generator(VALUE obj)
359+static struct crc_module *
360+get_module(VALUE obj)
355361 {
356- struct generator *p;
357- TypedData_Get_Struct(obj, struct generator, &generator_type, p);
358- if (!p) { rb_raise(rb_eArgError, "wrong initialized object - #<%s:0x%p>", rb_obj_classname(obj), (void *)obj); }
362+ struct crc_module *p = get_modulep(obj);
363+ if (!p) { rb_raise(rb_eTypeError, "wrong initialized object - #<%s:0x%p>", rb_obj_classname(obj), (void *)obj); }
359364 return p;
360365 }
361366
362-static VALUE
363-generator_alloc(VALUE mod)
364-{
365- return TypedData_Wrap_Struct(mod, &generator_type, NULL);
366-}
367-
368367 static void
369-generator_init_args(int argc, VALUE argv[], int *flags, int *bitsize, VALUE *poly, VALUE *init, VALUE *xorout, VALUE *name)
368+ext_init_args(int argc, VALUE argv[], int *flags, int *bitsize, VALUE *poly, VALUE *init, VALUE *xorout, VALUE *name)
370369 {
371370 rb_check_arity(argc, 2, 7);
372371 *bitsize = NUM2INT(argv[0]);
@@ -390,191 +389,180 @@
390389 *name = (argc > 6 && !NIL_P(argv[6])) ? rb_String(argv[6]) : Qnil;
391390 }
392391
393-/*
394- * call-seq:
395- * initialize(bitsize, polynomial, initial_state = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil)
396- */
397392 static VALUE
398-generator_init(int argc, VALUE argv[], VALUE obj)
393+ext_s_new(int argc, VALUE argv[], VALUE crc)
399394 {
400- int flags, bitsize;
401- VALUE poly, init, xorout, name;
402- check_generator_notinit(obj);
403- generator_init_args(argc, argv, &flags, &bitsize, &poly, &init, &xorout, &name);
395+ if (get_modulep(crc)) {
396+ return rb_call_super(argc, argv);
397+ } else {
398+ int flags, bitsize;
399+ VALUE poly, init, xorout, name;
400+ ext_init_args(argc, argv, &flags, &bitsize, &poly, &init, &xorout, &name);
404401
405- struct generator *p;
406- size_t allocsize = sizeof(struct generator);
407- RTYPEDDATA_DATA(obj) = p = (struct generator *)ALLOC_N(char, allocsize);
408- p->bitsize = bitsize;
409- p->flags = flags;
410- p->table = NULL;
402+ struct crc_module *p;
403+ VALUE crcmod = TypedData_Make_Struct(crc, struct crc_module, &ext_type, p);
411404
412- /*
413- * bitmask の代入でわざわざ1ビット分を後から行う理由は、
414- * 例えば uint8_t に対して << 8 をすると何もしないため、
415- * これへの対処を目的とする。
416- */
417-#define INIT_GENERATOR(TYPE, AS, TO_UINT, CONV_UINT, P, BITSIZE, POLY, INIT, XOROUT) \
418- P->bitmask.AS = ~(~(TYPE)0 << 1 << (BITSIZE - 1)); \
419- P->polynomial.AS = P->bitmask.AS & TO_UINT(POLY); \
420- P->initial.AS = P->bitmask.AS & TO_UINT(INIT); \
421- P->xorout.AS = P->bitmask.AS & TO_UINT(XOROUT); \
405+ p->bitsize = bitsize;
406+ p->type = flags & TYPE_MASK;
407+ p->reflect_input = ((flags & REFLECT_INPUT) != 0) ? 1 : 0;
408+ p->reflect_output = ((flags & REFLECT_OUTPUT) != 0) ? 1 : 0;
409+ p->table = NULL;
422410
423- SWITCH_BY_TYPE(flags,
424- INIT_GENERATOR(uint8_t, as8, to_uint8, conv_uint8, p, bitsize, poly, init, xorout),
425- INIT_GENERATOR(uint16_t, as16, to_uint16, conv_uint16, p, bitsize, poly, init, xorout),
426- INIT_GENERATOR(uint32_t, as32, to_uint32, conv_uint32, p, bitsize, poly, init, xorout),
427- INIT_GENERATOR(uint64_t, as64, to_uint64, conv_uint64, p, bitsize, poly, init, xorout),
428- INIT_GENERATOR(uint128_t, as128, to_uint128, conv_uint128, p, bitsize, poly, init, xorout));
411+ /*
412+ * bitmask の代入でわざわざ1ビット分を後から行う理由は、
413+ * 例えば uint8_t に対して << 8 をすると何もしないため、
414+ * これへの対処を目的とする。
415+ */
416+#define SNNIPET_INIT_MOD(BITSIZE, AS, TYPE, TOUINT, CONVUINT) \
417+ p->bitmask.AS = ~(~(TYPE)0 << 1 << (bitsize - 1)); \
418+ p->polynomial.AS = p->bitmask.AS & TOUINT(poly); \
419+ p->initial.AS = p->bitmask.AS & TOUINT(init); \
420+ p->xorout.AS = p->bitmask.AS & TOUINT(xorout); \
429421
430-#undef INIT_GENERATOR
422+ SWITCH_BY_TYPE(p->type, SNNIPET_INIT_MOD);
431423
432- rb_ivar_set(obj, generator_iv_name, name);
424+ VALUE newcrc = rb_define_class_id(0, crc);
425+ rb_ivar_set(newcrc, ext_iv_module, crcmod);
426+ rb_ivar_set(newcrc, ext_iv_name, name);
433427
434- return obj;
428+ rb_extend_object(newcrc, rb_const_get(cCRC, rb_intern("ModuleClass")));
429+ rb_define_alias(rb_singleton_class(newcrc), "[]", "new");
430+
431+ return newcrc;
432+ }
435433 }
436434
437435 static VALUE
438-generator_bitsize(VALUE t)
436+ext_bitsize(VALUE t)
439437 {
440- return INT2FIX(get_generator(t)->bitsize);
438+ return INT2FIX(get_module(t)->bitsize);
441439 }
442440
443441 static VALUE
444-generator_bitmask(VALUE t)
442+ext_bitmask(VALUE t)
445443 {
446- struct generator *p = get_generator(t);
447- SWITCH_BY_TYPE(p->flags,
448- return conv_uint8(p->bitmask.as8),
449- return conv_uint16(p->bitmask.as16),
450- return conv_uint32(p->bitmask.as32),
451- return conv_uint64(p->bitmask.as64),
452- return conv_uint128(p->bitmask.as128));
444+ struct crc_module *p = get_module(t);
445+
446+#define SNNIPET_BITMASK(BITSIZE, AS, TYPE, TOUINT, CONVUINT) \
447+ return CONVUINT(p->bitmask.AS); \
448+
449+ SWITCH_BY_TYPE(p->type, SNNIPET_BITMASK);
453450 }
454451
455452 static VALUE
456-generator_polynomial(VALUE t)
453+ext_polynomial(VALUE t)
457454 {
458- struct generator *p = get_generator(t);
459- SWITCH_BY_TYPE(p->flags,
460- return conv_uint8(p->polynomial.as8),
461- return conv_uint16(p->polynomial.as16),
462- return conv_uint32(p->polynomial.as32),
463- return conv_uint64(p->polynomial.as64),
464- return conv_uint128(p->polynomial.as128));
455+ struct crc_module *p = get_module(t);
456+
457+#define SNNIPET_POLYNOMIAL(BITSIZE, AS, TYPE, TOUINT, CONVUINT) \
458+ return CONVUINT(p->polynomial.AS); \
459+
460+ SWITCH_BY_TYPE(p->type, SNNIPET_POLYNOMIAL);
465461 }
466462
467463 static VALUE
468-generator_initial_state(VALUE t)
464+ext_initial_crc(VALUE t)
469465 {
470- struct generator *p = get_generator(t);
471- SWITCH_BY_TYPE(p->flags,
472- return conv_uint8(p->initial.as8),
473- return conv_uint16(p->initial.as16),
474- return conv_uint32(p->initial.as32),
475- return conv_uint64(p->initial.as64),
476- return conv_uint128(p->initial.as128));
466+ struct crc_module *p = get_module(t);
467+
468+#define SNNIPET_INITIAL_CRC(BITSIZE, AS, TYPE, TOUINT, CONVUINT) \
469+ return CONVUINT(p->initial.AS); \
470+
471+ SWITCH_BY_TYPE(p->type, SNNIPET_INITIAL_CRC);
477472 }
478473
479474 static VALUE
480-generator_table(VALUE t)
475+ext_table(VALUE t)
481476 {
482- struct generator *p = get_generator(t);
477+ struct crc_module *p = get_module(t);
483478 rb_raise(rb_eNotImpError, "");
484479 }
485480
486481 static VALUE
487-generator_reflect_input(VALUE t)
482+ext_reflect_input(VALUE t)
488483 {
489- struct generator *p = get_generator(t);
490- return (p->flags & REFLECT_INPUT) ? Qtrue : Qfalse;
484+ struct crc_module *p = get_module(t);
485+ return (p->reflect_input != 0) ? Qtrue : Qfalse;
491486 }
492487
493488 static VALUE
494-generator_reflect_output(VALUE t)
489+ext_reflect_output(VALUE t)
495490 {
496- struct generator *p = get_generator(t);
497- return (p->flags & REFLECT_OUTPUT) ? Qtrue : Qfalse;
491+ struct crc_module *p = get_module(t);
492+ return (p->reflect_output != 0) ? Qtrue : Qfalse;
498493 }
499494
500495 static VALUE
501-generator_xor_output(VALUE t)
496+ext_xor_output(VALUE t)
502497 {
503- struct generator *p = get_generator(t);
504- SWITCH_BY_TYPE(p->flags,
505- return conv_uint8(p->xorout.as8),
506- return conv_uint16(p->xorout.as16),
507- return conv_uint32(p->xorout.as32),
508- return conv_uint64(p->xorout.as64),
509- return conv_uint128(p->xorout.as128));
498+ struct crc_module *p = get_module(t);
499+
500+#define SNNIPET_XOR_OUTPUT(BITSIZE, AS, TYPE, TOUINT, CONVUINT) \
501+ return CONVUINT(p->xorout.AS); \
502+
503+ SWITCH_BY_TYPE(p->type, SNNIPET_XOR_OUTPUT);
510504 }
511505
512506 static VALUE
513-generator_name(VALUE t)
507+ext_name(VALUE t)
514508 {
515- // get_generator で初期化の確認
516- get_generator(t);
509+ // get_module で初期化の確認
510+ get_module(t);
517511
518- return rb_ivar_get(t, generator_iv_name);
512+ return rb_ivar_get(t, ext_iv_name);
519513 }
520514
521515 static VALUE
522-generator_set_name(VALUE t, VALUE name)
516+ext_set_name(VALUE t, VALUE name)
523517 {
524- // get_generator で初期化の確認
525- get_generator(t);
518+ // get_module で初期化の確認
519+ get_module(t);
526520
527- rb_ivar_set(t, generator_iv_name, rb_String(name));
521+ rb_ivar_set(t, ext_iv_name, rb_String(name));
528522 return name;
529523 }
530524
531525 static VALUE
532-generator_update(VALUE t, VALUE seq, VALUE state)
526+ext_update(VALUE t, VALUE seq, VALUE state)
533527 {
534- struct generator *p = get_generator(t);
528+ struct crc_module *p = get_module(t);
535529 rb_check_type(seq, RUBY_T_STRING);
536530 const char *q = RSTRING_PTR(seq);
537531 const char *qq = q + RSTRING_LEN(seq);
538532
539533 if (!p->table) {
540- size_t tablebytes = (p->flags & TYPE_MASK) * 16 * 256;
534+ size_t tablebytes = (p->type) * 16 * 256;
541535 VALUE tablebuf = rb_str_buf_new(tablebytes);
542536 rb_str_set_len(tablebuf, tablebytes);
543537 void *table = RSTRING_PTR(tablebuf);
544- if (p->flags & REFLECT_INPUT) {
545- SWITCH_BY_TYPE(p->flags,
546- crc_build_reflect_tables_u8(p->bitsize, table, p->polynomial.as8, 16),
547- crc_build_reflect_tables_u16(p->bitsize, table, p->polynomial.as16, 16),
548- crc_build_reflect_tables_u32(p->bitsize, table, p->polynomial.as32, 16),
549- crc_build_reflect_tables_u64(p->bitsize, table, p->polynomial.as64, 16),
550- crc_build_reflect_tables_u128(p->bitsize, table, p->polynomial.as128, 16));
538+ if (p->reflect_input) {
539+#define SNNIPET_BUILD_REFTABLE(BITSIZE, AS, TYPE, TOUINT, CONVUINT) \
540+ crc_build_reflect_tables_u##BITSIZE(p->bitsize, table, p->polynomial.AS, 16); \
541+
542+ SWITCH_BY_TYPE(p->type, SNNIPET_BUILD_REFTABLE);
551543 } else {
552- SWITCH_BY_TYPE(p->flags,
553- crc_build_tables_u8(p->bitsize, table, p->polynomial.as8, 16),
554- crc_build_tables_u16(p->bitsize, table, p->polynomial.as16, 16),
555- crc_build_tables_u32(p->bitsize, table, p->polynomial.as32, 16),
556- crc_build_tables_u64(p->bitsize, table, p->polynomial.as64, 16),
557- crc_build_tables_u128(p->bitsize, table, p->polynomial.as128, 16));
544+#define SNNIPET_BUILD_TABLE(BITSIZE, AS, TYPE, TOUINT, CONVUINT) \
545+ crc_build_tables_u##BITSIZE(p->bitsize, table, p->polynomial.AS, 16); \
546+
547+ SWITCH_BY_TYPE(p->type, SNNIPET_BUILD_TABLE);
558548 }
559- rb_ivar_set(t, generator_iv_table_buffer, tablebuf);
549+ rb_ivar_set(t, ext_iv_table_buffer, tablebuf);
560550 rb_obj_freeze(tablebuf);
561551 p->table = table;
562552 }
563553
564- if (p->flags & REFLECT_INPUT) {
565- SWITCH_BY_TYPE(p->flags,
566- return conv_uint8(crc_reflect_update_u8(p->bitsize, p->table, q, qq, to_uint8(state))),
567- return conv_uint16(crc_reflect_update_u16(p->bitsize, p->table, q, qq, to_uint16(state))),
568- return conv_uint32(crc_reflect_update_u32(p->bitsize, p->table, q, qq, to_uint32(state))),
569- return conv_uint64(crc_reflect_update_u64(p->bitsize, p->table, q, qq, to_uint64(state))),
570- return conv_uint128(crc_reflect_update_u128(p->bitsize, p->table, q, qq, to_uint128(state))));
554+ if (p->reflect_input) {
555+#define SNNIPET_REFUPDATE(BITSIZE, AS, TYPE, TOUINT, CONVUINT) \
556+ return CONVUINT(crc_reflect_update_u##BITSIZE( \
557+ p->bitsize, p->table, q, qq, TOUINT(state))); \
558+
559+ SWITCH_BY_TYPE(p->type, SNNIPET_REFUPDATE);
571560 } else {
572- SWITCH_BY_TYPE(p->flags,
573- return conv_uint8(crc_update_u8(p->bitsize, p->table, q, qq, to_uint8(state))),
574- return conv_uint16(crc_update_u16(p->bitsize, p->table, q, qq, to_uint16(state))),
575- return conv_uint32(crc_update_u32(p->bitsize, p->table, q, qq, to_uint32(state))),
576- return conv_uint64(crc_update_u64(p->bitsize, p->table, q, qq, to_uint64(state))),
577- return conv_uint128(crc_update_u128(p->bitsize, p->table, q, qq, to_uint128(state))));
561+#define SNNIPET_UPDATE(BITSIZE, AS, TYPE, TOUINT, CONVUINT) \
562+ return CONVUINT(crc_update_u##BITSIZE( \
563+ p->bitsize, p->table, q, qq, TOUINT(state))); \
564+
565+ SWITCH_BY_TYPE(p->type, SNNIPET_UPDATE);
578566 }
579567 }
580568
@@ -639,30 +627,28 @@
639627 void
640628 Init__turbo(void)
641629 {
642- generator_iv_name = rb_intern("crc-turbo.CRC::Generator.name");
643- generator_iv_table_buffer = rb_intern("crc-turbo.CRC::Generator.table-buffer");
630+ ext_iv_name = rb_intern("crc-turbo.CRC.name");
631+ ext_iv_module = rb_intern("crc-turbo.CRC.module");
632+ ext_iv_table_buffer = rb_intern("crc-turbo.CRC.table-buffer");
644633
645- mCRC = rb_define_module("CRC");
634+ cCRC = rb_define_class("CRC", rb_cObject);
635+ rb_define_singleton_method(cCRC, "new", ext_s_new, -1);
636+ rb_define_singleton_method(cCRC, "bitsize", ext_bitsize, 0);
637+ rb_define_singleton_method(cCRC, "bitmask", ext_bitmask, 0);
638+ rb_define_singleton_method(cCRC, "polynomial", ext_polynomial, 0);
639+ rb_define_singleton_method(cCRC, "initial_crc", ext_initial_crc, 0);
640+ rb_define_singleton_method(cCRC, "table", ext_table, 0);
641+ rb_define_singleton_method(cCRC, "reflect_input?", ext_reflect_input, 0);
642+ rb_define_singleton_method(cCRC, "reflect_output?", ext_reflect_output, 0);
643+ rb_define_singleton_method(cCRC, "xor_output", ext_xor_output, 0);
644+ rb_define_singleton_method(cCRC, "name", ext_name, 0);
645+ rb_define_singleton_method(cCRC, "name=", ext_set_name, 1);
646+ rb_define_singleton_method(cCRC, "update", ext_update, 2);
646647
647- mUtils = rb_define_module_under(mCRC, "Utils");
648+ mUtils = rb_define_module_under(cCRC, "Utils");
648649 rb_define_method(mUtils, "bitreflect8", utils_s_bitref8, 1);
649650 rb_define_method(mUtils, "bitreflect16", utils_s_bitref16, 1);
650651 rb_define_method(mUtils, "bitreflect32", utils_s_bitref32, 1);
651652 rb_define_method(mUtils, "bitreflect64", utils_s_bitref64, 1);
652653 rb_define_method(mUtils, "bitreflect128", utils_s_bitref128, 1);
653-
654- cGenerator = rb_define_class_under(mCRC, "Generator", rb_cObject);
655- rb_define_alloc_func(cGenerator, generator_alloc);
656- rb_define_method(cGenerator, "initialize", generator_init, -1);
657- rb_define_method(cGenerator, "bitsize", generator_bitsize, 0);
658- rb_define_method(cGenerator, "bitmask", generator_bitmask, 0);
659- rb_define_method(cGenerator, "polynomial", generator_polynomial, 0);
660- rb_define_method(cGenerator, "initial_state", generator_initial_state, 0);
661- rb_define_method(cGenerator, "table", generator_table, 0);
662- rb_define_method(cGenerator, "reflect_input", generator_reflect_input, 0);
663- rb_define_method(cGenerator, "reflect_output", generator_reflect_output, 0);
664- rb_define_method(cGenerator, "xor_output", generator_xor_output, 0);
665- rb_define_method(cGenerator, "name", generator_name, 0);
666- rb_define_method(cGenerator, "name=", generator_set_name, 1);
667- rb_define_method(cGenerator, "update", generator_update, 2);
668654 }
--- trunk/crc/crc-turbo/ext/crc/crc_imps.h (revision 99)
+++ trunk/crc/crc-turbo/ext/crc/crc_imps.h (revision 100)
@@ -4,7 +4,7 @@
44 *
55 * This is a general CRC generator.
66 *
7- * It's used slice-by-16 algorithm with byte-order free and byte-alignment free.
7+ * It's used slice-by-16 algorithm with byte-order free.
88 * This is based on the Intel's slice-by-eight algorithm.
99 *
1010 * Worst point is need more memory!
--- trunk/crc/crc-turbo/gemstub.rb (revision 99)
+++ trunk/crc/crc-turbo/gemstub.rb (revision 100)
@@ -1,6 +1,6 @@
11 GEMSTUB = Gem::Specification.new do |s|
22 s.name = "crc-turbo"
3- s.version = "0.2"
3+ s.version = "0.3"
44 s.summary = "general CRC generator"
55 s.description = <<EOS
66 This is a C extention for "crc" gem library.
@@ -12,8 +12,8 @@
1212 s.email = "dearblue@users.osdn.me"
1313
1414 s.required_ruby_version = ">= 2.0"
15- s.add_development_dependency "rake", "~> 11.0"
16- s.add_runtime_dependency "crc", "~> 0.2"
15+ s.add_development_dependency "rake"
16+ s.add_runtime_dependency "crc", "~> 0.3"
1717 end
1818
1919 EXTMAP["crc"] = "crc/_turbo"
--- trunk/crc/crc-turbo/HISTORY.ja.md (revision 99)
+++ trunk/crc/crc-turbo/HISTORY.ja.md (revision 100)
@@ -2,6 +2,10 @@
22
33 # crc-turbo for ruby の更新履歴
44
5+## crc-0.3
6+
7+ * crc-0.3 に追従して、CRC::BasicCRC と CRC::Generator を CRC に統合
8+
59 ## crc-0.2 (平成28年5月15日 (日))
610
711 * \[FIX\] CRC::Generator#polynomial メソッドが間違った値を返していた問題を修正
--- trunk/crc/lib/crc/version.rb (nonexistent)
+++ trunk/crc/lib/crc/version.rb (revision 100)
@@ -0,0 +1,5 @@
1+#!ruby
2+
3+class CRC
4+ VERSION = "0.3"
5+end
--- trunk/crc/lib/crc/_modules.rb (revision 99)
+++ trunk/crc/lib/crc/_modules.rb (revision 100)
@@ -12,12 +12,13 @@
1212 # * https://github.com/cluelogic/cluelib/blob/master/src/cl_crc.svh
1313 # * https://users.ece.cmu.edu/~koopman/crc/hw_data.html
1414 # * https://users.ece.cmu.edu/~koopman/roses/dsn04/koopman04_crc_poly_embedded.pdf
15+# * (CRC-64-ISO-3309) http://swissknife.cvs.sourceforge.net/viewvc/swissknife/SWISS/lib/SWISS/CRC64.pm
1516 #++
1617
17-module CRC
18+class CRC
1819 LIST = [
1920 #
20- # bit size, polynomial, initial state,
21+ # bit size, polynomial, initial crc,
2122 # refrect input, xor output,
2223 # reflect output, crc("123456789"), names...
2324 #
@@ -33,10 +34,10 @@
3334 [ 6, 0x19, true, true, 0, 0, 0x26, "CRC-6-DARC"],
3435 [ 6, 0x03, true, true, 0, 0, 0x06, "CRC-6-ITU"],
3536 [ 7, 0x09, false, false, 0, 0, 0x75, "CRC-7", "CRC-7-JESD84-A441"],
36- [ 7, 0x65, false, false, 0, 0, nil, "CRC-7-MVB"],
37+ #[ 7, 0x65, false, false, 0, 0, nil, "CRC-7-MVB"],
3738 [ 7, 0x4F, true, true, ~0, 0, 0x53, "CRC-7-ROHC", "CRC-7-RFC 3095"],
3839 [ 7, 0x45, false, false, 0, 0, 0x61, "CRC-7-UMTS"],
39- [ 8, 0xD5, false, false, 0, 0, nil, "CRC-8"],
40+ #[ 8, 0xD5, false, false, 0, 0, nil, "CRC-8"],
4041 [ 8, 0x07, false, false, 0, 0, 0xF4, "CRC-8-CCITT", "CRC-8-SMBus"],
4142 [ 8, 0x31, true, true, 0, 0, 0xA1, "CRC-8-MAXIM", "CRC-8-Dallas/Maxim", "DOW-CRC"],
4243 [ 8, 0x39, true, true, 0, 0, 0x15, "CRC-8-DARC"],
@@ -60,9 +61,9 @@
6061 [14, 0x0805, true, true, 0, 0, 0x082D, "CRC-14-DARC"],
6162 [15, 0x4599, false, false, 0, 0, 0x059E, "CRC-15", "CRC-15-CAN"],
6263 [15, 0x6815, false, false, 1, 1, 0x2566, "CRC-15-MPT1327"],
63- [16, 0x2F15, false, false, 0, 0, nil, "Chakravarty"],
64- [16, 0x8005, true, true, 0, 0, 0xBB3D, "ARC", "CRC-16", "CRC-IBM", "CRC-16-ARC", "CRC-16-LHA"],
65- [16, 0xA02B, false, false, 0, 0, nil, "CRC-16-ARINC"],
64+ #[16, 0x2F15, false, false, 0, 0, nil, "Chakravarty"],
65+ [16, 0x8005, true, true, 0, 0, 0xBB3D, "CRC-16", "ARC", "CRC-IBM", "CRC-16-ARC", "CRC-16-LHA"],
66+ #[16, 0xA02B, false, false, 0, 0, nil, "CRC-16-ARINC"],
6667 [16, 0x1021, false, false, 0x1D0F, 0, 0xE5CC, "CRC-16-AUG-CCITT", "CRC-16-SPI-FUJITSU"],
6768 [16, 0xC867, false, false, ~0, 0, 0x4C06, "CRC-16-CDMA2000"],
6869 [16, 0x0589, false, false, 1, 1, 0x007E, "CRC-16-DECT-R", "R-CRC-16"],
@@ -81,14 +82,14 @@
8182 [16, 0xA097, false, false, 0, 0, 0x0FB3, "CRC-16-TELEDISK"],
8283 [16, 0x1021, true, true, 0x89EC, 0, 0x26B1, "CRC-16-TMS37157"],
8384 [16, 0x8005, true, true, 0, ~0, 0xB4C8, "CRC-16-USB"],
84- [16, 0x1021, true, true, 0xC6C6, 0, 0xBF05, "CRC-A", "CRC-16-ISO/IEC FCD 14443-3"],
85- [16, 0x1021, true, true, 0, 0, 0x2189, "KERMIT", "CRC-16-CCITT", "CRC-16-CCITT-TRUE", "CRC-CCITT"],
86- [16, 0x8005, true, true, ~0, 0, 0x4B37, "MODBUS"],
87- [16, 0x1021, true, true, 0, ~0, 0x906E, "X-25", "CRC-16-IBM-SDLC", "CRC-16-ISO-HDLC", "CRC-B"],
88- [16, 0x1021, false, false, 0, 0, 0x31C3, "XMODEM", "ZMODEM", "CRC-16-ACORN", "CRC-16-LTE"],
89- [17, 0x0001685B, false, false, 0, 0, nil, "CRC-17-CAN"],
90- [21, 0x00102899, false, false, 0, 0, nil, "CRC-21-CAN"],
91- [24, 0x005D6DCB, false, false, 0, 0, nil, "CRC-24"],
85+ [16, 0x1021, true, true, 0xC6C6, 0, 0xBF05, "CRC-16-A", "CRC-A", "CRC-16-ISO/IEC FCD 14443-3"],
86+ [16, 0x1021, true, true, 0, 0, 0x2189, "CRC-16-KERMIT", "KERMIT", "CRC-16-CCITT", "CRC-16-CCITT-TRUE", "CRC-CCITT"],
87+ [16, 0x8005, true, true, ~0, 0, 0x4B37, "CRC-16-MODBUS", "MODBUS"],
88+ [16, 0x1021, true, true, 0, ~0, 0x906E, "CRC-16-X-25", "X-25", "CRC-16-IBM-SDLC", "CRC-16-ISO-HDLC", "CRC-16-CRC-B", "CRC-B"],
89+ [16, 0x1021, false, false, 0, 0, 0x31C3, "CRC-16-XMODEM", "XMODEM", "CRC-16-ZMODEM", "ZMODEM", "CRC-16-ACORN", "CRC-16-LTE"],
90+ #[17, 0x0001685B, false, false, 0, 0, nil, "CRC-17-CAN"],
91+ #[21, 0x00102899, false, false, 0, 0, nil, "CRC-21-CAN"],
92+ #[24, 0x005D6DCB, false, false, 0, 0, nil, "CRC-24"],
9293 [24, 0x00864CFB, false, false, 0, 0, 0x00CDE703, "CRC-24-Radix-64"],
9394 [24, 0x00864CFB, false, false, 0x00B704CE, 0, 0x0021CF02, "CRC-24-OPENPGP"],
9495 [24, 0x0000065B, true, true, 0x00555555, 0, 0x00C25A56, "CRC-24-BLE"],
@@ -97,25 +98,25 @@
9798 [24, 0x00328B63, false, false, 0, ~0, 0x00B4F3E6, "CRC-24-INTERLAKEN"],
9899 [24, 0x00864CFB, false, false, 0, 0, 0x00CDE703, "CRC-24-LTE-A"],
99100 [24, 0x00800063, false, false, 0, 0, 0x0023EF52, "CRC-24-LTE-B"],
100- [30, 0x2030B9C7, false, false, 0, 0, nil, "CRC-30"],
101+ #[30, 0x2030B9C7, false, false, 0, 0, nil, "CRC-30"],
101102 [30, 0x2030B9C7, false, false, 0, ~0, 0x04C34ABF, "CRC-30-CDMA"],
102103 [31, 0x04C11DB7, false, false, 0, ~0, 0x0CE9E46C, "CRC-31-PHILIPS"],
103- [32, 0x04C11DB7, true, true, 0, ~0, 0xCBF43926, "CRC-32", "CRC-32-ADCCP", "PKZIP", "CRC-32-PKZIP"],
104+ [32, 0x04C11DB7, true, true, 0, ~0, 0xCBF43926, "CRC-32", "CRC-32-ADCCP", "CRC-32-PKZIP", "PKZIP"],
104105 [32, 0x04C11DB7, false, false, 0, ~0, 0xFC891918, "CRC-32-BZIP2", "CRC-32-AAL5", "CRC-32-DECT-B", "B-CRC-32"],
105106 [32, 0x1EDC6F41, true, true, 0, ~0, 0xE3069283, "CRC-32C", "CRC-32-ISCSI", "CRC-32-CASTAGNOLI", "CRC-32-INTERLAKEN"],
106107 [32, 0xa833982b, true, true, 0, ~0, 0x87315576, "CRC-32D"],
107108 [32, 0x04C11DB7, false, false, ~0, 0, 0x0376E6E7, "CRC-32-MPEG-2"],
108109 [32, 0x04C11DB7, false, false, ~0, ~0, 0x765E7680, "CRC-32-POSIX", "CKSUM"],
109- [32, 0x741B8CD7, true, true, 0, ~0, nil, "CRC-32K"],
110- [32, 0x32583499, true, true, 0, ~0, nil, "CRC-32K2"],
110+ #[32, 0x741B8CD7, true, true, 0, ~0, nil, "CRC-32K"],
111+ #[32, 0x32583499, true, true, 0, ~0, nil, "CRC-32K2"],
111112 [32, 0x814141AB, false, false, 0, 0, 0x3010BF7F, "CRC-32Q"],
112- [32, 0x04C11DB7, true, true, ~0, 0, 0x340BC6D9, "JAMCRC", "CRC-32-JAMCRC"],
113- [32, 0x000000AF, false, false, 0, 0, 0xBD0BE338, "XFER", "CRC-32-XFER"],
113+ [32, 0x04C11DB7, true, true, ~0, 0, 0x340BC6D9, "CRC-32-JAMCRC", "JAMCRC"],
114+ [32, 0x000000AF, false, false, 0, 0, 0xBD0BE338, "CRC-32-XFER", "XFER"],
114115 [40, 0x0004820009, false, false, ~0, ~0, 0xD4164FC646, "CRC-40-GSM"],
115- [64, 0x42F0E1EBA9EA3693, true, true, 0, ~0, 0x995DC9BBDF1939FA, "CRC-64", "CRC-64-XZ"],
116+ [64, 0x42F0E1EBA9EA3693, true, true, 0, ~0, 0x995DC9BBDF1939FA, "CRC-64-XZ", "CRC-64"],
116117 [64, 0x42F0E1EBA9EA3693, false, false, 0, 0, 0x6C40DF5F0B497347, "CRC-64-ECMA", "CRC-64-ECMA-182"],
117118 [64, 0x42F0E1EBA9EA3693, false, false, 0, ~0, 0x62EC59E3F1A4F00A, "CRC-64-WE"],
118- [64, 0x000000000000001B, false, false, 0, 0, nil, "CRC-64-ISO"],
119+ [64, 0x000000000000001B, true, true, 0, 0, 0x46A5A9388A5BEFFE, "CRC-64-ISO", "CRC-64-ISO-3309"],
119120 # [82, 0x308C0111011401440411, true, true, 0, 0, 0x9EA83F625023801FD612, "CRC-82/DARC"],
120121 ]
121122 end
--- trunk/crc/lib/crc/finder.rb (revision 99)
+++ trunk/crc/lib/crc/finder.rb (revision 100)
@@ -1,6 +1,8 @@
1+#!ruby
2+
13 require_relative "../crc"
24
3-module CRC
5+class CRC
46 def self.find(crc, seq, bitsize, polynomial, initstate = [0, ~0, 1], xor = [0, ~0, 1])
57 bitsize0 = bitsize.to_i
68 if bitsize0 < 1 || bitsize0 > 128
@@ -10,8 +12,6 @@
1012 crc &= bitmask
1113 results = []
1214 poly = Array(polynomial)
13- #poly += poly.map { |po| Utils.bitreflect(po, bitsize0) }
14- #poly.uniq!
1515 poly.each do |poly|
1616 poly &= bitmask
1717 [false, true].each do |refin|
@@ -20,7 +20,7 @@
2020 xormask &= bitmask
2121 Array(initstate).each do |init|
2222 init &= bitmask
23- mod = CRC.create_module(bitsize0, poly, init, refin, refout, xormask)
23+ mod = CRC.new(bitsize0, poly, init, refin, refout, xormask)
2424 results << mod if mod.crc(seq) == crc
2525 end
2626 end
--- trunk/crc/lib/crc/acrc.rb (nonexistent)
+++ trunk/crc/lib/crc/acrc.rb (revision 100)
@@ -0,0 +1,195 @@
1+#!ruby
2+
3+require_relative "../crc"
4+
5+class CRC
6+ module ModuleClass
7+ #
8+ # call-seq:
9+ # acrc(crc, rest_seq = nil, target_crc = 0) -> byte string as arc-code
10+ #
11+ # 目的となる crc になるように、指定された crc に続くバイト列を逆算します。
12+ #
13+ # 出力されるバイト列は、crc のビット数を表現できるバイト数となります。
14+ #
15+ # 現在のところ、reflect-input/output 限定となっています。
16+ #
17+ # * crc32("123456789????") の結果が 0 となるような、???? の部分を逆算する
18+ #
19+ # seq = "123456789"
20+ # seq << CRC::CRC32.acrc(seq)
21+ # p CRC::CRC32[seq] # => #<CRC::CRC32:00000000>
22+ #
23+ # * crc32("123456789????ABCDEFG") の結果が 0 となるような、???? の部分を逆算する
24+ #
25+ # seq1 = "123456789"
26+ # seq2 = "ABCDEFG"
27+ # seq = seq1 + CRC::CRC32.acrc(seq1, seq2) + seq2
28+ # p CRC::CRC32[seq] # => #<CRC::CRC32:00000000>
29+ #
30+ # * crc32("123456789????ABCDEFG") の結果が 0x12345678 となるような、???? の部分を逆算する
31+ #
32+ # seq1 = "123456789"
33+ # seq2 = "ABCDEFG"
34+ # target_crc = 0x12345678
35+ # seq = seq1 + CRC::CRC32.acrc(seq1, seq2, target_crc) + seq2
36+ # p CRC::CRC32[seq] # => #<CRC::CRC32:12345678>
37+ #
38+ def acrc(crc, rest_seq = nil, target_crc = 0)
39+ raise NotImplementedError, "crc polynomial is not odd" unless polynomial.odd?
40+ raise NotImplementedError, "crc module is not reflect input and output" unless reflect_input? && reflect_output?
41+
42+ bitsize = self.bitsize
43+ poly = CRC.bitreflect(polynomial, bitsize)
44+ target_crc = target_crc.to_i
45+ target_crc ^= xor_output
46+
47+ if rest_seq
48+ rest_seq.bytesize.downto(1) do |i|
49+ target_crc = Aux.acrc_loop_reflect(target_crc, rest_seq.getbyte(i - 1), poly, bitsize, 0xff, 8)
50+ end
51+ end
52+
53+ bytes = (bitsize + 7) / 8
54+ bits = bytes * 8
55+
56+ case crc
57+ when Numeric
58+ state = bitmask & crc ^ xor_output
59+ when CRC
60+ raise "different crc module (given %p(%p), expect %p)" % [crc, crc.class, self] unless variant?(crc)
61+ state = crc.state
62+ else
63+ state = new(crc).state
64+ end
65+
66+ if bits > bitsize
67+ # ビット数が 8 の境界にない場合、その隙間分を埋める。
68+ # 現在の実装では、最終結果のバイト列における最終バイト値の
69+ # 上位ビットが 0 であるようにしている。
70+ pad = bits - bitsize
71+ target_crc = Aux.acrc_loop_reflect(target_crc, 0, poly, bitsize, 0xff, pad)
72+ end
73+
74+ target_crc = Aux.acrc_loop_reflect(target_crc, state, poly, bitsize, bitmask, bitsize)
75+
76+ bytes.times.reduce("") { |a, *| a << (target_crc & 0xff).chr(Encoding::BINARY); target_crc >>= 8; a }
77+ end
78+ end
79+
80+ module Aux
81+ def self.acrc_loop_reflect(target_crc, state, poly, crcbits, bitmask, bits)
82+ head = bits - 1
83+ bitmask1 = bitmask >> 1
84+ crchead = crcbits - 1
85+
86+ #puts "target_crc=0b%016b, state=0b%016b, reversed-polynomial=0b%016b" % [target_crc, state, poly]
87+ bits.times do |i|
88+ if target_crc[crchead] == 0
89+ target_crc <<= 1
90+ else
91+ target_crc ^= poly
92+ target_crc <<= 1
93+ target_crc |= 0x01
94+ end
95+
96+ target_crc ^= state[head]
97+ #puts " 0_%016b ^ %d" % [target_crc, state[head]]
98+ state = (state & bitmask1) << 1
99+ end
100+ #puts "target_crc=0b%016b" % target_crc
101+
102+ target_crc
103+ end
104+ end
105+end
106+
107+if $0 == __FILE__
108+ seq = "abcdefghijklmnopqrstuvwxyz"
109+ seq2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
110+ code = CRC::X_25.acrc(seq, seq2)
111+ puts "base-crc=[%p, %p], arc'd-crc=%p, arc-code=%s" % [CRC::X_25[seq], CRC::X_25[seq2], CRC::X_25[seq + code + seq2], code.unpack("H*")[0]]
112+ code = CRC::CRC32.acrc(seq, seq2)
113+ puts "base-crc=[%p, %p], arc'd-crc=%p, arc-code=%s" % [CRC::CRC32[seq], CRC::CRC32[seq2], CRC::CRC32[seq + code + seq2], code.unpack("H*")[0]]
114+ code = CRC::CRC32C.acrc(seq, seq2)
115+ puts "base-crc=[%p, %p], arc'd-crc=%p, arc-code=%s" % [CRC::CRC32C[seq], CRC::CRC32C[seq2], CRC::CRC32C[seq + code + seq2], code.unpack("H*")[0]]
116+
117+ MyCRC = crcmod = CRC.new(32, rand(1<<32) | 1, rand(1<<32) | 1, true, true, rand(1<<32) | 1)
118+ 20.times do |i|
119+ s = (10+rand(20)).times.reduce("") { |a, *| a << rand(256).chr(Encoding::BINARY) }
120+ t = (10+rand(20)).times.reduce("") { |a, *| a << rand(256).chr(Encoding::BINARY) }
121+ crc = crcmod.new(s)
122+ puts "crc=[%p, %p], arc'd-crc=%p, target=%08X, seq=%s" %
123+ [crc, crcmod[t], crcmod.new(s + crcmod.acrc(crc.crc, t, i * 9929) + t), i * 9929, s.unpack("H*")[0]]
124+ end
125+end
126+
127+__END__
128+
129+目的となる CRC 値を逆算して、特定のバイト列を得る機能です。
130+
131+ただの思いつきで、crc すると結果が 0 になるバイト列を計算できないかなと遊んでみた結果、
132+それなりの形となってしまいました。
133+
134+以下は acrc メソッドとして実装した、その仕組みとなります。
135+
136+
137+X-25{CRC-16-0x1021 ref-in/out xor=0xffff} を用いた場合
138+
139+("abcdefghijklmnopqrstuvwxyz" + ??) を CRC して結果を 0 にしたい (?? は2バイト)。
140+
141+この時の ?? を求める。
142+
143+先に "abcdefghijklmnopqrstuvwxyz" までの CRC を求めておく => 0x0d43
144+
145+(ここまでの内部状態は 0xf2bc) ?? <STOP> (この段階で内部状態が 0xffff であること)
146+
147+内部状態の最上位ビットから順に送って、目的となる内部状態が 0xffff から 0xf2bc になるような値を逆算する
148+
149+
150+code = 0 # 最終的に求めたい CRC
151+state = 0b1111001010111100 # 現在の CRC 生成器の内部状態
152+reversed_polynomial = 0b1000010000001000
153+
154+ 1. 最終的に求めたい CRC と xor_output する
155+ 1111111111111111
156+
157+ 2. この時、code の最上位ビットが1なので、poly (reversed) で xor する
158+ 最上位ビットが0ならば何もしない
159+ 0111101111110111
160+
161+ 3. 左にずらす
162+ 1111011111101110
163+
164+ 4. (2) において poly-reversed で xor したため、最下位ビットを1にする
165+ (2) を行わなかった場合は何もしない
166+ 1111011111101111
167+
168+ 5. 目的となる内部状態の最上位ビットと作業内部状態の最下位ビットを xor した時に 1 となるように調整する
169+ (2) を行わなかった場合は 0 を維持するように処置する
170+ 1111011111101110
171+
172+ 6. 1 ビット目の処理が完了。(2) に戻って必要なだけ繰り返す
173+
174+ 1111011111101110 <= 1 ## 最上位から2ビット目を入力
175+ 1110011111001100 <= 1 ## 最上位から3ビット目を入力
176+ 1100011110001000 <= 1 ## 以下同様に……
177+ 1000011100000000 <= 0
178+ 0000011000010001 <= 0
179+ 0000110000100010 <= 1
180+ 0001100001000101 <= 0
181+ 0011000010001010 <= 1
182+ 0110000100010101 <= 0
183+ 1100001000101010 <= 1
184+ 1000110001000100 <= 1
185+ 0001000010011000 <= 1
186+ 0010000100110001 <= 1
187+ 0100001001100011 <= 0
188+ 1000010011000110 <= 0
189+ 0000000110011101 ## 繰り返して得られた結果
190+ この結果を元にして、バイト順を入れ替える
191+ (CRC として求める場合に、下位から入力されるため)
192+
193+ 10011101:00000001 >>>> [0x9d, 0x01] が返る
194+
195+[EOF]
--- trunk/crc/lib/crc/_byruby.rb (revision 99)
+++ trunk/crc/lib/crc/_byruby.rb (revision 100)
@@ -9,7 +9,7 @@
99 # \* \* \* \* \* \* \* \*
1010 #
1111 # Ruby implemented CRC generator.
12-# It's used slice-by-16 algorithm with byte-order free and byte-alignment free.
12+# It's used slice-by-16 algorithm with byte-order free.
1313 # This is based on the Intel's slice-by-eight algorithm.
1414 #
1515 # It's faster than about 50% (CRC-32) and about 30% (CRC-64) of
@@ -26,69 +26,46 @@
2626 #
2727 # If defined "RUBY_CRC_NOFAST=3" enviroment variable, switch to reference algorithm.
2828 #
29-module CRC
30- module Utils
31- def bitreflect8(n)
32- n = n.to_i
33- n = ((n & 0x55) << 1) | ((n >> 1) & 0x55)
34- n = ((n & 0x33) << 2) | ((n >> 2) & 0x33)
35- return ((n & 0x0f) << 4) | (n >> 4) # 0x0f
36- end
37-
38- def bitreflect16(n)
39- n = n.to_i
40- n = ((n & 0x5555) << 1) | ((n >> 1) & 0x5555)
41- n = ((n & 0x3333) << 2) | ((n >> 2) & 0x3333)
42- n = ((n & 0x0f0f) << 4) | ((n >> 4) & 0x0f0f)
43- return ((n & 0x00ff) << 8) | (n >> 8) # 0x00ff
44- end
45-
46- def bitreflect32(n)
47- n = n.to_i
48- n = ((n & 0x55555555) << 1) | ((n >> 1) & 0x55555555)
49- n = ((n & 0x33333333) << 2) | ((n >> 2) & 0x33333333)
50- n = ((n & 0x0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f)
51- n = ((n & 0x00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff)
52- return ((n & 0x0000ffff) << 16) | (n >> 16) # 0x0000ffff
53- end
54-
55- def bitreflect64(n)
56- n = n.to_i
57- n = ((n & 0x5555555555555555) << 1) | ((n >> 1) & 0x5555555555555555)
58- n = ((n & 0x3333333333333333) << 2) | ((n >> 2) & 0x3333333333333333)
59- n = ((n & 0x0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f)
60- n = ((n & 0x00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff)
61- n = ((n & 0x0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff)
62- return ((n & 0x00000000ffffffff) << 32) | (n >> 32) # 0x00000000ffffffff
63- end
64-
65- def bitreflect128(n)
66- n = n.to_i
67- n = ((n & 0x55555555555555555555555555555555) << 1) | ((n >> 1) & 0x55555555555555555555555555555555)
68- n = ((n & 0x33333333333333333333333333333333) << 2) | ((n >> 2) & 0x33333333333333333333333333333333)
69- n = ((n & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f)
70- n = ((n & 0x00ff00ff00ff00ff00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff00ff00ff00ff00ff)
71- n = ((n & 0x0000ffff0000ffff0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff0000ffff0000ffff)
72- n = ((n & 0x00000000ffffffff00000000ffffffff) << 32) | ((n >> 32) & 0x00000000ffffffff00000000ffffffff)
73- return ((n & 0x0000000000000000ffffffffffffffff) << 64) | (n >> 64) # 0x0000000000000000ffffffffffffffff
74- end
75- end
76-
77- class Generator < Struct.new(:bitsize, :bitmask, :polynomial, :initial_state, :table, :reflect_input, :reflect_output, :xor_output, :name)
78- BasicStruct = superclass
79-
80- def initialize(bitsize, polynomial, initial_state = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil)
29+class CRC
30+ class << self
31+ #
32+ # call-seq:
33+ # new(bitsize, polynomial, initial_crc = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil) -> new crc module class (CRC based class)
34+ # new(initial_crc = nil, size = 0) -> new crc generator (CRC instance)
35+ # new(seq, initial_crc = nil, size = 0) -> new crc generator (CRC instance)
36+ #
37+ def new(bitsize, polynomial, initial_crc = 0, reflect_input = true, reflect_output = true, xor_output = ~0, name = nil)
8138 bitsize = bitsize.to_i
8239 if bitsize < 1 || bitsize > 64
8340 raise ArgumentError, "wrong bitsize (except 1..64, but given #{bitsize})"
8441 end
42+
8543 bitmask = ~(~0 << bitsize)
8644 polynomial = bitmask & polynomial
87- initial_state = bitmask & initial_state
45+ initial_crc = bitmask & initial_crc
8846 xor_output = bitmask & xor_output
8947 name = (name.nil? || ((name = String(name)).empty?)) ? nil : name
90- super(bitsize, bitmask, polynomial, initial_state, nil,
91- !!reflect_input, !!reflect_output, xor_output, name)
48+
49+ ::Class.new(self) do
50+ @bitsize = bitsize
51+ @bitmask = bitmask
52+ @polynomial = polynomial
53+ @initial_crc = initial_crc
54+ @table = nil
55+ @reflect_input = !!reflect_input
56+ @reflect_output = !!reflect_output
57+ @xor_output = xor_output
58+ @name = name
59+
60+ # CRC クラスを普通に派生させた場合でも、CRC.new の基底メソッドが呼ばれるための細工
61+ define_singleton_method(:new, &Class.instance_method(:new).bind(self))
62+
63+ singleton_class.class_eval do
64+ alias_method :[], :new
65+ end
66+
67+ extend CRC::ModuleClass
68+ end
9269 end
9370
9471 def update_with_reference(seq, state)
@@ -204,14 +181,14 @@
204181
205182 def table
206183 if reflect_input
207- set_table t = CRC.build_reflect_table(bitsize, polynomial, slice: 16)
184+ @table = CRC.build_reflect_table(bitsize, polynomial, slice: 16)
208185 else
209- set_table t = CRC.build_table(bitsize, polynomial, slice: 16)
186+ @table = CRC.build_table(bitsize, polynomial, slice: 16)
210187 end
211188
212- define_singleton_method :table, self.class.superclass.instance_method(:table)
189+ singleton_class.class_eval "attr_reader :table"
213190
214- t
191+ @table
215192 end
216193
217194 case ENV["RUBY_CRC_NOFAST"].to_i
@@ -222,13 +199,60 @@
222199 else
223200 alias update update_with_reference
224201 end
202+ end
225203
226- class BasicStruct
227- alias set_table table=
228- private :set_table
204+ module ModuleClass
205+ attr_reader :bitsize, :bitmask, :polynomial, :initial_crc,
206+ :reflect_input, :reflect_output, :xor_output, :name
229207
230- undef :bitsize=, :bitmask=, :polynomial=, :initial_state=, :table=,
231- :reflect_input=, :reflect_output=, :xor_output=, :name=, :[]=
208+ alias reflect_input? reflect_input
209+ alias reflect_output? reflect_output
210+ end
211+
212+ module Utils
213+ def bitreflect8(n)
214+ n = n.to_i
215+ n = ((n & 0x55) << 1) | ((n >> 1) & 0x55)
216+ n = ((n & 0x33) << 2) | ((n >> 2) & 0x33)
217+ return ((n & 0x0f) << 4) | (n >> 4) # 0x0f
232218 end
219+
220+ def bitreflect16(n)
221+ n = n.to_i
222+ n = ((n & 0x5555) << 1) | ((n >> 1) & 0x5555)
223+ n = ((n & 0x3333) << 2) | ((n >> 2) & 0x3333)
224+ n = ((n & 0x0f0f) << 4) | ((n >> 4) & 0x0f0f)
225+ return ((n & 0x00ff) << 8) | (n >> 8) # 0x00ff
226+ end
227+
228+ def bitreflect32(n)
229+ n = n.to_i
230+ n = ((n & 0x55555555) << 1) | ((n >> 1) & 0x55555555)
231+ n = ((n & 0x33333333) << 2) | ((n >> 2) & 0x33333333)
232+ n = ((n & 0x0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f)
233+ n = ((n & 0x00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff)
234+ return ((n & 0x0000ffff) << 16) | (n >> 16) # 0x0000ffff
235+ end
236+
237+ def bitreflect64(n)
238+ n = n.to_i
239+ n = ((n & 0x5555555555555555) << 1) | ((n >> 1) & 0x5555555555555555)
240+ n = ((n & 0x3333333333333333) << 2) | ((n >> 2) & 0x3333333333333333)
241+ n = ((n & 0x0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f)
242+ n = ((n & 0x00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff)
243+ n = ((n & 0x0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff)
244+ return ((n & 0x00000000ffffffff) << 32) | (n >> 32) # 0x00000000ffffffff
245+ end
246+
247+ def bitreflect128(n)
248+ n = n.to_i
249+ n = ((n & 0x55555555555555555555555555555555) << 1) | ((n >> 1) & 0x55555555555555555555555555555555)
250+ n = ((n & 0x33333333333333333333333333333333) << 2) | ((n >> 2) & 0x33333333333333333333333333333333)
251+ n = ((n & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f) << 4) | ((n >> 4) & 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f)
252+ n = ((n & 0x00ff00ff00ff00ff00ff00ff00ff00ff) << 8) | ((n >> 8) & 0x00ff00ff00ff00ff00ff00ff00ff00ff)
253+ n = ((n & 0x0000ffff0000ffff0000ffff0000ffff) << 16) | ((n >> 16) & 0x0000ffff0000ffff0000ffff0000ffff)
254+ n = ((n & 0x00000000ffffffff00000000ffffffff) << 32) | ((n >> 32) & 0x00000000ffffffff00000000ffffffff)
255+ return ((n & 0x0000000000000000ffffffffffffffff) << 64) | (n >> 64) # 0x0000000000000000ffffffffffffffff
256+ end
233257 end
234258 end
--- trunk/crc/lib/crc/_combine.rb (revision 99)
+++ trunk/crc/lib/crc/_combine.rb (revision 100)
@@ -33,7 +33,7 @@
3333 # License:: zlib-style
3434 #--
3535
36-module CRC
36+class CRC
3737 module Aux
3838 def self.gf2_matrix_times(matrix, vector)
3939 sum = 0
@@ -53,13 +53,13 @@
5353
5454 nil
5555 end
56- end
5756
58- class Generator
59- def combine(crc1, crc2, len2)
57+ def self.combine(crc1, crc2, len2,
58+ bitsize, polynomial, initial_crc,
59+ reflect_input, reflect_output, xor_output)
6060 return crc1 unless len2 > 1
6161
62- crc1 ^= initial_state
62+ crc1 ^= initial_crc
6363
6464 odd = []
6565 even = []
--- trunk/crc/lib/crc.rb (revision 99)
+++ trunk/crc/lib/crc.rb (revision 100)
@@ -10,6 +10,8 @@
1010 end
1111 end
1212
13+require_relative "crc/version"
14+
1315 #
1416 # This is a general CRC generator.
1517 #
@@ -30,15 +32,18 @@
3032 # crc32 << s
3133 # end
3234 # p crc32 # => #<CRC::CRC32:6A632AA5>
33-# p crc32.state # => 1784883877
35+# p crc32.crc # => 1784883877
3436 # p crc32.digest # => "jc*\xA5"
3537 # p crc32.hexdigest # => "6A632AA5"
3638 #
37-module CRC
39+class CRC
3840 CRC = self
3941
4042 extend Utils
4143
44+ #
45+ # Utilities.
46+ #
4247 module Utils
4348 extend self
4449
@@ -141,20 +146,23 @@
141146
142147 extend Utils
143148
149+ #
150+ # Internal using module.
151+ #
144152 module Aux
145- def self.DIGEST(state, bitsize)
153+ def self.DIGEST(num, bitsize)
146154 bits = (bitsize + 7) / 8 * 8
147- seq = "".b
148- (bits - 8).step(0, -8) { |i| seq << yield((state >> i) & 0xff) }
155+ seq = ""
156+ (bits - 8).step(0, -8) { |i| seq << yield((num >> i) & 0xff) }
149157 seq
150158 end
151159
152- def self.digest(state, bitsize)
153- DIGEST(state, bitsize) { |n| [n].pack("C") }
160+ def self.digest(num, bitsize)
161+ DIGEST(num, bitsize) { |n| n.chr(Encoding::BINARY) }
154162 end
155163
156- def self.hexdigest(state, bitsize)
157- DIGEST(state, bitsize) { |n| "%02X" % n }
164+ def self.hexdigest(num, bitsize)
165+ DIGEST(num, bitsize) { |n| "%02X" % n }
158166 end
159167
160168 #
@@ -174,35 +182,76 @@
174182 end
175183 end
176184
177- class Generator
178- def crc(seq, state = nil)
179- finish(update(seq, setup(state)))
185+ module ModuleClass
186+ def setup(crc = nil)
187+ crc ||= initial_crc
188+ crc = CRC.bitreflect(crc, bitsize) if reflect_input? ^ reflect_output?
189+ crc ^ xor_output
180190 end
181191
182- def setup(state = nil)
183- state ||= initial_state
184- state = CRC.bitreflect(state, bitsize) if reflect_input ^ reflect_output
185- state ^ xor_output
186- end
192+ alias init setup
187193
188194 def finish(state)
189- state = CRC.bitreflect(state, bitsize) if reflect_input ^ reflect_output
195+ state = CRC.bitreflect(state, bitsize) if reflect_input? ^ reflect_output?
190196 state ^ xor_output
191197 end
192198
193- alias reflect_input? reflect_input
194- alias reflect_output? reflect_output
199+ def crc(seq, crc = nil)
200+ finish(update(seq, setup(crc)))
201+ end
195202
196- def digest(seq, state = nil)
197- Aux.digest(crc(seq, state), bitsize)
203+ def digest(seq, crc = nil)
204+ Aux.digest(crc(seq, crc), bitsize)
198205 end
199206
200- def hexdigest(seq, state = nil)
201- Aux.hexdigest(crc(seq, state), bitsize)
207+ def hexdigest(seq, crc = nil)
208+ Aux.hexdigest(crc(seq, crc), bitsize)
202209 end
203210
204- def to_s
211+ def variant?(obj)
205212 case
213+ when obj.kind_of?(CRC)
214+ mod = obj.class
215+ when obj.kind_of?(Class) && obj < CRC
216+ mod = obj
217+ else
218+ return false
219+ end
220+
221+ if bitsize == mod.bitsize &&
222+ polynomial == mod.polynomial &&
223+ reflect_input? == mod.reflect_input? &&
224+ reflect_output? == mod.reflect_output? &&
225+ xor_output == mod.xor_output
226+ true
227+ else
228+ false
229+ end
230+ end
231+
232+ #
233+ # call-seq:
234+ # combine(crc1, crc2) -> new combined crc
235+ # combine(crc1_int, crc2_int, crc2_len) -> new combined crc
236+ #
237+ def combine(*args)
238+ case args.size
239+ when 2
240+ unless args[0].kind_of?(CRC) && args[1].kind_of?(CRC)
241+ raise ArgumentError, "When given two arguments, both arguments are should be CRC instance"
242+ end
243+
244+ crc1 + crc2
245+ when 3
246+ Aux.combine(Integer(args[0].to_i), Integer(args[1].to_i), Integer(args[2].to_i),
247+ bitsize, polynomial, initial_crc, reflect_input?, reflect_output?, xor_output)
248+ else
249+ raise ArgumentError, "wrong number of arguments (given #{args.size}, expect 2..3)"
250+ end
251+ end
252+
253+ def to_str
254+ case
206255 when bitsize > 64 then width = 20
207256 when bitsize > 32 then width = 16
208257 when bitsize > 16 then width = 8
@@ -210,17 +259,17 @@
210259 else width = 2
211260 end
212261
213- if reflect_input
214- ref = ", reflect-in#{reflect_output ? "/out" : ""}"
262+ if reflect_input?
263+ ref = " reflect-in#{reflect_output? ? "/out" : ""}"
215264 else
216- ref = reflect_output ? ", reflect-out" : ""
265+ ref = reflect_output? ? " reflect-out" : ""
217266 end
218267
219- case initial_state
268+ case initial_crc
220269 when 0 then init = "0"
221270 when bitmask then init = "~0"
222271 when 1 then init = "1"
223- else init = "0x%0#{width}X" % initial_state
272+ else init = "0x%0#{width}X" % initial_crc
224273 end
225274
226275 case xor_output
@@ -230,15 +279,11 @@
230279 else xor = "0x%0#{width}X" % xor_output
231280 end
232281
233- if nm = name
234- "#{nm}(CRC-%d-0x%0#{width}X%s init=%s, xor=%s)" % [bitsize, polynomial, ref, init, xor]
235- else
236- "(CRC-%d-0x%0#{width}X%s init=%s, xor=%s)" % [bitsize, polynomial, ref, init, xor]
237- end
282+ "CRC-%d-0x%0#{width}X%s init=%s xor=%s" % [bitsize, polynomial, ref, init, xor]
238283 end
239284
240285 def inspect
241- "\#<#{self.class} #{to_s}>"
286+ "#{super}{#{to_str}}"
242287 end
243288
244289 def pretty_inspect(q)
@@ -246,189 +291,136 @@
246291 end
247292 end
248293
249- class BasicCRC < Struct.new(:internal_state, :initial_state, :size)
250- BasicStruct = superclass
294+ attr_accessor :state, :size
251295
252- class BasicStruct
253- alias state! internal_state
254- alias set_state! internal_state=
296+ #
297+ # call-seq:
298+ # initialize(initial_crc = nil, size = 0)
299+ # initialize(seq, initial_crc = nil, size = 0)
300+ #
301+ def initialize(*args)
302+ initialize_args(args) do |seq, initial_crc, size|
303+ m = self.class
304+ @state = m.setup((initial_crc || m.initial_crc).to_i)
305+ @size = size.to_i
306+ update(seq) if seq
255307 end
308+ end
256309
257- #
258- # call-seq:
259- # initialize(initial_state = nil, size = 0)
260- # initialize(seq, initial_state = nil, size = 0)
261- #
262- def initialize(*args)
263- initialize_args(args) do |seq, initial_state, size|
264- g = self.class::GENERATOR
265- initial_state ||= g.initial_state
266- super g.setup(initial_state.to_i), initial_state.to_i, size.to_i
267- update(seq) if seq
268- end
269- end
310+ def reset(initial_crc = nil, size = 0)
311+ m = self.class
312+ @state = m.setup((initial_crc || m.initial_crc).to_i)
313+ @size = size.to_i
314+ self
315+ end
270316
271- def reset(initial_state = self.initial_state, size = 0)
272- g = self.class::GENERATOR
273- initial_state ||= g.initial_state
274- set_state! g.setup(initial_state)
275- self.initial_state = initial_state
276- self.size = size.to_i
277- self
278- end
317+ def update(seq)
318+ @state = self.class.update(seq, state)
319+ @size += seq.bytesize
320+ self
321+ end
279322
280- def update(seq)
281- set_state! self.class::GENERATOR.update(seq, state!)
282- self.size += seq.bytesize
283- self
284- end
323+ alias << update
285324
286- alias << update
325+ def crc
326+ self.class.finish(state)
327+ end
287328
288- def state
289- self.class::GENERATOR.finish(state!)
329+ def +(crc2)
330+ raise ArgumentError, "not a CRC instance (#{crc2.inspect})" unless crc2.kind_of?(CRC)
331+ m1 = self.class
332+ m2 = crc2.class
333+ unless m1.bitsize == m2.bitsize &&
334+ m1.polynomial == m2.polynomial &&
335+ m1.reflect_input? == m2.reflect_input? &&
336+ m1.reflect_output? == m2.reflect_output? &&
337+ # m1.initial_crc == m2.initial_crc &&
338+ m1.xor_output == m2.xor_output
339+ raise ArgumentError, "different CRC module (#{m1.inspect} and #{m2.inspect})"
290340 end
341+ m1.new(m1.combine(crc, crc2.crc, crc2.size), size + crc2.size)
342+ end
291343
292- def +(crc2)
293- raise ArgumentError, "not a CRC instance (#{crc2.inspect})" unless crc2.kind_of?(BasicCRC)
294- c1 = self.class
295- g1 = c1::GENERATOR
296- g2 = crc2.class::GENERATOR
297- unless g1.bitsize == g2.bitsize &&
298- g1.polynomial == g2.polynomial &&
299- g1.reflect_input == g2.reflect_input &&
300- g1.reflect_output == g2.reflect_output &&
301- # g1.initial_state == g2.initial_state &&
302- g1.xor_output == g2.xor_output
303- raise ArgumentError, "different CRC module (#{g1.inspect} and #{g2.inspect})"
304- end
305- c1.new(g1.combine(state, crc2.state, crc2.size), size + crc2.size)
306- end
307-
308- def ==(a)
309- case a
310- when BasicCRC
311- c1 = self.class
312- g1 = c1::GENERATOR
313- g2 = a.class::GENERATOR
314- if g1.bitsize == g2.bitsize &&
315- g1.polynomial == g2.polynomial &&
316- g1.reflect_input == g2.reflect_input &&
317- g1.reflect_output == g2.reflect_output &&
318- # g1.initial_state == g2.initial_state &&
319- g1.xor_output == g2.xor_output &&
320- state! == a.state!
321- true
322- else
323- false
324- end
325- when Integer
326- state == a
344+ def ==(a)
345+ case a
346+ when CRC
347+ m1 = self.class
348+ m2 = a.class
349+ if m1.bitsize == m2.bitsize &&
350+ m1.polynomial == m2.polynomial &&
351+ m1.reflect_input? == m2.reflect_input? &&
352+ m1.reflect_output? == m2.reflect_output? &&
353+ # m1.initial_crc == m2.initial_crc &&
354+ m1.xor_output == m2.xor_output &&
355+ state == a.state
356+ true
327357 else
328- super
358+ false
329359 end
360+ when Integer
361+ crc == a
362+ else
363+ super
330364 end
365+ end
331366
332- alias to_i state
333- alias to_int state
367+ alias to_i crc
368+ alias to_int crc
334369
335- def to_a
336- [state]
337- end
370+ def to_a
371+ [crc]
372+ end
338373
339- def digest
340- Aux.DIGEST(state, self.class::GENERATOR.bitsize) { |n| [n].pack("C") }
341- end
374+ def digest
375+ Aux.digest(crc, self.class.bitsize)
376+ end
342377
343- # return digest as internal state
344- def digest!
345- Aux.DIGEST(state!, self.class::GENERATOR.bitsize) { |n| [n].pack("C") }
346- end
378+ # return digest as internal state
379+ def digest!
380+ Aux.digest(state, self.class.bitsize)
381+ end
347382
348- def hexdigest
349- Aux.DIGEST(state, self.class::GENERATOR.bitsize) { |n| "%02X" % n }
350- end
383+ def hexdigest
384+ Aux.hexdigest(crc, self.class.bitsize)
385+ end
351386
352- # return hex-digest as internal state
353- def hexdigest!
354- Aux.DIGEST(state!, self.class::GENERATOR.bitsize) { |n| "%02X" % n }
355- end
387+ # return hex-digest as internal state
388+ def hexdigest!
389+ Aux.hexdigest(state, self.class.bitsize)
390+ end
356391
357- alias to_str hexdigest
358- alias to_s hexdigest
392+ alias to_str hexdigest
393+ alias to_s hexdigest
359394
360- def inspect
361- "\#<#{self.class}:#{hexdigest}>"
362- end
395+ def inspect
396+ "\#<#{self.class}:#{hexdigest}>"
397+ end
363398
364- def pretty_inspect(q)
365- q.text inspect
366- end
399+ def pretty_inspect(q)
400+ q.text inspect
401+ end
367402
368- class << self
369- alias [] new
370-
371- #
372- # call-seq:
373- # combine(crc1, crc2) -> new combined crc
374- # combine(crc1_int, crc2_int, crc2_len) -> new combined crc
375- #
376- def combine(crc1, crc2, len2 = nil)
377- return crc1 + crc2 if crc1.kind_of?(BasicCRC) && crc2.kind_of?(BasicCRC)
378- self::GENERATOR.combine(crc1.to_i, crc2.to_i, len2)
403+ private
404+ def initialize_args(args)
405+ case args.size
406+ when 0
407+ yield nil, nil, 0
408+ when 1
409+ if args[0].kind_of?(String)
410+ yield args[0], nil, 0
411+ else
412+ yield nil, args[0], 0
379413 end
380-
381- def crc(seq, state = nil)
382- self::GENERATOR.crc(seq, state)
383- end
384-
385- def digest(seq, state = nil)
386- Aux.digest(self::GENERATOR.crc(seq, state), self::GENERATOR.bitsize)
387- end
388-
389- def hexdigest(seq, state = nil)
390- Aux.hexdigest(self::GENERATOR.crc(seq, state), self::GENERATOR.bitsize)
391- end
392-
393- def inspect
394- if const_defined?(:GENERATOR)
395- if nm = name
396- "#{nm}(#{self::GENERATOR.to_s})"
397- else
398- super.sub(/(?=\>$)/) { " #{self::GENERATOR.to_s}" }
399- end
400- else
401- super
402- end
403- end
404-
405- def pretty_inspect(q)
406- q.text inspect
407- end
408- end
409-
410- private
411- def initialize_args(args)
412- case args.size
413- when 0
414- yield nil, nil, 0
415- when 1
416- if args[0].kind_of?(String)
417- yield args[0], nil, 0
418- else
419- yield nil, args[0], 0
420- end
421- when 2
422- if args[0].kind_of?(String)
423- yield args[0], args[1], 0
424- else
425- yield nil, args[0], args[1].to_i
426- end
427- when 3
428- yield args[0], args[1], args[2].to_i
414+ when 2
415+ if args[0].kind_of?(String)
416+ yield args[0], args[1], 0
429417 else
430- raise ArgumentError, "wrong argument size (given #{args.size}, expect 0..3)"
418+ yield nil, args[0], args[1].to_i
431419 end
420+ when 3
421+ yield args[0], args[1], args[2].to_i
422+ else
423+ raise ArgumentError, "wrong argument size (given #{args.size}, expect 0..3)"
432424 end
433425 end
434426
@@ -443,24 +435,17 @@
443435
444436 alias [] lookup
445437
446- def crc(modulename, seq, state = nil)
447- lookup(modulename).crc(seq, state)
438+ def crc(modulename, seq, crc = nil)
439+ lookup(modulename).crc(seq, crc)
448440 end
449441
450- def digest(modulename, seq, state = nil)
451- lookup(modulename).digest(seq, state)
442+ def digest(modulename, seq, crc = nil)
443+ lookup(modulename).digest(seq, crc)
452444 end
453445
454- def hexdigest(modulename, seq, state = nil)
455- lookup(modulename).hexdigest(seq, state)
446+ def hexdigest(modulename, seq, crc = nil)
447+ lookup(modulename).hexdigest(seq, crc)
456448 end
457-
458- def create_module(bitsize, polynomial, initial_state = 0, refin = true, refout = true, xor = ~0, name = nil)
459- g = Generator.new(bitsize, polynomial, initial_state, refin, refout, xor, name)
460- crc = Class.new(BasicCRC)
461- crc.const_set :GENERATOR, g
462- crc
463- end
464449 end
465450
466451 require_relative "crc/_modules"
@@ -469,10 +454,11 @@
469454 #
470455 # Create CRC module classes.
471456 #
472- LIST.each do |bitsize, polynomial, refin, refout, initial_state, xor, check, *names|
457+ LIST.each do |bitsize, polynomial, refin, refout, initial_crc, xor, check, *names|
458+ names.flatten!
473459 names.map! { |nm| nm.freeze }
474460
475- crc = create_module(bitsize, polynomial, initial_state, refin, refout, xor, names[0])
461+ crc = CRC.new(bitsize, polynomial, initial_crc, refin, refout, xor, names[0])
476462 crc.const_set :NAME, names
477463
478464 names.each do |nm|
@@ -481,31 +467,36 @@
481467 raise NameError, "collision crc-module name: #{nm} (#{crc::GENERATOR} and #{MODULE_TABLE[nm1]::GENERATOR})"
482468 end
483469 MODULE_TABLE[nm1] = crc
470+
471+ name = nm.sub(/(?<=\bCRC)-(?=\d+)/, "").gsub(/[\W]+/, "_")
472+ const_set(name, crc)
473+
474+ define_singleton_method(name.upcase, ->(*args) { crc.new(*args) })
475+ define_singleton_method(name.downcase, ->(*args) {
476+ if args.size == 0
477+ crc
478+ else
479+ crc.crc(*args)
480+ end
481+ })
484482 end
485- name = names[0].sub(/(?<=\bCRC)-(?=\d+)/, "").gsub(/[\W]+/, "_")
486- const_set(name, crc)
487483
488484 check = Integer(check.to_i) if check
489485 crc.const_set :CHECK, check
490-
491- g = crc::GENERATOR
492- define_singleton_method(name.upcase, ->(*args) { crc.new(*args) })
493- define_singleton_method(name.downcase, ->(*args) { g.crc(*args) })
494486 end
495487
496488 if $0 == __FILE__
497489 $stderr.puts "#{__FILE__}:#{__LINE__}: SELF CHECK for CRC modules (#{File.basename($".grep(/_(?:byruby|turbo)/)[0]||"")})\n"
498490 MODULE_TABLE.values.uniq.each do |crc|
499- g = crc::GENERATOR
500491 check = crc::CHECK
501- checked = g.crc("123456789")
492+ checked = crc.crc("123456789")
502493 case check
503494 when nil
504- $stderr.puts "| %20s(\"123456789\") = %16X (check only)\n" % [g.name, checked]
495+ $stderr.puts "| %20s(\"123456789\") = %16X (check only)\n" % [crc.name, checked]
505496 when checked
506497 ;
507498 else
508- $stderr.puts "| %20s(\"123456789\") = %16X (expect to %X)\n" % [g.name, checked, check]
499+ $stderr.puts "| %20s(\"123456789\") = %16X (expect to %X)\n" % [crc.name, checked, check]
509500 end
510501 end
511502 $stderr.puts "#{__FILE__}:#{__LINE__}: DONE SELF CHECK\n"
--- trunk/crc/gemstub.rb (revision 99)
+++ trunk/crc/gemstub.rb (revision 100)
@@ -1,12 +1,13 @@
1+require_relative "lib/crc/version"
2+
13 GEMSTUB = Gem::Specification.new do |s|
24 s.name = "crc"
3- s.version = "0.2"
5+ s.version = CRC::VERSION
46 s.summary = "general CRC generator"
57 s.description = <<EOS
68 This is a general CRC (Cyclic Redundancy Check) generator for ruby.
7-It is written by pure ruby with based on slice-by-eight algorithm (slice-by-16 algorithm as byte-order free and byte-alignment free).
8-Included built-in CRC modules are CRC-32, CRC-64-XZ, CRC-64-ECMA, CRC-64-ISO, CRC-16-CCITT, CRC-16-IBM, CRC-8, CRC-5-USB, CRC-5-EPC and many more.
9-Additional your customized CRC modules are defined to posible.
9+It is written by pure ruby.
10+Customization is posible for 1 to 64 bit width, any polynomial primitives, and with/without bit reflection input/output.
1011 If you need more speed, please use crc-turbo.
1112 EOS
1213 s.homepage = "https://osdn.jp/projects/rutsubo/"
@@ -15,7 +16,7 @@
1516 s.email = "dearblue@users.osdn.me"
1617
1718 s.required_ruby_version = ">= 2.0"
18- s.add_development_dependency "rake", "~> 11.0"
19+ s.add_development_dependency "rake"
1920 end
2021
2122 EXTRA << "benchmark.rb"
--- trunk/crc/HISTORY.ja.md (revision 99)
+++ trunk/crc/HISTORY.ja.md (revision 100)
@@ -2,6 +2,28 @@
22
33 # crc for ruby の更新履歴
44
5+## crc-0.3 (平成28年7月31日 日曜日)
6+
7+互換性を損なう変更があります。
8+
9+ * CRC::BasicCRC クラスと CRC::Generator クラスを、CRC クラスに統合
10+ * ruby オブジェクト CRC をモジュールからクラスに変更しました。
11+ * CRC::BasicCRC クラスと CRC::Generator クラスを削除しました。
12+ * crc-0.2 まで CRC::BasicCRC の派生クラスだった各 crc モジュールは
13+ CRC クラスから派生するようになりました。
14+ * CRC.create\_module を削除し、CRC.new に統合
15+ * crc-0.2 まであった CRC.create\_module メソッドを削除しました。
16+ * CRC.new メソッドが変わりの役割を担うようになりました。
17+ * crc モジュールの別名も CRC クラスの定数 (クラスの別名) として追加するように変更
18+ * CRC としての整数値を得るメソッドを引数なしで呼び出した場合、CRC モジュールを返すように変更
19+ * 例えば ``CRC.crc32`` を引数なしで呼び出すと、CRC::CRC32 クラスオブジェクトが返るようになりました。
20+ * CRC-64-ISO の修正
21+ * CRC モジュール名の整理
22+ * 初期値以外が同じかどうかを確認する CRC.variant? メソッドを追加
23+ * ``CRC#initial_crc`` を廃止
24+ * 定義が不確かな CRC モジュールを無効化
25+ * (実験的) 任意の CRC 値から逆算してバイト列を生成する機能 CRC.acrc (crc/acrc.rb) を追加
26+
527 ## crc-0.2 (平成28年5月15日 (日))
628
729 * CRC モジュールの追加と修正
--- trunk/crc/README.md (revision 99)
+++ trunk/crc/README.md (revision 100)
@@ -7,7 +7,7 @@
77
88 Included built-in CRC modules are CRC-32, CRC-64-ECMA, CRC-64-ISO, CRC-16-CCITT, CRC-16-IBM, CRC-8, CRC-5-USB, CRC-5-EPC and many more.
99
10-Additional your customized CRC modules are defined to posible.
10+Customization is posible for 1 to 64 bit width, any polynomial primitives, and with/without bit reflection input/output.
1111
1212 This library is slower than ×85+ of zlib/crc32, and slower than ×120+ of extlzma/crc32 on FreeBSD 10.3R amd64.
1313
@@ -20,51 +20,98 @@
2020 * author: dearblue (mailto:dearblue@users.osdn.me)
2121 * report issue to: <https://osdn.jp/projects/rutsubo/ticket/>
2222 * how to install: ``gem install crc``
23- * version: 0.2
24- * release quality: thechnical preview
23+ * version: 0.3
24+ * release quality: technical preview
2525 * licensing: BSD-2-Clause<br>any parts are under Creative Commons License Zero (CC0 / Public Domain), and zlib-style License.
2626 * dependency gems: none
27- * dependency external c libraries: none
28- * bundled external c libraries: none
27+ * dependency external C libraries: none
28+ * bundled external C libraries: none
2929
3030
31-## Features
31+## API Guide
3232
33-This examples are used CRC-32 module. Please see CRC::BasicCRC for more details.
33+This examples are used CRC-32 module. Please see CRC for more details.
3434
35- * CRC.crc32(seq, init = 0) -> crc-32 integer (likely as ``Zlib.crc32``)
36- * CRC::CRC32.crc(seq, init = 0) -> crc-32 integer (likely as ``Zlib.crc32``)
37- * CRC::CRC32.digest(seq, init = 0) -> crc-32 digest (likely as ``Digest::XXXX.digest``)
38- * CRC::CRC32.hexdigest(seq, init = 0) -> crc-32 hex-digest (likely as ``Digest::XXXX.hexdigest``)
39- * CRC::CRC32.new(init = 0) -> crc-32 context (likely as ``Digest::XXXX.new``)
40- * CRC::CRC32#update(seq) -> self (likely as ``Digest::XXXX#update``)
41- * CRC::CRC32#state -> crc-32 integer
42- * CRC::CRC32#digest -> crc-32 digest (likely as ``Digest::XXXX#digest``)
43- * CRC::CRC32#hexdigest -> crc-32 hex-digest (likely as ``Digest::XXXX#hexdigest``)
44- * CRC.crc("crc-32", seq, init = 0) -> crc-32 integer
45- * CRC.digest("crc-32", seq, init = 0) -> crc-32 digest
46- * CRC.hexdigest("crc-32", seq, init = 0) -> crc-32 hex-digest
47- * CRC::CRC32.combine(CRC.crc32("123"), CRC.crc32("456789"), 6) -> 3421780262 (likely as ``Zlib.crc32_comibne``)
48- * CRC.CRC32("123") + CRC.CRC32("456") + CRC.CRC32("789") -> &#35;&lt;CRC::CRC32:CBF43926&gt;
35+ * Calcurate by direct
4936
50-----
37+ * ``CRC.crc32(seq, init = CRC::CRC32.initial_crc) => crc-32 integer`` (likely as ``Zlib.crc32``)
38+ * ``CRC.crc32.crc(seq, init = CRC::CRC32.initial_crc) => crc-32 integer`` (likely as ``Zlib.crc32``)
39+ * ``CRC.crc32.digest(seq, init = CRC::CRC32.initial_crc) => crc-32 digest`` (likely as ``Digest::XXXX.digest``)
40+ * ``CRC.crc32.hexdigest(seq, init = 0) -> crc-32 hex-digest`` (likely as ``Digest::XXXX.hexdigest``)
41+ * ``CRC.crc32[seq, init = 0, current_length = 0] -> crc-32 generator``
42+ * ``CRC.crc32.new(seq, init = 0, current_length = 0) -> crc-32 generator``
5143
52- * CRC.create\_module(bitsize, poly, init\_state, refin, refout, xorout) -> new crc module class
44+ * Calcurate by streaming
5345
46+ * ``CRC.crc32[init = 0, current_length = 0] => crc-32 generator``
47+ * ``CRC.crc32.new(init = 0, current_length = 0) => crc-32 generator``
48+ * ``CRC.crc32#update(seq) => self`` (likely as ``Digest::XXXX.update``)
49+ * ``CRC.crc32#finish => crc-32 integer`` (likely as ``Digest::XXXX.finish``)
50+ * ``CRC.crc32#crc => crc-32 integer`` (same as ``CRC.crc32#finish``)
51+ * ``CRC.crc32#digest => crc-32 digest`` (likely as ``Digest::XXXX.digest``)
52+ * ``CRC.crc32#hexdigest => crc-32 hex-digest`` (likely as ``Digest::XXXX.hexdigest``)
53+
54+ Example:
55+
5456 ``` ruby:ruby
55- MyCRC32 = CRC.create_module(32, 0x04C11DB7)
56- p MyCRC32.class # => Class
57- p MyCRC32.hexdigest("123456789") # => "CBF43926"
57+ x = CRC.crc32.new # => #<CRC::CRC32:00000000>
58+ x.update "123" # => #<CRC::CRC32:884863D2>
59+ x.update "456789" # => #<CRC::CRC32:CBF43926>
60+ x.crc # => 3421780262
61+ x.digest # => "\xCB\xF49&"
62+ x.hexdigest # => "CBF43926"
5863 ```
5964
65+ * Combine
6066
67+ * ``CRC.combine(crc1, crc2, len2) => combined crc integer`` (likely as ``Zlib.crc32_comibne``)
68+ * ``CRC#+(right_crc) => combined crc generator``
69+
70+ Example-1:
71+
72+ ``` ruby:ruby
73+ CRC.crc32.combine(CRC.crc32("123"), CRC.crc32("456789"), 6) # => 3421780262
74+ ```
75+
76+ Example-2:
77+
78+ ``` ruby:ruby
79+ CRC.crc32["123"] + CRC.crc32["456"] + CRC.crc32["789"] # => #<CRC::CRC32:CBF43926>
80+ ```
81+
82+ * Create customized crc module
83+
84+ * ``CRC.new(bitsize, poly, initial_crc = 0, refin = true, refout = true, xor_output = ~0) => new crc module class``
85+
86+ ``` ruby:ruby
87+ MyCRC32 = CRC.new(32, 0x04C11DB7)
88+ MyCRC32.class # => Class
89+ MyCRC32.hexdigest("123456789") # => "CBF43926"
90+ MyCRC32.new("123456789") # => #<MyCRC32:CBF43926>
91+ ```
92+
93+ * Calcurate arc-crc (***EXPERIMENTAL***)
94+
95+ * ``CRC.acrc(pre, post = nil, want_crc = 0) => arc-crc byte string``
96+
97+ ``` ruby:ruby
98+ a = "12"
99+ c = "789"
100+ wantcrc = 0xCBF43926
101+ b = CRC.crc32.acrc(a, c, wantcrc) # => "3456"
102+ CRC.crc32[a + b + c] # => #<CRC::CRC32:CBF43926>
103+ ```
104+
105+ See CRC::ModuleClass.acrc for more detail.
106+
107+
61108 ## Built-in CRC modules
62109
63110 ``` shell:shell
64-% ruby -rcrc -e 'puts CRC::MODULE_TABLE.values.uniq.map { |m| m::GENERATOR.name }.join(", ")'
111+% ruby -rcrc -e 'puts CRC::MODULE_TABLE.values.uniq.map { |m| m.name }.join(", ")'
65112 ```
66113
67-CRC-1, CRC-3-ROHC, CRC-4-INTERLAKEN, CRC-4-ITU, CRC-5-EPC, CRC-5-ITU, CRC-5-USB, CRC-6-CDMA2000-A, CRC-6-CDMA2000-B, CRC-6-DARC, CRC-6-ITU, CRC-7, CRC-7-MVB, CRC-7-ROHC, CRC-7-UMTS, CRC-8, CRC-8-CCITT, CRC-8-MAXIM, CRC-8-DARC, CRC-8-SAE, CRC-8-WCDMA, CRC-8-CDMA2000, CRC-8-DVB-S2, CRC-8-EBU, CRC-8-I-CODE, CRC-8-ITU, CRC-8-LTE, CRC-8-ROHC, CRC-10, CRC-10-CDMA2000, CRC-11, CRC-11-UMTS, CRC-12-CDMA2000, CRC-12-DECT, CRC-12-UMTS, CRC-13-BBC, CRC-14-DARC, CRC-15, CRC-15-MPT1327, Chakravarty, ARC, CRC-16-ARINC, CRC-16-AUG-CCITT, CRC-16-CDMA2000, CRC-16-DECT-R, CRC-16-DECT-X, CRC-16-T10-DIF, CRC-16-DNP, CRC-16-BUYPASS, CRC-16-CCITT-FALSE, CRC-16-DDS-110, CRC-16-EN-13757, CRC-16-GENIBUS, CRC-16-LJ1200, CRC-16-MAXIM, CRC-16-MCRF4XX, CRC-16-RIELLO, CRC-16-TELEDISK, CRC-16-TMS37157, CRC-16-USB, CRC-A, KERMIT, MODBUS, X-25, XMODEM, CRC-17-CAN, CRC-21-CAN, CRC-24, CRC-24-Radix-64, CRC-24-OPENPGP, CRC-24-BLE, CRC-24-FLEXRAY-A, CRC-24-FLEXRAY-B, CRC-24-INTERLAKEN, CRC-24-LTE-A, CRC-24-LTE-B, CRC-30, CRC-30-CDMA, CRC-31-PHILIPS, CRC-32, CRC-32-BZIP2, CRC-32C, CRC-32D, CRC-32-MPEG-2, CRC-32-POSIX, CRC-32K, CRC-32K2, CRC-32Q, JAMCRC, XFER, CRC-40-GSM, CRC-64, CRC-64-ECMA, CRC-64-WE, CRC-64-ISO
114+CRC-1, CRC-3-ROHC, CRC-4-INTERLAKEN, CRC-4-ITU, CRC-5-EPC, CRC-5-ITU, CRC-5-USB, CRC-6-CDMA2000-A, CRC-6-CDMA2000-B, CRC-6-DARC, CRC-6-ITU, CRC-7, CRC-7-MVB, CRC-7-ROHC, CRC-7-UMTS, CRC-8, CRC-8-CCITT, CRC-8-MAXIM, CRC-8-DARC, CRC-8-SAE, CRC-8-WCDMA, CRC-8-CDMA2000, CRC-8-DVB-S2, CRC-8-EBU, CRC-8-I-CODE, CRC-8-ITU, CRC-8-LTE, CRC-8-ROHC, CRC-10, CRC-10-CDMA2000, CRC-11, CRC-11-UMTS, CRC-12-CDMA2000, CRC-12-DECT, CRC-12-UMTS, CRC-13-BBC, CRC-14-DARC, CRC-15, CRC-15-MPT1327, Chakravarty, CRC-16, CRC-16-ARINC, CRC-16-AUG-CCITT, CRC-16-CDMA2000, CRC-16-DECT-R, CRC-16-DECT-X, CRC-16-T10-DIF, CRC-16-DNP, CRC-16-BUYPASS, CRC-16-CCITT-FALSE, CRC-16-DDS-110, CRC-16-EN-13757, CRC-16-GENIBUS, CRC-16-LJ1200, CRC-16-MAXIM, CRC-16-MCRF4XX, CRC-16-RIELLO, CRC-16-TELEDISK, CRC-16-TMS37157, CRC-16-USB, CRC-16-A, CRC-16-KERMIT, CRC-16-MODBUS, CRC-16-X-25, CRC-16-XMODEM, CRC-17-CAN, CRC-21-CAN, CRC-24, CRC-24-Radix-64, CRC-24-OPENPGP, CRC-24-BLE, CRC-24-FLEXRAY-A, CRC-24-FLEXRAY-B, CRC-24-INTERLAKEN, CRC-24-LTE-A, CRC-24-LTE-B, CRC-30, CRC-30-CDMA, CRC-31-PHILIPS, CRC-32, CRC-32-BZIP2, CRC-32C, CRC-32D, CRC-32-MPEG-2, CRC-32-POSIX, CRC-32K, CRC-32K2, CRC-32Q, CRC-32-JAMCRC, CRC-32-XFER, CRC-40-GSM, CRC-64-XZ, CRC-64-ECMA, CRC-64-WE, CRC-64-ISO
68115
69116
70117 ## Environment variables for behavior
@@ -75,6 +122,69 @@
75122 * ``RUBY_CRC_NOFAST=3``: Switch to reference algorithm from slice-by-16 algorithm. Slower than about 7% (when CRC-32).
76123
77124
78-## About CRC::Generator#combine
125+## About CRC.combine
79126
80-CRC::Generator#combine is ported from Mark Adler's crccomb.c in https://stackoverflow.com/questions/29915764/generic-crc-8-16-32-64-combine-implementation#29928573 .
127+CRC.combine is ported from Mark Adler's crccomb.c in <https://stackoverflow.com/questions/29915764/generic-crc-8-16-32-64-combine-implementation#29928573>.
128+
129+
130+## arc-crc (***EXPERIMENTAL***)
131+
132+(Written in japanese from here)
133+
134+crc-0.3 にて、任意の CRC となるバイト列を逆算する機能が***実験的に***追加されました。
135+
136+今のところは、reflect-input/output 限定となっています。
137+
138+``require "crc/acrc"`` にて、その機能が利用可能となります。
139+
140+名前の由来は、arc-sin などの C 関数である asin と同様に、arc-crc => acrc となっています。
141+
142+以下は使用例です。
143+
144+ * 文字列 "123456789????" を CRC32 した場合に 0 となるような、???? の部分を逆算する
145+
146+ ``` ruby:ruby
147+ require "crc/acrc"
148+
149+ seq = "123456789"
150+ seq << CRC.crc32.acrc(seq)
151+ p CRC.crc32[seq] # => #<CRC::CRC32:00000000>
152+ ```
153+
154+ * 文字列 "123456789????ABCDEFG" の、???? の部分を逆算する
155+
156+ ``` ruby:ruby
157+ require "crc/acrc"
158+
159+ seq1 = "123456789"
160+ seq2 = "ABCDEFG"
161+ seq = seq1 + CRC.crc32.acrc(seq1, seq2) + seq2
162+ p CRC.crc32[seq] # => #<CRC::CRC32:00000000>
163+ ```
164+
165+ * 文字列 "123456789????ABCDEFG" を CRC32 した場合に 0x12345678 となるような、???? の部分を逆算する
166+
167+ ``` ruby:ruby
168+ require "crc/acrc"
169+
170+ seq1 = "123456789"
171+ seq2 = "ABCDEFG"
172+ target_crc = 0x12345678
173+ seq = seq1 + CRC.crc32.acrc(seq1, seq2, target_crc) + seq2
174+ p CRC.crc32[seq] # => #<CRC::CRC32:12345678>
175+ ```
176+
177+ * 独自仕様の CRC モジュールにも対応
178+
179+ ``` ruby:ruby
180+ require "crc/acrc"
181+
182+ seq1 = "123456789"
183+ seq2 = "ABCDEFG"
184+ target_crc = 0x12345678
185+ MyCRC = CRC.new(29, rand(1 << 29) | 1)
186+ seq = seq1 + MyCRC.acrc(seq1, seq2, target_crc) + seq2
187+ p MyCRC[seq] # => #<MyCRC:12345678>
188+ ```
189+
190+[EOF]
--- trunk/crc/benchmark.rb (revision 99)
+++ trunk/crc/benchmark.rb (revision 100)
@@ -9,8 +9,9 @@
99 require "crc"
1010 begin; require "extlzma"; rescue LoadError; no_extlzma = true; end
1111 begin; require "digest/crc"; rescue LoadError; no_digest_crc = true; end
12+begin; require "crc32"; rescue LoadError; no_crc32 = true; end
1213
13-def measure(generator_name)
14+def measure(size, generator_name)
1415 print " * measuring for #{generator_name}..."
1516 $stdout.flush
1617 realms = 5.times.map do
@@ -19,7 +20,7 @@
1920 $stdout.flush
2021 real
2122 end.min
22- puts " (#{(realms * 100).round / 100.0} ms.)\n"
23+ printf " (%.2f ms.) (peak: %0.2f MiB / s)\n", realms, size / (realms / 1000)
2324 [generator_name, realms]
2425 end
2526
@@ -38,17 +39,22 @@
3839 #s = SecureRandom.random_bytes(size << 20)
3940 s = "0" * (size << 20)
4041
41-crc = measure("ruby-crc/crc32") { CRC.crc32(s) }[1]
42+crc = measure(size, "crc/crc32") { CRC.crc32(s) }[1]
4243 comparisons = []
43-comparisons << measure("zlib/crc-32") { Zlib.crc32(s) }
44-comparisons << measure("extlzma/crc-32") { LZMA.crc32(s) } unless no_extlzma
45-comparisons << measure("digest/crc-32") { Digest::CRC32.digest(s) } unless no_digest_crc
46-comparisons << measure("ruby-crc/crc-64") { CRC.crc64(s) }
47-comparisons << measure("extlzma/crc-64") { LZMA.crc64(s) } unless no_extlzma
44+comparisons << measure(size, "zlib/crc-32") { Zlib.crc32(s) }
45+comparisons << measure(size, "extlzma/crc-32") { LZMA.crc32(s) } unless no_extlzma
46+comparisons << measure(size, "digest/crc-32") { Digest::CRC32.digest(s) } unless no_digest_crc
47+comparisons << measure(size, "crc32/crc-32") { Crc32.calculate(s, s.bytesize, 0) } unless no_crc32
48+comparisons << measure(size, "crc/crc-64") { CRC.crc64(s) }
49+comparisons << measure(size, "extlzma/crc-64") { LZMA.crc64(s) } unless no_extlzma
50+comparisons << measure(size, "crc/crc-5-usb") { CRC.crc5_usb(s) }
51+comparisons << measure(size, "crc/crc-16-usb") { CRC.crc16_usb(s) }
52+comparisons << measure(size, "crc/crc-32-posix") { CRC.crc32_posix(s) }
53+comparisons << measure(size, "crc/crc-32c") { CRC.crc32c(s) }
4854
4955 puts <<'EOS'
5056 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
51- (slowly at over 1.0)
57+ (ruby-crc/crc32 is slowly at over 1.0)
5258 EOS
5359
5460 comparisons.each do |name, meas|
旧リポジトリブラウザで表示