⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 path.c

📁 subversion-1.4.5.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * paths.c:   a path manipulation library using svn_stringbuf_t * * ==================================================================== * Copyright (c) 2000-2004 CollabNet.  All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution.  The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals.  For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <string.h>#include <assert.h>#include <apr_file_info.h>#include <apr_lib.h>#include "svn_string.h"#include "svn_path.h"#include "svn_private_config.h"         /* for SVN_PATH_LOCAL_SEPARATOR */#include "svn_utf.h"#include "svn_io.h"                     /* for svn_io_stat() */#include "svn_ctype.h"/* The canonical empty path.  Can this be changed?  Well, change the empty   test below and the path library will work, not so sure about the fs/wc   libraries. */#define SVN_EMPTY_PATH ""/* TRUE if s is the canonical empty path, FALSE otherwise */#define SVN_PATH_IS_EMPTY(s) ((s)[0] == '\0')/* TRUE if s,n is the platform's empty path ("."), FALSE otherwise. Can   this be changed?  Well, the path library will work, not so sure about   the OS! */#define SVN_PATH_IS_PLATFORM_EMPTY(s,n) ((n) == 1 && (s)[0] == '.')const char *svn_path_internal_style(const char *path, apr_pool_t *pool){  if ('/' != SVN_PATH_LOCAL_SEPARATOR)    {      char *p = apr_pstrdup(pool, path);      path = p;      /* Convert all local-style separators to the canonical ones. */      for (; *p != '\0'; ++p)        if (*p == SVN_PATH_LOCAL_SEPARATOR)          *p = '/';    }  return svn_path_canonicalize(path, pool);  /* FIXME: Should also remove trailing /.'s, if the style says so. */}const char *svn_path_local_style(const char *path, apr_pool_t *pool){  path = svn_path_canonicalize(path, pool);  /* FIXME: Should also remove trailing /.'s, if the style says so. */  /* Internally, Subversion represents the current directory with the     empty string.  But users like to see "." . */  if (SVN_PATH_IS_EMPTY(path))    return ".";  if ('/' != SVN_PATH_LOCAL_SEPARATOR)    {      char *p = apr_pstrdup(pool, path);      path = p;      /* Convert all canonical separators to the local-style ones. */      for (; *p != '\0'; ++p)        if (*p == '/')          *p = SVN_PATH_LOCAL_SEPARATOR;    }  return path;}#ifndef NDEBUGstatic svn_boolean_tis_canonical(const char *path,             apr_size_t len){  return (! SVN_PATH_IS_PLATFORM_EMPTY(path, len)          && (len <= 1 || path[len-1] != '/'));}#endifchar *svn_path_join(const char *base,                    const char *component,                    apr_pool_t *pool){  apr_size_t blen = strlen(base);  apr_size_t clen = strlen(component);  char *path;  assert(is_canonical(base, blen));  assert(is_canonical(component, clen));  /* If the component is absolute, then return it.  */  if (*component == '/')    return apr_pmemdup(pool, component, clen + 1);  /* If either is empty return the other */  if (SVN_PATH_IS_EMPTY(base))    return apr_pmemdup(pool, component, clen + 1);  if (SVN_PATH_IS_EMPTY(component))    return apr_pmemdup(pool, base, blen + 1);  if (blen == 1 && base[0] == '/')    blen = 0; /* Ignore base, just return separator + component */  /* Construct the new, combined path. */  path = apr_palloc(pool, blen + 1 + clen + 1);  memcpy(path, base, blen);  path[blen] = '/';  memcpy(path + blen + 1, component, clen + 1);  return path;}char *svn_path_join_many(apr_pool_t *pool, const char *base, ...){#define MAX_SAVED_LENGTHS 10  apr_size_t saved_lengths[MAX_SAVED_LENGTHS];  apr_size_t total_len;  int nargs;  va_list va;  const char *s;  apr_size_t len;  char *path;  char *p;  svn_boolean_t base_is_empty = FALSE, base_is_root = FALSE;  int base_arg = 0;  total_len = strlen(base);  assert(is_canonical(base, total_len));  if (total_len == 1 && *base == '/')    base_is_root = TRUE;  else if (SVN_PATH_IS_EMPTY(base))    {      total_len = sizeof(SVN_EMPTY_PATH) - 1;      base_is_empty = TRUE;    }  saved_lengths[0] = total_len;  /* Compute the length of the resulting string. */  nargs = 0;  va_start(va, base);  while ((s = va_arg(va, const char *)) != NULL)    {      len = strlen(s);      assert(is_canonical(s, len));      if (SVN_PATH_IS_EMPTY(s))        continue;      if (nargs++ < MAX_SAVED_LENGTHS)        saved_lengths[nargs] = len;      if (*s == '/')        {          /* an absolute path. skip all components to this point and reset             the total length. */          total_len = len;          base_arg = nargs;          base_is_root = len == 1;          base_is_empty = FALSE;        }      else if (nargs == base_arg               || (nargs == base_arg + 1 && base_is_root)               || base_is_empty)        {          /* if we have skipped everything up to this arg, then the base             and all prior components are empty. just set the length to             this component; do not add a separator.  If the base is empty             we can now ignore it. */          if (base_is_empty)            {              base_is_empty = FALSE;              total_len = 0;            }          total_len += len;        }      else        {          total_len += 1 + len;        }    }  va_end(va);  /* base == "/" and no further components. just return that. */  if (base_is_root && total_len == 1)    return apr_pmemdup(pool, "/", 2);  /* we got the total size. allocate it, with room for a NULL character. */  path = p = apr_palloc(pool, total_len + 1);  /* if we aren't supposed to skip forward to an absolute component, and if     this is not an empty base that we are skipping, then copy the base     into the output. */  if (base_arg == 0 && ! (SVN_PATH_IS_EMPTY(base) && ! base_is_empty))    {      if (SVN_PATH_IS_EMPTY(base))        memcpy(p, SVN_EMPTY_PATH, len = saved_lengths[0]);      else        memcpy(p, base, len = saved_lengths[0]);      p += len;    }  nargs = 0;  va_start(va, base);  while ((s = va_arg(va, const char *)) != NULL)    {      if (SVN_PATH_IS_EMPTY(s))        continue;      if (++nargs < base_arg)        continue;      if (nargs < MAX_SAVED_LENGTHS)        len = saved_lengths[nargs];      else        len = strlen(s);      /* insert a separator if we aren't copying in the first component         (which can happen when base_arg is set). also, don't put in a slash         if the prior character is a slash (occurs when prior component         is "/"). */      if (p != path && p[-1] != '/')        *p++ = '/';      /* copy the new component and advance the pointer */      memcpy(p, s, len);      p += len;    }  va_end(va);  *p = '\0';  assert((apr_size_t)(p - path) == total_len);  return path;}apr_size_tsvn_path_component_count(const char *path){  apr_size_t count = 0;  assert(is_canonical(path, strlen(path)));  while (*path)    {      const char *start;      while (*path == '/')        ++path;      start = path;            while (*path && *path != '/')        ++path;      if (path != start)        ++count;    }  return count;}/* Return the length of substring necessary to encompass the entire * previous path segment in PATH, which should be a LEN byte string. * * A trailing slash will not be included in the returned length except * in the case in which PATH is absolute and there are no more * previous segments. */static apr_size_tprevious_segment(const char *path,                 apr_size_t len){  if (len == 0)    return 0;  while (len > 0 && path[--len] != '/')    ;  if (len == 0 && path[0] == '/')    return 1;  else    return len;}voidsvn_path_add_component(svn_stringbuf_t *path,                        const char *component){  apr_size_t len = strlen(component);  assert(is_canonical(path->data, path->len));  assert(is_canonical(component, len));  /* Append a dir separator, but only if this path is neither empty     nor consists of a single dir separator already. */  if ((! SVN_PATH_IS_EMPTY(path->data))      && (! ((path->len == 1) && (*(path->data) == '/'))))    {      char dirsep = '/';      svn_stringbuf_appendbytes(path, &dirsep, sizeof(dirsep));    }  svn_stringbuf_appendbytes(path, component, len);}voidsvn_path_remove_component(svn_stringbuf_t *path){  assert(is_canonical(path->data, path->len));  path->len = previous_segment(path->data, path->len);  path->data[path->len] = '\0';}voidsvn_path_remove_components(svn_stringbuf_t *path, apr_size_t n){  while (n > 0)    {      svn_path_remove_component(path);      n--;    }}char *svn_path_dirname(const char *path, apr_pool_t *pool){  apr_size_t len = strlen(path);  assert(is_canonical(path, len));  return apr_pstrmemdup(pool, path, previous_segment(path, len));}char *svn_path_basename(const char *path, apr_pool_t *pool){  apr_size_t len = strlen(path);  apr_size_t start;  assert(is_canonical(path, len));  if (len == 1 && path[0] == '/')    start = 0;  else    {      start = len;      while (start > 0 && path[start - 1] != '/')        --start;    }  return apr_pstrmemdup(pool, path + start, len - start);}voidsvn_path_split(const char *path,               const char **dirpath,               const char **base_name,               apr_pool_t *pool){  assert(dirpath != base_name);  if (dirpath)    *dirpath = svn_path_dirname(path, pool);  if (base_name)    *base_name = svn_path_basename(path, pool);}intsvn_path_is_empty(const char *path){  /* assert (is_canonical (path, strlen (path))); ### Expensive strlen */  if (SVN_PATH_IS_EMPTY(path))    return 1;  return 0;}int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -