1/* key-gen.c --- manufacturing sequential keys for some db tables
2 *
3 * ====================================================================
4 *    Licensed to the Apache Software Foundation (ASF) under one
5 *    or more contributor license agreements.  See the NOTICE file
6 *    distributed with this work for additional information
7 *    regarding copyright ownership.  The ASF licenses this file
8 *    to you under the Apache License, Version 2.0 (the
9 *    "License"); you may not use this file except in compliance
10 *    with the License.  You may obtain a copy of the License at
11 *
12 *      http://www.apache.org/licenses/LICENSE-2.0
13 *
14 *    Unless required by applicable law or agreed to in writing,
15 *    software distributed under the License is distributed on an
16 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 *    KIND, either express or implied.  See the License for the
18 *    specific language governing permissions and limitations
19 *    under the License.
20 * ====================================================================
21 */
22
23#include <assert.h>
24#include <string.h>
25
26#define APR_WANT_STRFUNC
27#include <apr_want.h>
28#include <stdlib.h>
29#include <apr.h>
30
31#include "key-gen.h"
32
33
34
35/*** Keys for reps and strings. ***/
36
37
38void
39svn_fs_base__next_key(const char *this, apr_size_t *len, char *next)
40{
41  apr_size_t olen = *len;     /* remember the first length */
42  int i = olen - 1;           /* initial index; we work backwards */
43  char c;                     /* current char */
44  svn_boolean_t carry = TRUE; /* boolean: do we have a carry or not?
45                                 We start with a carry, because we're
46                                 incrementing the number, after all. */
47
48  /* Leading zeros are not allowed, except for the string "0". */
49  if ((*len > 1) && (this[0] == '0'))
50    {
51      *len = 0;
52      return;
53    }
54
55  for (i = (olen - 1); i >= 0; i--)
56    {
57      c = this[i];
58
59      /* Validate as we go. */
60      if (! (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z'))))
61        {
62          *len = 0;
63          return;
64        }
65
66      if (carry)
67        {
68          if (c == 'z')
69            next[i] = '0';
70          else
71            {
72              carry = FALSE;
73
74              if (c == '9')
75                next[i] = 'a';
76              else
77                next[i] = c + 1;
78            }
79        }
80      else
81        next[i] = c;
82    }
83
84  /* The new length is OLEN, plus 1 if there's a carry out of the
85     leftmost digit. */
86  *len = olen + (carry ? 1 : 0);
87
88  /* Ensure that we haven't overrun the (ludicrous) bound on key length.
89     Note that MAX_KEY_SIZE is a bound on the size *including*
90     the trailing null byte. */
91  assert(*len < MAX_KEY_SIZE);
92
93  /* Now we know it's safe to add the null terminator. */
94  next[*len] = '\0';
95
96  /* Handle any leftover carry. */
97  if (carry)
98    {
99      memmove(next+1, next, olen);
100      next[0] = '1';
101    }
102}
103
104
105int
106svn_fs_base__key_compare(const char *a, const char *b)
107{
108  int a_len = strlen(a);
109  int b_len = strlen(b);
110  int cmp;
111
112  if (a_len > b_len)
113    return 1;
114  if (b_len > a_len)
115    return -1;
116  cmp = strcmp(a, b);
117  return (cmp ? (cmp / abs(cmp)) : 0);
118}
119
120
121svn_boolean_t
122svn_fs_base__same_keys(const char *a, const char *b)
123{
124  if (! (a || b))
125    return TRUE;
126  if (a && (! b))
127    return FALSE;
128  if ((! a) && b)
129    return FALSE;
130  return (strcmp(a, b) == 0);
131}
132