BRL-CAD
dirname.c
Go to the documentation of this file.
1 /* D I R N A M E . C
2  * BRL-CAD
3  *
4  * Copyright (c) 2004-2014 United States Government as represented by
5  * the U.S. Army Research Laboratory.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public License
9  * version 2.1 as published by the Free Software Foundation.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this file; see the file named COPYING for more
18  * information.
19  */
20 
21 #include "common.h"
22 
23 #include <string.h>
24 
25 #include "bu/log.h"
26 #include "bu/malloc.h"
27 #include "bu/str.h"
28 
29 char *
30 bu_dirname(const char *cp)
31 {
32  char *ret;
33  char *found_dslash;
34  char *found_fslash;
35  size_t len;
36  const char DSLASH[2] = {BU_DIR_SEPARATOR, '\0'};
37  const char FSLASH[2] = {'/', '\0'};
38  const char *DOT = ".";
39  const char *DOTDOT = "..";
40 
41  /* Special cases */
42  if (UNLIKELY(!cp))
43  return bu_strdup(".");
44 
45  if (BU_STR_EQUAL(cp, DSLASH))
46  return bu_strdup(DSLASH);
47  if (BU_STR_EQUAL(cp, FSLASH))
48  return bu_strdup(FSLASH);
49 
50  if (BU_STR_EQUAL(cp, DOT)
51  || BU_STR_EQUAL(cp, DOTDOT)
52  || (strrchr(cp, BU_DIR_SEPARATOR) == NULL
53  && strrchr(cp, '/') == NULL))
54  return bu_strdup(DOT);
55 
56  /* Make a duplicate copy of the string, and shorten it in place */
57  ret = bu_strdup(cp);
58 
59  /* A sequence of trailing slashes don't count */
60  len = strlen(ret);
61  while (len > 1
62  && (ret[len-1] == BU_DIR_SEPARATOR
63  || ret[len-1] == '/')) {
64  ret[len-1] = '\0';
65  len--;
66  }
67 
68  /* If no slashes remain, return "." */
69  found_dslash = strrchr(ret, BU_DIR_SEPARATOR);
70  found_fslash = strrchr(ret, '/');
71  if (!found_dslash && !found_fslash) {
72  bu_free(ret, "bu_dirname");
73  return bu_strdup(DOT);
74  }
75 
76  /* Remove trailing slash, unless it's at front */
77  if (found_dslash == ret || found_fslash == ret) {
78  ret[1] = '\0'; /* ret == BU_DIR_SEPARATOR || "/" */
79  } else {
80  if (found_dslash)
81  *found_dslash = '\0';
82  if (found_fslash)
83  *found_fslash = '\0';
84  }
85 
86  return ret;
87 }
88 
89 /*
90  * Local Variables:
91  * mode: C
92  * tab-width: 8
93  * indent-tabs-mode: t
94  * c-file-style: "stroustrup"
95  * End:
96  * ex: shiftwidth=4 tabstop=8
97  */
Header file for the BRL-CAD common definitions.
#define BU_DIR_SEPARATOR
Definition: defines.h:97
void bu_free(void *ptr, const char *str)
Definition: malloc.c:328
char * bu_dirname(const char *cp)
Definition: dirname.c:30
#define bu_strdup(s)
Definition: str.h:71
#define UNLIKELY(expression)
Definition: common.h:282
#define BU_STR_EQUAL(s1, s2)
Definition: str.h:126