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