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
28 unsigned char *
svn__encode_uint(unsigned char * p,apr_uint64_t val)29 svn__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
53 unsigned char *
svn__encode_int(unsigned char * p,apr_int64_t val)54 svn__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
64 const unsigned char *
svn__decode_uint(apr_uint64_t * val,const unsigned char * p,const unsigned char * end)65 svn__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
93 const unsigned char *
svn__decode_int(apr_int64_t * val,const unsigned char * p,const unsigned char * end)94 svn__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