Merge branch 'release-2.140.101'
[feisty_meow.git] / nucleus / library / structures / checksums.cpp
1 /*****************************************************************************\
2 *                                                                             *
3 *  Name   : checksums group                                                   *
4 *  Authors: Chris Koeritz                                                     *
5 *                                                                             *
6 *******************************************************************************
7 * Copyright (c) 1992-$now By Author.  This program is free software; you can  *
8 * redistribute it and/or modify it under the terms of the GNU General Public  *
9 * License as published by the Free Software Foundation; either version 2 of   *
10 * the License or (at your option) any later version.  This is online at:      *
11 *     http://www.fsf.org/copyleft/gpl.html                                    *
12 * Please send any updates to: fred@gruntose.com                               *
13 \*****************************************************************************/
14
15 #include "checksums.h"
16
17 #include <basis/definitions.h>
18
19 using namespace basis;
20
21 namespace structures {
22
23 const int HIGHEST_MOD_VALUE = 32014;
24
25 unsigned int checksums::bizarre_checksum(const abyte *data, int length)
26 {
27   int sum = 0;
28   for (int i = 0; i < length; i++) sum += data[i] % 23 + i % 9;
29   sum = (sum % (HIGHEST_MOD_VALUE - 1)) + 1;
30   return (unsigned int)sum;
31 }
32
33 // fletcher checksum is from Dr. Dobbs Journal May 1992, pp. 32-38.
34
35 basis::un_short checksums::fletcher_checksum(const abyte *data, int length)
36 {
37   int sum1 = 0;
38   basis::un_int sum2 = 0;
39   const abyte *buffer = data;
40
41   while (length--) {
42     sum1 += int(*buffer++);
43     // check for overflow into high byte.
44     if (sum1 > 255) sum1++;
45     sum1 &= 0xFF;  // remove any bits in high byte for next sum.
46     sum2 += basis::un_int(sum1);
47   }
48   if (sum1 == 255) sum1 = 0;
49   unsigned int fletch = basis::un_int(sum2 & 0xFF);
50   fletch <<= 8;
51   fletch |= basis::un_int(sum1 & 0xFF);
52
53   return basis::un_short(fletch);
54 }
55
56 basis::un_short checksums::rolling_fletcher_checksum(basis::un_short previous, const abyte *data,
57     int len)
58 { return previous ^ fletcher_checksum(data, len); }
59
60 abyte checksums::byte_checksum(const abyte *data, int length)
61 {
62   abyte to_return = 0;
63   for (int i = 0; i < length; i++) to_return += abyte(data[i]);
64   return to_return;
65 }
66
67 basis::un_int checksums::short_checksum(const abyte *data, int length)
68 {
69   basis::un_int to_return = 0;
70   for (int i = 0; i < length; i++) to_return += data[i];
71   return to_return;
72 }
73
74 basis::un_int checksums::hash_bytes(const void *key_data, int key_length)
75 {
76   if (!key_data) return 0;  // error!
77   if (!key_length) return 0;  // ditto!
78
79   abyte *our_key = (abyte *)key_data;
80   abyte hashed[4] = { 0, 0, 0, 0 };
81
82   int fill_posn = 0;
83   for (int i = 0; i < key_length; i++) {
84     // add to the primary area.
85     hashed[fill_posn] = hashed[fill_posn] + our_key[i];
86     fill_posn++;
87     if (fill_posn >= 4) fill_posn = 0;
88     // add to the secondary area (the next in rotation after primary).
89     hashed[fill_posn] = hashed[fill_posn] + (our_key[i] / 4);
90   }
91
92   basis::un_int to_return = 0;
93   for (int j = 0; j < 4; j++) to_return = (to_return << 8) + hashed[j];
94   return to_return;
95 }
96
97 } //namespace.
98