aboutsummaryrefslogtreecommitdiff
path: root/subversion/libsvn_subr/encode.c
diff options
context:
space:
mode:
Diffstat (limited to 'subversion/libsvn_subr/encode.c')
-rw-r--r--subversion/libsvn_subr/encode.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/subversion/libsvn_subr/encode.c b/subversion/libsvn_subr/encode.c
new file mode 100644
index 000000000000..503277cd9e2f
--- /dev/null
+++ b/subversion/libsvn_subr/encode.c
@@ -0,0 +1,107 @@
+/*
+ * encode.c: various data encoding routines
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ */
+
+#include "private/svn_subr_private.h"
+
+#include "svn_private_config.h"
+
+unsigned char *
+svn__encode_uint(unsigned char *p, apr_uint64_t val)
+{
+ int n;
+ apr_uint64_t v;
+
+ /* Figure out how many bytes we'll need. */
+ v = val >> 7;
+ n = 1;
+ while (v > 0)
+ {
+ v = v >> 7;
+ n++;
+ }
+
+ /* Encode the remaining bytes; n is always the number of bytes
+ coming after the one we're encoding. */
+ while (--n >= 1)
+ *p++ = (unsigned char)(((val >> (n * 7)) | 0x80) & 0xff);
+
+ *p++ = (unsigned char)(val & 0x7f);
+
+ return p;
+}
+
+unsigned char *
+svn__encode_int(unsigned char *p, apr_int64_t val)
+{
+ apr_uint64_t value = val;
+ value = value & APR_UINT64_C(0x8000000000000000)
+ ? APR_UINT64_MAX - (2 * value)
+ : 2 * value;
+
+ return svn__encode_uint(p, value);
+}
+
+const unsigned char *
+svn__decode_uint(apr_uint64_t *val,
+ const unsigned char *p,
+ const unsigned char *end)
+{
+ apr_uint64_t temp = 0;
+
+ if (end - p > SVN__MAX_ENCODED_UINT_LEN)
+ end = p + SVN__MAX_ENCODED_UINT_LEN;
+
+ /* Decode bytes until we're done. */
+ while (SVN__PREDICT_TRUE(p < end))
+ {
+ unsigned int c = *p++;
+
+ if (c < 0x80)
+ {
+ *val = (temp << 7) | c;
+ return p;
+ }
+ else
+ {
+ temp = (temp << 7) | (c & 0x7f);
+ }
+ }
+
+ return NULL;
+}
+
+const unsigned char *
+svn__decode_int(apr_int64_t *val,
+ const unsigned char *p,
+ const unsigned char *end)
+{
+ apr_uint64_t value;
+ const unsigned char *result = svn__decode_uint(&value, p, end);
+
+ value = value & 1
+ ? (APR_UINT64_MAX - value / 2)
+ : value / 2;
+ *val = (apr_int64_t)value;
+
+ return result;
+}