db_path.c

Go to the documentation of this file.
00001 /*                       D B _ P A T H . C
00002  * BRL-CAD
00003  *
00004  * Copyright (c) 1990-2006 United States Government as represented by
00005  * the U.S. Army Research Laboratory.
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public License
00009  * as published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful, but
00013  * WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Library General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this file; see the file named COPYING for more
00019  * information.
00020  */
00021 
00022 /** @addtogroup dbio */
00023 
00024 /*@{*/
00025 /** @file db_path.c
00026  *  Routines to manipulate "db_full_path" structures
00027  *
00028  * Functions -
00029  *
00030  *
00031  *  Authors -
00032  *      Michael John Muuss
00033  *
00034  *  Source -
00035  *      SECAD/VLD Computing Consortium, Bldg 394
00036  *      The U. S. Army Ballistic Research Laboratory
00037  *      Aberdeen Proving Ground, Maryland  21005-5066
00038  *
00039  */
00040 
00041 #ifndef lint
00042 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/db_path.c,v 14.10 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00043 #endif
00044 
00045 #include "common.h"
00046 
00047 
00048 
00049 #include <stdio.h>
00050 #include <math.h>
00051 #ifdef HAVE_STRING_H
00052 #include <string.h>
00053 #else
00054 #include <strings.h>
00055 #endif
00056 
00057 #include "machine.h"
00058 #include "vmath.h"
00059 #include "raytrace.h"
00060 
00061 #include "./debug.h"
00062 
00063 /**
00064  *                      D B _ F U L L _ P A T H _ I N I T
00065  */
00066 void
00067 db_full_path_init( struct db_full_path *pathp )
00068 {
00069         pathp->fp_len = 0;
00070         pathp->fp_maxlen = 0;
00071         pathp->fp_names = (struct directory **)NULL;
00072         pathp->magic = DB_FULL_PATH_MAGIC;
00073 }
00074 
00075 /**
00076  *                      D B _ A D D _ N O D E _ T O _ F U L L _ P A T H
00077  */
00078 void
00079 db_add_node_to_full_path( struct db_full_path *pp, struct directory *dp )
00080 {
00081         RT_CK_FULL_PATH( pp );
00082 
00083         if( pp->fp_maxlen <= 0 )  {
00084                 pp->fp_maxlen = 32;
00085                 pp->fp_names = (struct directory **)bu_malloc(
00086                         pp->fp_maxlen * sizeof(struct directory *),
00087                         "db_full_path array");
00088         } else if( pp->fp_len >= pp->fp_maxlen )  {
00089                 pp->fp_maxlen *= 4;
00090                 pp->fp_names = (struct directory **)rt_realloc(
00091                         (char *)pp->fp_names,
00092                         pp->fp_maxlen * sizeof(struct directory *),
00093                         "enlarged db_full_path array");
00094         }
00095         pp->fp_names[pp->fp_len++] = dp;
00096 }
00097 
00098 /**
00099  *                      D B _ D U P _ F U L L _ P A T H
00100  */
00101 void
00102 db_dup_full_path(register struct db_full_path *newp, register const struct db_full_path *oldp)
00103 {
00104         RT_CK_FULL_PATH(newp);
00105         RT_CK_FULL_PATH(oldp);
00106 
00107         newp->fp_maxlen = oldp->fp_maxlen;
00108         newp->fp_len = oldp->fp_len;
00109         if( oldp->fp_len <= 0 )  {
00110                 newp->fp_names = (struct directory **)0;
00111                 return;
00112         }
00113         newp->fp_names = (struct directory **)bu_malloc(
00114                 newp->fp_maxlen * sizeof(struct directory *),
00115                 "db_full_path array (duplicate)" );
00116         bcopy( (char *)oldp->fp_names, (char *)newp->fp_names,
00117                 newp->fp_len * sizeof(struct directory *) );
00118 }
00119 
00120 /**
00121  *                      D B _ E X T E N D _ F U L L _ P A T H
00122  *
00123  *  Extend "pathp" so that it can grow from current fp_len by incr more names.
00124  *
00125  *  This is intended primarily as an internal method.
00126  */
00127 void
00128 db_extend_full_path( struct db_full_path *pathp, int incr )
00129 {
00130         int             newlen;
00131 
00132         RT_CK_FULL_PATH(pathp);
00133 
00134         if( pathp->fp_maxlen <= 0 )  {
00135                 pathp->fp_len = 0;
00136                 pathp->fp_maxlen = incr;
00137                 pathp->fp_names = (struct directory **)bu_malloc(
00138                         pathp->fp_maxlen * sizeof(struct directory *),
00139                         "empty fp_names extension" );
00140                 return;
00141         }
00142 
00143         newlen = pathp->fp_len + incr;
00144         if( pathp->fp_maxlen < newlen )  {
00145                 pathp->fp_maxlen = newlen+1;
00146                 pathp->fp_names = (struct directory **)rt_realloc(
00147                         (char *)pathp->fp_names,
00148                         pathp->fp_maxlen * sizeof(struct directory *),
00149                         "fp_names extension" );
00150         }
00151 }
00152 
00153 /**
00154  *                      D B _ A P P E N D _ F U L L _ P A T H
00155  */
00156 void
00157 db_append_full_path( struct db_full_path *dest, const struct db_full_path *src )
00158 {
00159         RT_CK_FULL_PATH(dest);
00160         RT_CK_FULL_PATH(src);
00161 
00162         db_extend_full_path( dest, src->fp_len );
00163         bcopy( (char *)&src->fp_names[0],
00164                 (char *)&dest->fp_names[dest->fp_len],
00165                 src->fp_len * sizeof(struct directory *) );
00166         dest->fp_len += src->fp_len;
00167 }
00168 
00169 /**
00170  *                      D B _ D U P _ P A T H _ T A I L
00171  *
00172  *  Dup old path from starting index to end.
00173  */
00174 void
00175 db_dup_path_tail(register struct db_full_path *newp, register const struct db_full_path *oldp, int start)
00176 {
00177         RT_CK_FULL_PATH(newp);
00178         RT_CK_FULL_PATH(oldp);
00179 
00180         if( start < 0 || start > oldp->fp_len-1 )  rt_bomb("db_dup_path_tail: start offset out of range\n");
00181 
00182         newp->fp_maxlen = newp->fp_len = oldp->fp_len - start;
00183         if( newp->fp_len <= 0 )  {
00184                 newp->fp_names = (struct directory **)0;
00185                 return;
00186         }
00187         newp->fp_names = (struct directory **)bu_malloc(
00188                 newp->fp_maxlen * sizeof(struct directory *),
00189                 "db_full_path array (duplicate)" );
00190         bcopy( (char *)&oldp->fp_names[start], (char *)newp->fp_names,
00191                 newp->fp_len * sizeof(struct directory *) );
00192 }
00193 
00194 /**
00195  *                      D B _ P A T H _ T O _ S T R I N G
00196  *
00197  *  Unlike rt_path_str(), this version can be used in parallel.
00198  *  Caller is responsible for freeing the returned buffer.
00199  */
00200 char *
00201 db_path_to_string( const struct db_full_path *pp )
00202 {
00203         register char   *cp;
00204         char    *buf;
00205         int     len;
00206         int     i;
00207 
00208         RT_CK_FULL_PATH( pp );
00209 
00210         len = 3;        /* leading slash, trailing null, spare */
00211         for( i=pp->fp_len-1; i >= 0; i-- )  {
00212                 if( pp->fp_names[i] )
00213                         len += strlen( pp->fp_names[i]->d_namep ) + 1;
00214                 else
00215                         len += 16;
00216         }
00217 
00218         buf = bu_malloc( len, "pathname string" );
00219         cp = buf;
00220 
00221         for( i=0; i < pp->fp_len; i++ )  {
00222                 *cp++ = '/';
00223                 if( pp->fp_names[i] )
00224                         strcpy( cp, pp->fp_names[i]->d_namep );
00225                 else
00226                         strcpy( cp, "**NULL**" );
00227                 cp += strlen( cp );
00228         }
00229         *cp++ = '\0';
00230         return buf;
00231 }
00232 
00233 /**
00234  *                      D B _ P A T H _ T O _ V L S
00235  *
00236  *  Append a string representation of the path onto the vls.
00237  *  Must have exactly the same formattting conventions as
00238  *  db_path_to_string().
00239  */
00240 void
00241 db_path_to_vls( struct bu_vls *str, const struct db_full_path *pp )
00242 {
00243         register int i;
00244 
00245         BU_CK_VLS(str);
00246         RT_CK_FULL_PATH( pp );
00247 
00248         for( i=0; i < pp->fp_len; i++ )  {
00249                 bu_vls_putc( str, '/' );
00250                 if( pp->fp_names[i] )
00251                         bu_vls_strcat( str, pp->fp_names[i]->d_namep );
00252                 else
00253                         bu_vls_strcat( str, "**NULL**" );
00254         }
00255 }
00256 
00257 /**
00258  *                      D B _ P R _ F U L L _ P A T H
00259  */
00260 void
00261 db_pr_full_path( const char *msg, const struct db_full_path *pathp )
00262 {
00263         char    *sofar = db_path_to_string(pathp);
00264 
00265         bu_log("%s %s\n", msg, sofar );
00266         bu_free(sofar, "path string");
00267 }
00268 
00269 /**
00270  *                      D B _ S T R I N G _ T O _ P A T H
00271  *
00272  *  Reverse the effects of db_path_to_string().
00273  *
00274  *  The db_full_path structure will be initialized.  If it was already in use,
00275  *  user should call db_free_full_path() first.
00276  *
00277  *  Returns -
00278  *      -1      One or more components of path did not exist in the directory.
00279  *       0      OK
00280  */
00281 int
00282 db_string_to_path(struct db_full_path *pp, const struct db_i *dbip, const char *str)
00283 {
00284         register char           *cp;
00285         register char           *slashp;
00286         struct directory        *dp;
00287         char                    *copy;
00288         int                     nslash = 0;
00289         int                     ret = 0;
00290         int                     len;
00291 
00292         RT_CK_DBI(dbip);
00293 
00294         /* Count slashes */
00295         while( *str == '/' )  str++;    /* strip off leading slashes */
00296         if( *str == '\0' )  {
00297                 /* Path of a lone slash */
00298                 db_full_path_init( pp );
00299                 return 0;
00300         }
00301 
00302         copy = bu_strdup( str );
00303 
00304         /* eliminate a a trailing slash */
00305         len = strlen( copy );
00306         if( copy[len-1] == '/' )
00307                 copy[len-1] = '\0';
00308 
00309         cp = copy;
00310         while( *cp )  {
00311                 if( (slashp = strchr( cp, '/' )) == NULL )  break;
00312                 nslash++;
00313                 cp = slashp+1;
00314         }
00315 
00316         /* Make a path structure just big enough */
00317         pp->magic = DB_FULL_PATH_MAGIC;
00318         pp->fp_maxlen = pp->fp_len = nslash+1;
00319         pp->fp_names = (struct directory **)bu_malloc(
00320                 pp->fp_maxlen * sizeof(struct directory *),
00321                 "db_string_to_path path array" );
00322 
00323 
00324         /* Build up path array */
00325         cp = copy;
00326         nslash = 0;
00327         while( *cp )  {
00328                 if( (slashp = strchr( cp, '/' )) == NULL )  {
00329                         /* Last element of string, has no trailing slash */
00330                         slashp = cp + strlen(cp) - 1;
00331                 } else {
00332                         *slashp = '\0';
00333                 }
00334                 if( (dp = db_lookup( dbip, cp, LOOKUP_NOISY )) == DIR_NULL )  {
00335                         bu_log("db_string_to_path() of '%s' failed on '%s'\n",
00336                                 str, cp );
00337                         ret = -1;       /* FAILED */
00338                         /* Fall through, storing null dp in this location */
00339                 }
00340                 pp->fp_names[nslash++] = dp;
00341                 cp = slashp+1;
00342         }
00343         BU_ASSERT_LONG( nslash, ==, pp->fp_len );
00344         bu_free( copy, "db_string_to_path() duplicate string");
00345         return ret;
00346 }
00347 
00348 /**
00349  *                      D B _ A R G V _ T O _ P A T H
00350  *
00351  *  Treat elements from argv[0] to argv[argc-1] as a path specification.
00352  *
00353  *  The path structure will be fully initialized.  If it was already in use,
00354  *  user should call db_free_full_path() first.
00355  *
00356  *  Returns -
00357  *      -1      One or more components of path did not exist in the directory.
00358  *       0      OK
00359  */
00360 int
00361 db_argv_to_path(register struct db_full_path *pp, struct db_i *dbip, int argc, const char *const *argv)
00362 {
00363         struct directory        *dp;
00364         int                     ret = 0;
00365         int                     i;
00366 
00367         RT_CK_DBI(dbip);
00368 
00369         /* Make a path structure just big enough */
00370         pp->magic = DB_FULL_PATH_MAGIC;
00371         pp->fp_maxlen = pp->fp_len = argc;
00372         pp->fp_names = (struct directory **)bu_malloc(
00373                 pp->fp_maxlen * sizeof(struct directory *),
00374                 "db_argv_to_path path array" );
00375 
00376         for( i=0; i<argc; i++ )  {
00377                 if( (dp = db_lookup( dbip, argv[i], LOOKUP_NOISY )) == DIR_NULL )  {
00378                         bu_log("db_argv_to_path() failed on element %d='%s'\n",
00379                                 i, argv[i] );
00380                         ret = -1;       /* FAILED */
00381                         /* Fall through, storing null dp in this location */
00382                 }
00383                 pp->fp_names[i] = dp;
00384         }
00385         return ret;
00386 }
00387 
00388 /**
00389  *                      D B _ F R E E _ F U L L _ P A T H
00390  *
00391  *  Free the contents of the db_full_path structure, but not the structure
00392  *  itself, which might be automatic.
00393  */
00394 void
00395 db_free_full_path(register struct db_full_path *pp)
00396 {
00397         RT_CK_FULL_PATH( pp );
00398 
00399         if( pp->fp_maxlen > 0 )  {
00400                 bu_free( (char *)pp->fp_names, "db_full_path array" );
00401                 pp->fp_maxlen = pp->fp_len = 0;
00402                 pp->fp_names = (struct directory **)0;
00403         }
00404 }
00405 
00406 /**
00407  *                      D B _ I D E N T I C A L _ F U L L _ P A T H S
00408  *
00409  *  Returns -
00410  *      1       match
00411  *      0       different
00412  */
00413 int
00414 db_identical_full_paths(
00415         const struct db_full_path *a,
00416         const struct db_full_path *b )
00417 {
00418         register int i;
00419 
00420         RT_CK_FULL_PATH(a);
00421         RT_CK_FULL_PATH(b);
00422 
00423         if( a->fp_len != b->fp_len )  return 0;
00424 
00425         for( i = a->fp_len-1; i >= 0; i-- )  {
00426                 if( a->fp_names[i] != b->fp_names[i] )  return 0;
00427         }
00428         return 1;
00429 }
00430 
00431 /**
00432  *                      D B _ F U L L _ P A T H _ S U B S E T
00433  *
00434  *  Returns -
00435  *      1       if 'b' is a proper subset of 'a'
00436  *      0       if not.
00437  */
00438 int
00439 db_full_path_subset(
00440         const struct db_full_path *a,
00441         const struct db_full_path *b )
00442 {
00443         register int i;
00444 
00445         RT_CK_FULL_PATH(a);
00446         RT_CK_FULL_PATH(b);
00447 
00448         if( b->fp_len > a->fp_len )  return 0;
00449 
00450         for( i=0; i < a->fp_len; i++ )  {
00451                 register int j;
00452 
00453                 if( a->fp_names[i] != b->fp_names[0] )  continue;
00454 
00455                 /* First element matches, check remaining length */
00456                 if( b->fp_len > a->fp_len - i )  return 0;
00457 
00458                 /* Check remainder of 'b' */
00459                 for( j=1; j < b->fp_len; j++ )  {
00460                         if( a->fp_names[i+j] != b->fp_names[j] )  goto step;
00461                 }
00462                 /* 'b' is a proper subset */
00463                 return 1;
00464 
00465 step:           ;
00466         }
00467         return 0;
00468 }
00469 
00470 /**
00471  *                      D B _ F U L L _ P A T H _ S E A R C H
00472  *
00473  *  Returns -
00474  *      1       'dp' is found on this path
00475  *      0       not found
00476  */
00477 int
00478 db_full_path_search( const struct db_full_path *a, const struct directory *dp )
00479 {
00480         register int i;
00481 
00482         RT_CK_FULL_PATH(a);
00483         RT_CK_DIR(dp);
00484 
00485         for( i = a->fp_len-1; i >= 0; i-- )  {
00486                 if( a->fp_names[i] == dp )  return 1;
00487         }
00488         return 0;
00489 }
00490 
00491 /*@}*/
00492 /*
00493  * Local Variables:
00494  * mode: C
00495  * tab-width: 8
00496  * c-basic-offset: 4
00497  * indent-tabs-mode: t
00498  * End:
00499  * ex: shiftwidth=4 tabstop=8
00500  */

Generated on Mon Sep 18 01:24:49 2006 for BRL-CAD by  doxygen 1.4.6