1251881Speter/* key-gen.c --- manufacturing sequential keys for some db tables
2251881Speter *
3251881Speter * ====================================================================
4251881Speter *    Licensed to the Apache Software Foundation (ASF) under one
5251881Speter *    or more contributor license agreements.  See the NOTICE file
6251881Speter *    distributed with this work for additional information
7251881Speter *    regarding copyright ownership.  The ASF licenses this file
8251881Speter *    to you under the Apache License, Version 2.0 (the
9251881Speter *    "License"); you may not use this file except in compliance
10251881Speter *    with the License.  You may obtain a copy of the License at
11251881Speter *
12251881Speter *      http://www.apache.org/licenses/LICENSE-2.0
13251881Speter *
14251881Speter *    Unless required by applicable law or agreed to in writing,
15251881Speter *    software distributed under the License is distributed on an
16251881Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17251881Speter *    KIND, either express or implied.  See the License for the
18251881Speter *    specific language governing permissions and limitations
19251881Speter *    under the License.
20251881Speter * ====================================================================
21251881Speter */
22251881Speter
23251881Speter#include <assert.h>
24251881Speter#include <string.h>
25251881Speter
26251881Speter#define APR_WANT_STRFUNC
27251881Speter#include <apr_want.h>
28251881Speter#include <stdlib.h>
29251881Speter#include <apr.h>
30251881Speter
31251881Speter#include "key-gen.h"
32251881Speter
33251881Speter
34251881Speter
35251881Speter/*** Keys for reps and strings. ***/
36251881Speter
37251881Speter
38251881Spetervoid
39251881Spetersvn_fs_base__next_key(const char *this, apr_size_t *len, char *next)
40251881Speter{
41251881Speter  apr_size_t olen = *len;     /* remember the first length */
42251881Speter  int i = olen - 1;           /* initial index; we work backwards */
43251881Speter  char c;                     /* current char */
44251881Speter  svn_boolean_t carry = TRUE; /* boolean: do we have a carry or not?
45251881Speter                                 We start with a carry, because we're
46251881Speter                                 incrementing the number, after all. */
47251881Speter
48251881Speter  /* Leading zeros are not allowed, except for the string "0". */
49251881Speter  if ((*len > 1) && (this[0] == '0'))
50251881Speter    {
51251881Speter      *len = 0;
52251881Speter      return;
53251881Speter    }
54251881Speter
55251881Speter  for (i = (olen - 1); i >= 0; i--)
56251881Speter    {
57251881Speter      c = this[i];
58251881Speter
59251881Speter      /* Validate as we go. */
60251881Speter      if (! (((c >= '0') && (c <= '9')) || ((c >= 'a') && (c <= 'z'))))
61251881Speter        {
62251881Speter          *len = 0;
63251881Speter          return;
64251881Speter        }
65251881Speter
66251881Speter      if (carry)
67251881Speter        {
68251881Speter          if (c == 'z')
69251881Speter            next[i] = '0';
70251881Speter          else
71251881Speter            {
72251881Speter              carry = FALSE;
73251881Speter
74251881Speter              if (c == '9')
75251881Speter                next[i] = 'a';
76251881Speter              else
77251881Speter                next[i] = c + 1;
78251881Speter            }
79251881Speter        }
80251881Speter      else
81251881Speter        next[i] = c;
82251881Speter    }
83251881Speter
84251881Speter  /* The new length is OLEN, plus 1 if there's a carry out of the
85251881Speter     leftmost digit. */
86251881Speter  *len = olen + (carry ? 1 : 0);
87251881Speter
88251881Speter  /* Ensure that we haven't overrun the (ludicrous) bound on key length.
89251881Speter     Note that MAX_KEY_SIZE is a bound on the size *including*
90251881Speter     the trailing null byte. */
91251881Speter  assert(*len < MAX_KEY_SIZE);
92251881Speter
93251881Speter  /* Now we know it's safe to add the null terminator. */
94251881Speter  next[*len] = '\0';
95251881Speter
96251881Speter  /* Handle any leftover carry. */
97251881Speter  if (carry)
98251881Speter    {
99251881Speter      memmove(next+1, next, olen);
100251881Speter      next[0] = '1';
101251881Speter    }
102251881Speter}
103251881Speter
104251881Speter
105251881Speterint
106251881Spetersvn_fs_base__key_compare(const char *a, const char *b)
107251881Speter{
108251881Speter  int a_len = strlen(a);
109251881Speter  int b_len = strlen(b);
110251881Speter  int cmp;
111251881Speter
112251881Speter  if (a_len > b_len)
113251881Speter    return 1;
114251881Speter  if (b_len > a_len)
115251881Speter    return -1;
116251881Speter  cmp = strcmp(a, b);
117251881Speter  return (cmp ? (cmp / abs(cmp)) : 0);
118251881Speter}
119251881Speter
120251881Speter
121251881Spetersvn_boolean_t
122251881Spetersvn_fs_base__same_keys(const char *a, const char *b)
123251881Speter{
124251881Speter  if (! (a || b))
125251881Speter    return TRUE;
126251881Speter  if (a && (! b))
127251881Speter    return FALSE;
128251881Speter  if ((! a) && b)
129251881Speter    return FALSE;
130251881Speter  return (strcmp(a, b) == 0);
131251881Speter}
132