types.c revision 299742
156171Sru/* 256171Sru * svn_types.c : Implementation for Subversion's data types. 356171Sru * 4146523Sru * ==================================================================== 556171Sru * Licensed to the Apache Software Foundation (ASF) under one 656171Sru * or more contributor license agreements. See the NOTICE file 756171Sru * distributed with this work for additional information 856171Sru * regarding copyright ownership. The ASF licenses this file 956171Sru * to you under the Apache License, Version 2.0 (the 10146523Sru * "License"); you may not use this file except in compliance 1156171Sru * with the License. You may obtain a copy of the License at 1256171Sru * 1356171Sru * http://www.apache.org/licenses/LICENSE-2.0 14146523Sru * 1556171Sru * Unless required by applicable law or agreed to in writing, 1656171Sru * software distributed under the License is distributed on an 17146523Sru * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1856171Sru * KIND, either express or implied. See the License for the 1956171Sru * specific language governing permissions and limitations 2056171Sru * under the License. 2156171Sru * ==================================================================== 2256171Sru */ 23146523Sru 24146523Sru#include <apr_pools.h> 2556171Sru#include <apr_uuid.h> 2656171Sru 2756171Sru#include "svn_hash.h" 2856171Sru#include "svn_types.h" 2956171Sru#include "svn_error.h" 3056171Sru#include "svn_string.h" 3156171Sru#include "svn_props.h" 3256171Sru#include "svn_private_config.h" 3356171Sru 3456171Sru#include "private/svn_dep_compat.h" 3556171Sru#include "private/svn_string_private.h" 3656171Sru 3756171Srusvn_error_t * 38146523Srusvn_revnum_parse(svn_revnum_t *rev, 39160167Scperciva const char *str, 40160167Scperciva const char **endptr) 41160167Scperciva{ 42160167Scperciva const char *end; 43 44 svn_revnum_t result = (svn_revnum_t)svn__strtoul(str, &end); 45 46 if (endptr) 47 *endptr = str; 48 49 if (str == end) 50 return svn_error_createf 51 (SVN_ERR_REVNUM_PARSE_FAILURE, NULL, 52 *str == '-' ? _("Negative revision number found parsing '%s'") 53 : _("Invalid revision number found parsing '%s'"), 54 str); 55 56 /* a revision number with more than 9 digits is suspicious. 57 Have a closer look at those. */ 58 if (str + 10 <= end) 59 { 60 /* we support 32 bit revision numbers only. check for overflows */ 61 if (str + 10 < end) 62 return svn_error_createf 63 (SVN_ERR_REVNUM_PARSE_FAILURE, NULL, 64 _("Revision number longer than 10 digits '%s'"), str); 65 66 /* we support 32 bit revision numbers only. check for overflows */ 67 if (*str > '2' || (apr_uint32_t)result > APR_INT32_MAX) 68 return svn_error_createf 69 (SVN_ERR_REVNUM_PARSE_FAILURE, NULL, 70 _("Revision number too large '%s'"), str); 71 } 72 73 if (endptr) 74 *endptr = end; 75 76 *rev = result; 77 78 return SVN_NO_ERROR; 79} 80 81const char * 82svn_uuid_generate(apr_pool_t *pool) 83{ 84 apr_uuid_t uuid; 85 char *uuid_str = apr_pcalloc(pool, APR_UUID_FORMATTED_LENGTH + 1); 86 apr_uuid_get(&uuid); 87 apr_uuid_format(uuid_str, &uuid); 88 return uuid_str; 89} 90 91const char * 92svn_depth_to_word(svn_depth_t depth) 93{ 94 switch (depth) 95 { 96 case svn_depth_exclude: 97 return "exclude"; 98 case svn_depth_unknown: 99 return "unknown"; 100 case svn_depth_empty: 101 return "empty"; 102 case svn_depth_files: 103 return "files"; 104 case svn_depth_immediates: 105 return "immediates"; 106 case svn_depth_infinity: 107 return "infinity"; 108 default: 109 return "INVALID-DEPTH"; 110 } 111} 112 113 114svn_depth_t 115svn_depth_from_word(const char *word) 116{ 117 if (strcmp(word, "exclude") == 0) 118 return svn_depth_exclude; 119 if (strcmp(word, "unknown") == 0) 120 return svn_depth_unknown; 121 if (strcmp(word, "empty") == 0) 122 return svn_depth_empty; 123 if (strcmp(word, "files") == 0) 124 return svn_depth_files; 125 if (strcmp(word, "immediates") == 0) 126 return svn_depth_immediates; 127 if (strcmp(word, "infinity") == 0) 128 return svn_depth_infinity; 129 /* There's no special value for invalid depth, and no convincing 130 reason to make one yet, so just fall back to unknown depth. 131 If you ever change that convention, check callers to make sure 132 they're not depending on it (e.g., option parsing in main() ). 133 */ 134 return svn_depth_unknown; 135} 136 137const char * 138svn_node_kind_to_word(svn_node_kind_t kind) 139{ 140 switch (kind) 141 { 142 case svn_node_none: 143 return "none"; 144 case svn_node_file: 145 return "file"; 146 case svn_node_dir: 147 return "dir"; 148 case svn_node_symlink: 149 return "symlink"; 150 case svn_node_unknown: 151 default: 152 return "unknown"; 153 } 154} 155 156 157svn_node_kind_t 158svn_node_kind_from_word(const char *word) 159{ 160 if (word == NULL) 161 return svn_node_unknown; 162 163 if (strcmp(word, "none") == 0) 164 return svn_node_none; 165 else if (strcmp(word, "file") == 0) 166 return svn_node_file; 167 else if (strcmp(word, "dir") == 0) 168 return svn_node_dir; 169 else if (strcmp(word, "symlink") == 0) 170 return svn_node_symlink; 171 else 172 /* This also handles word == "unknown" */ 173 return svn_node_unknown; 174} 175 176const char * 177svn_tristate__to_word(svn_tristate_t tristate) 178{ 179 switch (tristate) 180 { 181 case svn_tristate_false: 182 return "false"; 183 case svn_tristate_true: 184 return "true"; 185 case svn_tristate_unknown: 186 default: 187 return NULL; 188 } 189} 190 191svn_tristate_t 192svn_tristate__from_word(const char *word) 193{ 194 if (word == NULL) 195 return svn_tristate_unknown; 196 else if (0 == svn_cstring_casecmp(word, "true") 197 || 0 == svn_cstring_casecmp(word, "yes") 198 || 0 == svn_cstring_casecmp(word, "on") 199 || 0 == strcmp(word, "1")) 200 return svn_tristate_true; 201 else if (0 == svn_cstring_casecmp(word, "false") 202 || 0 == svn_cstring_casecmp(word, "no") 203 || 0 == svn_cstring_casecmp(word, "off") 204 || 0 == strcmp(word, "0")) 205 return svn_tristate_false; 206 207 return svn_tristate_unknown; 208} 209 210svn_commit_info_t * 211svn_create_commit_info(apr_pool_t *pool) 212{ 213 svn_commit_info_t *commit_info 214 = apr_pcalloc(pool, sizeof(*commit_info)); 215 216 commit_info->revision = SVN_INVALID_REVNUM; 217 /* All other fields were initialized to NULL above. */ 218 219 return commit_info; 220} 221 222svn_commit_info_t * 223svn_commit_info_dup(const svn_commit_info_t *src_commit_info, 224 apr_pool_t *pool) 225{ 226 svn_commit_info_t *dst_commit_info 227 = apr_palloc(pool, sizeof(*dst_commit_info)); 228 229 dst_commit_info->date = src_commit_info->date 230 ? apr_pstrdup(pool, src_commit_info->date) : NULL; 231 dst_commit_info->author = src_commit_info->author 232 ? apr_pstrdup(pool, src_commit_info->author) : NULL; 233 dst_commit_info->revision = src_commit_info->revision; 234 dst_commit_info->post_commit_err = src_commit_info->post_commit_err 235 ? apr_pstrdup(pool, src_commit_info->post_commit_err) : NULL; 236 dst_commit_info->repos_root = src_commit_info->repos_root 237 ? apr_pstrdup(pool, src_commit_info->repos_root) : NULL; 238 239 return dst_commit_info; 240} 241 242svn_log_changed_path2_t * 243svn_log_changed_path2_create(apr_pool_t *pool) 244{ 245 svn_log_changed_path2_t *new_changed_path 246 = apr_pcalloc(pool, sizeof(*new_changed_path)); 247 248 new_changed_path->text_modified = svn_tristate_unknown; 249 new_changed_path->props_modified = svn_tristate_unknown; 250 251 return new_changed_path; 252} 253 254svn_log_changed_path2_t * 255svn_log_changed_path2_dup(const svn_log_changed_path2_t *changed_path, 256 apr_pool_t *pool) 257{ 258 svn_log_changed_path2_t *new_changed_path 259 = apr_palloc(pool, sizeof(*new_changed_path)); 260 261 *new_changed_path = *changed_path; 262 263 if (new_changed_path->copyfrom_path) 264 new_changed_path->copyfrom_path = 265 apr_pstrdup(pool, new_changed_path->copyfrom_path); 266 267 return new_changed_path; 268} 269 270svn_dirent_t * 271svn_dirent_create(apr_pool_t *result_pool) 272{ 273 svn_dirent_t *new_dirent = apr_pcalloc(result_pool, sizeof(*new_dirent)); 274 275 new_dirent->kind = svn_node_unknown; 276 new_dirent->size = SVN_INVALID_FILESIZE; 277 new_dirent->created_rev = SVN_INVALID_REVNUM; 278 new_dirent->time = 0; 279 new_dirent->last_author = NULL; 280 281 return new_dirent; 282} 283 284svn_dirent_t * 285svn_dirent_dup(const svn_dirent_t *dirent, 286 apr_pool_t *pool) 287{ 288 svn_dirent_t *new_dirent = apr_palloc(pool, sizeof(*new_dirent)); 289 290 *new_dirent = *dirent; 291 292 new_dirent->last_author = apr_pstrdup(pool, dirent->last_author); 293 294 return new_dirent; 295} 296 297svn_log_entry_t * 298svn_log_entry_create(apr_pool_t *pool) 299{ 300 svn_log_entry_t *log_entry = apr_pcalloc(pool, sizeof(*log_entry)); 301 302 return log_entry; 303} 304 305svn_log_entry_t * 306svn_log_entry_dup(const svn_log_entry_t *log_entry, apr_pool_t *pool) 307{ 308 apr_hash_index_t *hi; 309 svn_log_entry_t *new_entry = apr_palloc(pool, sizeof(*new_entry)); 310 311 *new_entry = *log_entry; 312 313 if (log_entry->revprops) 314 new_entry->revprops = svn_prop_hash_dup(log_entry->revprops, pool); 315 316 if (log_entry->changed_paths2) 317 { 318 new_entry->changed_paths2 = apr_hash_make(pool); 319 320 for (hi = apr_hash_first(pool, log_entry->changed_paths2); 321 hi; hi = apr_hash_next(hi)) 322 { 323 const void *key; 324 void *change; 325 326 apr_hash_this(hi, &key, NULL, &change); 327 328 svn_hash_sets(new_entry->changed_paths2, apr_pstrdup(pool, key), 329 svn_log_changed_path2_dup(change, pool)); 330 } 331 } 332 333 /* We can't copy changed_paths by itself without using deprecated code, 334 but we don't have to, as this function was new after the introduction 335 of the changed_paths2 field. */ 336 new_entry->changed_paths = new_entry->changed_paths2; 337 338 return new_entry; 339} 340 341svn_location_segment_t * 342svn_location_segment_dup(const svn_location_segment_t *segment, 343 apr_pool_t *pool) 344{ 345 svn_location_segment_t *new_segment = 346 apr_palloc(pool, sizeof(*new_segment)); 347 348 *new_segment = *segment; 349 if (segment->path) 350 new_segment->path = apr_pstrdup(pool, segment->path); 351 return new_segment; 352} 353