1251881Speter/*
2251881Speter * adler32.c :  routines for handling Adler-32 checksums
3251881Speter *
4251881Speter * ====================================================================
5251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
6251881Speter *    or more contributor license agreements.  See the NOTICE file
7251881Speter *    distributed with this work for additional information
8251881Speter *    regarding copyright ownership.  The ASF licenses this file
9251881Speter *    to you under the Apache License, Version 2.0 (the
10251881Speter *    "License"); you may not use this file except in compliance
11251881Speter *    with the License.  You may obtain a copy of the License at
12251881Speter *
13251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
14251881Speter *
15251881Speter *    Unless required by applicable law or agreed to in writing,
16251881Speter *    software distributed under the License is distributed on an
17251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18251881Speter *    KIND, either express or implied.  See the License for the
19251881Speter *    specific language governing permissions and limitations
20251881Speter *    under the License.
21251881Speter * ====================================================================
22251881Speter */
23251881Speter
24251881Speter
25251881Speter#include <apr.h>
26251881Speter#include <zlib.h>
27251881Speter
28251881Speter#include "private/svn_adler32.h"
29251881Speter
30251881Speter/**
31251881Speter * An Adler-32 implementation per RFC1950.
32251881Speter *
33251881Speter * "The Adler-32 algorithm is much faster than the CRC32 algorithm yet
34251881Speter * still provides an extremely low probability of undetected errors"
35251881Speter */
36251881Speter
37251881Speter/*
38251881Speter * 65521 is the largest prime less than 65536.
39251881Speter * "That 65521 is prime is important to avoid a possible large class of
40251881Speter *  two-byte errors that leave the check unchanged."
41251881Speter */
42251881Speter#define ADLER_MOD_BASE 65521
43251881Speter
44251881Speter/*
45251881Speter * Start with CHECKSUM and update the checksum by processing a chunk
46251881Speter * of DATA sized LEN.
47251881Speter */
48251881Speterapr_uint32_t
49251881Spetersvn__adler32(apr_uint32_t checksum, const char *data, apr_off_t len)
50251881Speter{
51251881Speter  /* The actual limit can be set somewhat higher but should
52251881Speter   * not be lower because the SIMD code would not be used
53251881Speter   * in that case.
54251881Speter   *
55251881Speter   * However, it must be lower than 5552 to make sure our local
56251881Speter   * implementation does not suffer from overflows.
57251881Speter   */
58251881Speter  if (len >= 80)
59251881Speter    {
60251881Speter      /* Larger buffers can be effiently handled by Marc Adler's
61251881Speter       * optimized code. Also, new zlib versions will come with
62251881Speter       * SIMD code for x86 and x64.
63251881Speter       */
64251881Speter      return (apr_uint32_t)adler32(checksum,
65251881Speter                                   (const Bytef *)data,
66251881Speter                                   (uInt)len);
67251881Speter    }
68251881Speter  else
69251881Speter    {
70251881Speter      const unsigned char *input = (const unsigned char *)data;
71251881Speter      apr_uint32_t s1 = checksum & 0xFFFF;
72251881Speter      apr_uint32_t s2 = checksum >> 16;
73251881Speter      apr_uint32_t b;
74251881Speter
75251881Speter      /* Some loop unrolling
76251881Speter       * (approx. one clock tick per byte + 2 ticks loop overhead)
77251881Speter       */
78251881Speter      for (; len >= 8; len -= 8, input += 8)
79251881Speter      {
80251881Speter        s1 += input[0]; s2 += s1;
81251881Speter        s1 += input[1]; s2 += s1;
82251881Speter        s1 += input[2]; s2 += s1;
83251881Speter        s1 += input[3]; s2 += s1;
84251881Speter        s1 += input[4]; s2 += s1;
85251881Speter        s1 += input[5]; s2 += s1;
86251881Speter        s1 += input[6]; s2 += s1;
87251881Speter        s1 += input[7]; s2 += s1;
88251881Speter      }
89251881Speter
90251881Speter      /* Adler-32 calculation as a simple two ticks per iteration loop.
91251881Speter       */
92251881Speter      while (len--)
93251881Speter        {
94251881Speter          b = *input++;
95251881Speter          s1 += b;
96251881Speter          s2 += s1;
97251881Speter        }
98251881Speter
99251881Speter      return ((s2 % ADLER_MOD_BASE) << 16) | (s1 % ADLER_MOD_BASE);
100251881Speter    }
101251881Speter}
102