encode.c revision 362181
1/*
2 * encode.c:  various data encoding routines
3 *
4 * ====================================================================
5 *    Licensed to the Apache Software Foundation (ASF) under one
6 *    or more contributor license agreements.  See the NOTICE file
7 *    distributed with this work for additional information
8 *    regarding copyright ownership.  The ASF licenses this file
9 *    to you under the Apache License, Version 2.0 (the
10 *    "License"); you may not use this file except in compliance
11 *    with the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 *    Unless required by applicable law or agreed to in writing,
16 *    software distributed under the License is distributed on an
17 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18 *    KIND, either express or implied.  See the License for the
19 *    specific language governing permissions and limitations
20 *    under the License.
21 * ====================================================================
22 */
23
24#include "private/svn_subr_private.h"
25
26#include "svn_private_config.h"
27
28unsigned char *
29svn__encode_uint(unsigned char *p, apr_uint64_t val)
30{
31  int n;
32  apr_uint64_t v;
33
34  /* Figure out how many bytes we'll need.  */
35  v = val >> 7;
36  n = 1;
37  while (v > 0)
38    {
39      v = v >> 7;
40      n++;
41    }
42
43  /* Encode the remaining bytes; n is always the number of bytes
44     coming after the one we're encoding.  */
45  while (--n >= 1)
46    *p++ = (unsigned char)(((val >> (n * 7)) | 0x80) & 0xff);
47
48  *p++ = (unsigned char)(val & 0x7f);
49
50  return p;
51}
52
53unsigned char *
54svn__encode_int(unsigned char *p, apr_int64_t val)
55{
56  apr_uint64_t value = val;
57  value = value & APR_UINT64_C(0x8000000000000000)
58        ? APR_UINT64_MAX - (2 * value)
59        : 2 * value;
60
61  return svn__encode_uint(p, value);
62}
63
64const unsigned char *
65svn__decode_uint(apr_uint64_t *val,
66                 const unsigned char *p,
67                 const unsigned char *end)
68{
69  apr_uint64_t temp = 0;
70
71  if (end - p > SVN__MAX_ENCODED_UINT_LEN)
72    end = p + SVN__MAX_ENCODED_UINT_LEN;
73
74  /* Decode bytes until we're done. */
75  while (SVN__PREDICT_TRUE(p < end))
76    {
77      unsigned int c = *p++;
78
79      if (c < 0x80)
80        {
81          *val = (temp << 7) | c;
82          return p;
83        }
84      else
85        {
86          temp = (temp << 7) | (c & 0x7f);
87        }
88    }
89
90  return NULL;
91}
92
93const unsigned char *
94svn__decode_int(apr_int64_t *val,
95                const unsigned char *p,
96                const unsigned char *end)
97{
98  apr_uint64_t value;
99  const unsigned char *result = svn__decode_uint(&value, p, end);
100
101  value = value & 1
102        ? (APR_UINT64_MAX - value / 2)
103        : value / 2;
104  *val = (apr_int64_t)value;
105
106  return result;
107}
108