1/*
2 * Copyright (c) 2012 Apple, Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24
25
26#include "crc.h"
27
28
29uint64_t
30crc_reverse_init(crcInfoPtr crc)
31{
32    dispatch_once(&crc->table_init, ^{
33        gen_std_crc_table(crc);
34    });
35    return crc->descriptor->def.parms.initial_value;
36}
37
38static inline uint8_t
39crc_table_value8(uint8_t *table, uint8_t p, uint8_t crc) {
40    return table[(crc ^ p)  & 0xff] ^ (crc >> 8);
41}
42
43static inline uint16_t
44crc_table_value16(uint16_t *table, uint8_t p, uint16_t crc) {
45    return table[(crc ^ p)  & 0xff] ^ (crc >> 8);
46}
47
48static inline uint32_t
49crc_table_value32(uint32_t *table, uint8_t p, uint32_t crc) {
50    return table[(crc ^ p)  & 0xff] ^ (crc >> 8);
51}
52
53static inline uint64_t
54crc_table_value64(uint64_t *table, uint8_t p, uint64_t crc) {
55    return table[(crc ^ p)  & 0xffLL] ^ (crc >> 8);
56}
57
58uint64_t
59crc_reverse_update(crcInfoPtr crc, uint8_t *p, size_t len, uint64_t current)
60{
61    while (len--) {
62        switch (crc->descriptor->def.parms.width) {
63            case 1: current = crc_table_value8(crc->table.bytes, *p, (uint8_t) current); break;
64            case 2: current = crc_table_value16(crc->table.b16, *p, (uint16_t) current); break;
65            case 4: current = crc_table_value32(crc->table.b32, *p, (uint32_t) current); break;
66            case 8: current = crc_table_value64(crc->table.b64, *p, current); break;
67        }
68    }
69    return current;
70}
71
72
73uint64_t
74crc_reverse_final(crcInfoPtr crc, uint64_t current)
75{
76    return current ^ crc->descriptor->def.parms.final_xor;
77}
78
79uint64_t
80crc_reverse_oneshot(crcInfoPtr crc, uint8_t *p, size_t len)
81{
82    dispatch_once(&crc->table_init, ^{
83        gen_std_crc_table(crc);
84    });
85    uint64_t current = crc->descriptor->def.parms.initial_value;
86    while (len--) {
87        switch (crc->descriptor->def.parms.width) {
88            case 1: current = crc_table_value8(crc->table.bytes, *p, (uint8_t) current); break;
89            case 2: current = crc_table_value16(crc->table.b16, *p, (uint16_t) current); break;
90            case 4: current = crc_table_value32(crc->table.b32, *p, (uint32_t) current); break;
91            case 8: current = crc_table_value64(crc->table.b64, *p, current); break;
92        }
93        p++;
94    }
95    return current ^ crc->descriptor->def.parms.final_xor;
96}
97