1289177Speter/* id.c : implements FSX-internal ID functions
2289177Speter *
3289177Speter * ====================================================================
4289177Speter *    Licensed to the Apache Software Foundation (ASF) under one
5289177Speter *    or more contributor license agreements.  See the NOTICE file
6289177Speter *    distributed with this work for additional information
7289177Speter *    regarding copyright ownership.  The ASF licenses this file
8289177Speter *    to you under the Apache License, Version 2.0 (the
9289177Speter *    "License"); you may not use this file except in compliance
10289177Speter *    with the License.  You may obtain a copy of the License at
11289177Speter *
12289177Speter *      http://www.apache.org/licenses/LICENSE-2.0
13289177Speter *
14289177Speter *    Unless required by applicable law or agreed to in writing,
15289177Speter *    software distributed under the License is distributed on an
16289177Speter *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17289177Speter *    KIND, either express or implied.  See the License for the
18289177Speter *    specific language governing permissions and limitations
19289177Speter *    under the License.
20289177Speter * ====================================================================
21289177Speter */
22289177Speter
23289177Speter#include <assert.h>
24289177Speter
25289177Speter#include "id.h"
26289177Speter#include "index.h"
27289177Speter#include "util.h"
28289177Speter
29289177Speter#include "private/svn_string_private.h"
30289177Speter
31289177Speter
32289177Speter
33289177Spetersvn_boolean_t
34289177Spetersvn_fs_x__is_txn(svn_fs_x__change_set_t change_set)
35289177Speter{
36289177Speter  return change_set < SVN_FS_X__INVALID_CHANGE_SET;
37289177Speter}
38289177Speter
39289177Spetersvn_boolean_t
40289177Spetersvn_fs_x__is_revision(svn_fs_x__change_set_t change_set)
41289177Speter{
42289177Speter  return change_set > SVN_FS_X__INVALID_CHANGE_SET;
43289177Speter}
44289177Speter
45289177Spetersvn_revnum_t
46289177Spetersvn_fs_x__get_revnum(svn_fs_x__change_set_t change_set)
47289177Speter{
48289177Speter  return svn_fs_x__is_revision(change_set)
49289177Speter       ? (svn_revnum_t)change_set
50289177Speter       : SVN_INVALID_REVNUM;
51289177Speter}
52289177Speter
53289177Speterapr_int64_t
54289177Spetersvn_fs_x__get_txn_id(svn_fs_x__change_set_t change_set)
55289177Speter{
56289177Speter  return svn_fs_x__is_txn(change_set)
57289177Speter       ? -change_set + SVN_FS_X__INVALID_CHANGE_SET -1
58289177Speter       : SVN_FS_X__INVALID_TXN_ID;
59289177Speter}
60289177Speter
61289177Speter
62289177Spetersvn_fs_x__change_set_t
63289177Spetersvn_fs_x__change_set_by_rev(svn_revnum_t revnum)
64289177Speter{
65289177Speter  assert(revnum >= SVN_FS_X__INVALID_CHANGE_SET);
66289177Speter  return revnum;
67289177Speter}
68289177Speter
69289177Spetersvn_fs_x__change_set_t
70289177Spetersvn_fs_x__change_set_by_txn(apr_int64_t txn_id)
71289177Speter{
72289177Speter  assert(txn_id >= SVN_FS_X__INVALID_CHANGE_SET);
73289177Speter  return -txn_id + SVN_FS_X__INVALID_CHANGE_SET -1;
74289177Speter}
75289177Speter
76289177Speter
77289177Speter/* Parse the NUL-terminated ID part at DATA and write the result into *PART.
78289177Speter * Return TRUE if no errors were detected. */
79289177Speterstatic svn_boolean_t
80289177Speterpart_parse(svn_fs_x__id_t *part,
81289177Speter           const char *data)
82289177Speter{
83289177Speter  part->number = svn__base36toui64(&data, data);
84289177Speter  switch (data[0])
85289177Speter    {
86289177Speter      /* txn number? */
87289177Speter      case '-': part->change_set = -svn__base36toui64(&data, data + 1);
88289177Speter                return TRUE;
89289177Speter
90289177Speter      /* revision number? */
91289177Speter      case '+': part->change_set = svn__base36toui64(&data, data + 1);
92289177Speter                return TRUE;
93289177Speter
94289177Speter      /* everything else is forbidden */
95289177Speter      default:  return FALSE;
96289177Speter    }
97289177Speter}
98289177Speter
99289177Speter/* Write the textual representation of *PART into P and return a pointer
100289177Speter * to the first position behind that string.
101289177Speter */
102289177Speterstatic char *
103289177Speterpart_unparse(char *p,
104289177Speter             const svn_fs_x__id_t *part)
105289177Speter{
106289177Speter  p += svn__ui64tobase36(p, part->number);
107289177Speter  if (part->change_set >= 0)
108289177Speter    {
109289177Speter      *(p++) = '+';
110289177Speter      p += svn__ui64tobase36(p, part->change_set);
111289177Speter    }
112289177Speter  else
113289177Speter    {
114289177Speter      *(p++) = '-';
115289177Speter      p += svn__ui64tobase36(p, -part->change_set);
116289177Speter    }
117289177Speter
118289177Speter  return p;
119289177Speter}
120289177Speter
121289177Speter
122289177Speter
123289177Speter/* Operations on ID parts */
124289177Speter
125289177Spetersvn_boolean_t
126289177Spetersvn_fs_x__id_is_root(const svn_fs_x__id_t* part)
127289177Speter{
128289177Speter  return part->change_set == 0 && part->number == 0;
129289177Speter}
130289177Speter
131289177Spetersvn_boolean_t
132289177Spetersvn_fs_x__id_eq(const svn_fs_x__id_t *lhs,
133289177Speter                const svn_fs_x__id_t *rhs)
134289177Speter{
135289177Speter  return lhs->change_set == rhs->change_set && lhs->number == rhs->number;
136289177Speter}
137289177Speter
138289177Spetersvn_error_t *
139289177Spetersvn_fs_x__id_parse(svn_fs_x__id_t *part,
140289177Speter                   const char *data)
141289177Speter{
142289177Speter  if (!part_parse(part, data))
143289177Speter    return svn_error_createf(SVN_ERR_FS_MALFORMED_NODEREV_ID, NULL,
144289177Speter                             "Malformed ID string");
145289177Speter
146289177Speter  return SVN_NO_ERROR;
147289177Speter}
148289177Speter
149289177Spetersvn_string_t *
150289177Spetersvn_fs_x__id_unparse(const svn_fs_x__id_t *id,
151289177Speter                     apr_pool_t *result_pool)
152289177Speter{
153289177Speter  char string[2 * SVN_INT64_BUFFER_SIZE + 1];
154289177Speter  char *p = part_unparse(string, id);
155289177Speter
156289177Speter  return svn_string_ncreate(string, p - string, result_pool);
157289177Speter}
158289177Speter
159289177Spetervoid
160289177Spetersvn_fs_x__id_reset(svn_fs_x__id_t *part)
161289177Speter{
162289177Speter  part->change_set = SVN_FS_X__INVALID_CHANGE_SET;
163289177Speter  part->number = 0;
164289177Speter}
165289177Speter
166289177Spetersvn_boolean_t
167289177Spetersvn_fs_x__id_used(const svn_fs_x__id_t *part)
168289177Speter{
169289177Speter  return part->change_set != SVN_FS_X__INVALID_CHANGE_SET;
170289177Speter}
171289177Speter
172289177Spetervoid
173289177Spetersvn_fs_x__init_txn_root(svn_fs_x__id_t *noderev_id,
174289177Speter                        svn_fs_x__txn_id_t txn_id)
175289177Speter{
176289177Speter  noderev_id->change_set = svn_fs_x__change_set_by_txn(txn_id);
177289177Speter  noderev_id->number = SVN_FS_X__ITEM_INDEX_ROOT_NODE;
178289177Speter}
179289177Speter
180289177Spetervoid
181289177Spetersvn_fs_x__init_rev_root(svn_fs_x__id_t *noderev_id,
182289177Speter                        svn_revnum_t rev)
183289177Speter{
184289177Speter  noderev_id->change_set = svn_fs_x__change_set_by_rev(rev);
185289177Speter  noderev_id->number = SVN_FS_X__ITEM_INDEX_ROOT_NODE;
186289177Speter}
187289177Speter
188289177Speterint
189289177Spetersvn_fs_x__id_compare(const svn_fs_x__id_t *a,
190289177Speter                     const svn_fs_x__id_t *b)
191289177Speter{
192289177Speter  if (a->change_set < b->change_set)
193289177Speter    return -1;
194289177Speter  if (a->change_set > b->change_set)
195289177Speter    return 1;
196289177Speter
197289177Speter  return a->number < b->number ? -1 : a->number == b->number ? 0 : 1;
198289177Speter}
199