1 /* id.c : operations on node-revision IDs
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 <string.h>
24 #include <stdlib.h>
25 
26 #include "id.h"
27 #include "../libsvn_fs/fs-loader.h"
28 
29 
30 
31 typedef struct id_private_t {
32   const char *node_id;
33   const char *copy_id;
34   const char *txn_id;
35 } id_private_t;
36 
37 
38 /* Accessing ID Pieces.  */
39 
40 const char *
svn_fs_base__id_node_id(const svn_fs_id_t * id)41 svn_fs_base__id_node_id(const svn_fs_id_t *id)
42 {
43   id_private_t *pvt = id->fsap_data;
44 
45   return pvt->node_id;
46 }
47 
48 
49 const char *
svn_fs_base__id_copy_id(const svn_fs_id_t * id)50 svn_fs_base__id_copy_id(const svn_fs_id_t *id)
51 {
52   id_private_t *pvt = id->fsap_data;
53 
54   return pvt->copy_id;
55 }
56 
57 
58 const char *
svn_fs_base__id_txn_id(const svn_fs_id_t * id)59 svn_fs_base__id_txn_id(const svn_fs_id_t *id)
60 {
61   id_private_t *pvt = id->fsap_data;
62 
63   return pvt->txn_id;
64 }
65 
66 
67 svn_string_t *
svn_fs_base__id_unparse(const svn_fs_id_t * id,apr_pool_t * pool)68 svn_fs_base__id_unparse(const svn_fs_id_t *id,
69                         apr_pool_t *pool)
70 {
71   id_private_t *pvt = id->fsap_data;
72 
73   return svn_string_createf(pool, "%s.%s.%s",
74                             pvt->node_id, pvt->copy_id, pvt->txn_id);
75 }
76 
77 
78 /*** Comparing node IDs ***/
79 
80 svn_boolean_t
svn_fs_base__id_eq(const svn_fs_id_t * a,const svn_fs_id_t * b)81 svn_fs_base__id_eq(const svn_fs_id_t *a,
82                    const svn_fs_id_t *b)
83 {
84   id_private_t *pvta = a->fsap_data, *pvtb = b->fsap_data;
85 
86   if (a == b)
87     return TRUE;
88   if (strcmp(pvta->node_id, pvtb->node_id) != 0)
89      return FALSE;
90   if (strcmp(pvta->copy_id, pvtb->copy_id) != 0)
91     return FALSE;
92   if (strcmp(pvta->txn_id, pvtb->txn_id) != 0)
93     return FALSE;
94   return TRUE;
95 }
96 
97 
98 svn_boolean_t
svn_fs_base__id_check_related(const svn_fs_id_t * a,const svn_fs_id_t * b)99 svn_fs_base__id_check_related(const svn_fs_id_t *a,
100                               const svn_fs_id_t *b)
101 {
102   id_private_t *pvta = a->fsap_data, *pvtb = b->fsap_data;
103 
104   if (a == b)
105     return TRUE;
106 
107   return (strcmp(pvta->node_id, pvtb->node_id) == 0);
108 }
109 
110 
111 svn_fs_node_relation_t
svn_fs_base__id_compare(const svn_fs_id_t * a,const svn_fs_id_t * b)112 svn_fs_base__id_compare(const svn_fs_id_t *a,
113                         const svn_fs_id_t *b)
114 {
115   if (svn_fs_base__id_eq(a, b))
116     return svn_fs_node_unchanged;
117   return (svn_fs_base__id_check_related(a, b) ? svn_fs_node_common_ancestor
118                                               : svn_fs_node_unrelated);
119 }
120 
121 
122 
123 /* Creating ID's.  */
124 
125 static id_vtable_t id_vtable = {
126   svn_fs_base__id_unparse,
127   svn_fs_base__id_compare
128 };
129 
130 
131 svn_fs_id_t *
svn_fs_base__id_create(const char * node_id,const char * copy_id,const char * txn_id,apr_pool_t * pool)132 svn_fs_base__id_create(const char *node_id,
133                        const char *copy_id,
134                        const char *txn_id,
135                        apr_pool_t *pool)
136 {
137   svn_fs_id_t *id = apr_palloc(pool, sizeof(*id));
138   id_private_t *pvt = apr_palloc(pool, sizeof(*pvt));
139 
140   pvt->node_id = apr_pstrdup(pool, node_id);
141   pvt->copy_id = apr_pstrdup(pool, copy_id);
142   pvt->txn_id = apr_pstrdup(pool, txn_id);
143   id->vtable = &id_vtable;
144   id->fsap_data = pvt;
145   return id;
146 }
147 
148 
149 svn_fs_id_t *
svn_fs_base__id_copy(const svn_fs_id_t * id,apr_pool_t * pool)150 svn_fs_base__id_copy(const svn_fs_id_t *id, apr_pool_t *pool)
151 {
152   svn_fs_id_t *new_id = apr_palloc(pool, sizeof(*new_id));
153   id_private_t *new_pvt = apr_palloc(pool, sizeof(*new_pvt));
154   id_private_t *pvt = id->fsap_data;
155 
156   new_pvt->node_id = apr_pstrdup(pool, pvt->node_id);
157   new_pvt->copy_id = apr_pstrdup(pool, pvt->copy_id);
158   new_pvt->txn_id = apr_pstrdup(pool, pvt->txn_id);
159   new_id->vtable = &id_vtable;
160   new_id->fsap_data = new_pvt;
161   return new_id;
162 }
163 
164 
165 svn_fs_id_t *
svn_fs_base__id_parse(const char * data,apr_size_t len,apr_pool_t * pool)166 svn_fs_base__id_parse(const char *data,
167                       apr_size_t len,
168                       apr_pool_t *pool)
169 {
170   svn_fs_id_t *id;
171   id_private_t *pvt;
172   char *data_copy, *str;
173 
174   /* Dup the ID data into POOL.  Our returned ID will have references
175      into this memory. */
176   data_copy = apr_pstrmemdup(pool, data, len);
177 
178   /* Alloc a new svn_fs_id_t structure. */
179   id = apr_palloc(pool, sizeof(*id));
180   pvt = apr_palloc(pool, sizeof(*pvt));
181   id->vtable = &id_vtable;
182   id->fsap_data = pvt;
183 
184   /* Now, we basically just need to "split" this data on `.'
185      characters.  We will use svn_cstring_tokenize, which will put
186      terminators where each of the '.'s used to be.  Then our new
187      id field will reference string locations inside our duplicate
188      string.*/
189 
190   /* Node Id */
191   str = svn_cstring_tokenize(".", &data_copy);
192   if (str == NULL)
193     return NULL;
194   pvt->node_id = str;
195 
196   /* Copy Id */
197   str = svn_cstring_tokenize(".", &data_copy);
198   if (str == NULL)
199     return NULL;
200   pvt->copy_id = str;
201 
202   /* Txn Id */
203   str = svn_cstring_tokenize(".", &data_copy);
204   if (str == NULL)
205     return NULL;
206   pvt->txn_id = str;
207 
208   return id;
209 }
210