00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #ifndef lint
00047 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/db_lookup.c,v 14.19 2006/09/16 02:04:24 lbutler Exp $ (BRL)";
00048 #endif
00049
00050 #include "common.h"
00051
00052 #include <stdio.h>
00053 #ifdef HAVE_STRING_H
00054 # include <string.h>
00055 #else
00056 # include <strings.h>
00057 #endif
00058
00059 #include "machine.h"
00060 #include "vmath.h"
00061 #include "db.h"
00062 #include "raytrace.h"
00063
00064 #include "./debug.h"
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 int
00076 db_is_directory_non_empty(const struct db_i *dbip)
00077 {
00078 register int i;
00079
00080 RT_CK_DBI(dbip);
00081
00082 for (i = 0; i < RT_DBNHASH; i++) {
00083 if( dbip->dbi_Head[i] != DIR_NULL )
00084 return 1;
00085 }
00086 return 0;
00087 }
00088
00089
00090
00091
00092
00093
00094 int
00095 db_get_directory_size(const struct db_i *dbip)
00096 {
00097 register struct directory *dp;
00098 register int count = 0;
00099 int i;
00100
00101 RT_CK_DBI(dbip);
00102
00103 for (i = 0; i < RT_DBNHASH; i++) {
00104 for (dp = dbip->dbi_Head[i]; dp != DIR_NULL; dp = dp->d_forw)
00105 count++;
00106 }
00107 return count;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116 void
00117 db_ck_directory(const struct db_i *dbip)
00118 {
00119 register struct directory *dp;
00120 int i;
00121
00122 RT_CK_DBI(dbip);
00123
00124 for (i = 0; i < RT_DBNHASH; i++) {
00125 for (dp = dbip->dbi_Head[i]; dp != DIR_NULL; dp = dp->d_forw)
00126 RT_CK_DIR(dp);
00127 }
00128 }
00129
00130
00131
00132
00133
00134
00135
00136 int
00137 db_dirhash(const char *str)
00138 {
00139 register const unsigned char *s = (unsigned char *)str;
00140 register long sum;
00141 register int i;
00142
00143 sum = 0;
00144
00145 for( i=1; *s; )
00146 sum += *s++ * i++;
00147
00148 return( RT_DBHASH(sum) );
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174 int
00175 db_dircheck(struct db_i *dbip,
00176 struct bu_vls *ret_name,
00177 int noisy,
00178 struct directory ***headp)
00179 {
00180 register struct directory *dp;
00181 register char *cp = bu_vls_addr(ret_name);
00182 register char n0 = cp[0];
00183 register char n1 = cp[1];
00184
00185
00186 *headp = &(dbip->dbi_Head[db_dirhash(cp)]);
00187
00188 for (dp = **headp; dp != DIR_NULL; dp=dp->d_forw) {
00189 register char *this;
00190 if (n0 == *(this=dp->d_namep) &&
00191 n1 == this[1] &&
00192 strcmp(cp, this) == 0) {
00193
00194 register int c;
00195
00196 bu_vls_strcpy(ret_name, "A_");
00197 bu_vls_strcat(ret_name, this);
00198
00199 for (c = 'A'; c <= 'Z'; c++) {
00200 *cp = c;
00201 if (db_lookup(dbip, cp, noisy) == DIR_NULL)
00202 break;
00203 }
00204 if (c > 'Z') {
00205 bu_log("db_dircheck: Duplicate of name '%s', ignored\n",
00206 cp);
00207 return -1;
00208 }
00209 bu_log("db_dircheck: Duplicate of '%s', given temporary name '%s'\n",
00210 cp+2, cp);
00211
00212
00213 *headp = &(dbip->dbi_Head[db_dirhash(cp)]);
00214 break;
00215 }
00216 }
00217
00218 return 0;
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 struct directory *
00238 db_lookup(const struct db_i *dbip, register const char *name, int noisy)
00239 {
00240 register struct directory *dp;
00241 register char n0;
00242 register char n1;
00243
00244 if (!name) {
00245 bu_log("db_lookup received NULL name\n");
00246 return (DIR_NULL);
00247 }
00248
00249 n0 = name[0];
00250 n1 = name[1];
00251
00252 RT_CK_DBI(dbip);
00253
00254 dp = dbip->dbi_Head[db_dirhash(name)];
00255 for(; dp != DIR_NULL; dp=dp->d_forw ) {
00256 register char *this;
00257 if(
00258 n0 == *(this=dp->d_namep) &&
00259 n1 == this[1] &&
00260 strcmp( name, this ) == 0
00261 ) {
00262 if(RT_G_DEBUG&DEBUG_DB) bu_log("db_lookup(%s) x%x\n", name, dp);
00263 return(dp);
00264 }
00265 }
00266
00267 if(noisy || RT_G_DEBUG&DEBUG_DB) bu_log("db_lookup(%s) failed: %s does not exist\n", name, name);
00268 return( DIR_NULL );
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288 struct directory *
00289 db_diradd(register struct db_i *dbip, register const char *name, long int laddr, int len, int flags, genptr_t ptr)
00290 {
00291 struct directory **headp;
00292 register struct directory *dp;
00293 char *tmp_ptr;
00294 struct bu_vls local;
00295
00296 RT_CK_DBI(dbip);
00297
00298 if(RT_G_DEBUG&DEBUG_DB) {
00299 bu_log("db_diradd(dbip=0x%x, name='%s', addr=0x%x, len=%d, flags=0x%x, ptr=0x%x)\n",
00300 dbip, name, laddr, len, flags, ptr );
00301 }
00302
00303 if( (tmp_ptr=strchr( name, '/' )) != NULL ) {
00304
00305
00306
00307 if( dbip->dbi_version < 5 && (tmp_ptr - name) < 16 ) {
00308 bu_log("db_diradd() object named '%s' is illegal, ignored\n", name );
00309 return DIR_NULL;
00310 }
00311 }
00312
00313 bu_vls_init(&local);
00314 if( dbip->dbi_version < 5 ) {
00315 bu_vls_strncpy(&local, name, NAMESIZE);
00316 } else {
00317
00318 if (!ptr) {
00319 bu_log("WARNING: db_diradd() called with a null minor type pointer for object %s\nIgnoring %s\n", name, name);
00320 bu_vls_free(&local);
00321 return DIR_NULL;
00322 }
00323 bu_vls_strcpy(&local, name);
00324 }
00325 if (db_dircheck(dbip, &local, 0, &headp) < 0) {
00326 bu_vls_free(&local);
00327 return DIR_NULL;
00328 }
00329
00330
00331 RT_GET_DIRECTORY(dp, &rt_uniresource);
00332 RT_CK_DIR(dp);
00333 RT_DIR_SET_NAMEP(dp, bu_vls_addr(&local));
00334 dp->d_un.file_offset = laddr;
00335 dp->d_flags = flags & ~(RT_DIR_INMEM);
00336 dp->d_len = len;
00337 dp->d_forw = *headp;
00338 BU_LIST_INIT( &dp->d_use_hd );
00339 *headp = dp;
00340 dp->d_animate = NULL;
00341 dp->d_nref = 0;
00342 dp->d_uses = 0;
00343 if( dbip->dbi_version > 4 ) {
00344 dp->d_major_type = DB5_MAJORTYPE_BRLCAD;
00345 dp->d_minor_type = *(unsigned char *)ptr;
00346 }
00347 bu_vls_free(&local);
00348 return( dp );
00349 }
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365 int
00366 db_dirdelete(register struct db_i *dbip, register struct directory *dp)
00367 {
00368 register struct directory *findp;
00369 register struct directory **headp;
00370
00371 RT_CK_DBI(dbip);
00372 RT_CK_DIR(dp);
00373
00374 headp = &(dbip->dbi_Head[db_dirhash(dp->d_namep)]);
00375
00376 if( dp->d_flags & RT_DIR_INMEM )
00377 {
00378 if( dp->d_un.ptr != NULL )
00379 bu_free( dp->d_un.ptr, "db_dirdelete() inmem ptr" );
00380 }
00381
00382 if( *headp == dp ) {
00383 RT_DIR_FREE_NAMEP(dp);
00384 *headp = dp->d_forw;
00385
00386
00387 dp->d_forw = rt_uniresource.re_directory_hd;
00388 rt_uniresource.re_directory_hd = dp;
00389 return(0);
00390 }
00391 for( findp = *headp; findp != DIR_NULL; findp = findp->d_forw ) {
00392 if( findp->d_forw != dp )
00393 continue;
00394 RT_DIR_FREE_NAMEP(dp);
00395 findp->d_forw = dp->d_forw;
00396
00397
00398 dp->d_forw = rt_uniresource.re_directory_hd;
00399 rt_uniresource.re_directory_hd = dp;
00400 return(0);
00401 }
00402 return(-1);
00403 }
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415 int
00416 db_rename(register struct db_i *dbip, register struct directory *dp, const char *newname)
00417 {
00418 register struct directory *findp;
00419 register struct directory **headp;
00420
00421 RT_CK_DBI(dbip);
00422 RT_CK_DIR(dp);
00423
00424
00425 headp = &(dbip->dbi_Head[db_dirhash(dp->d_namep)]);
00426 if( *headp == dp ) {
00427
00428 *headp = dp->d_forw;
00429 } else {
00430 for( findp = *headp; findp != DIR_NULL; findp = findp->d_forw ) {
00431 if( findp->d_forw != dp )
00432 continue;
00433
00434 findp->d_forw = dp->d_forw;
00435 goto out;
00436 }
00437 return(-1);
00438 }
00439
00440 out:
00441
00442 RT_DIR_FREE_NAMEP(dp);
00443 RT_DIR_SET_NAMEP( dp, newname );
00444
00445
00446 headp = &(dbip->dbi_Head[db_dirhash(newname)]);
00447 dp->d_forw = *headp;
00448 *headp = dp;
00449 return(0);
00450 }
00451
00452
00453
00454
00455
00456
00457 void
00458 db_pr_dir(register const struct db_i *dbip)
00459 {
00460 register const struct directory *dp;
00461 register char *flags;
00462 register int i;
00463
00464 RT_CK_DBI(dbip);
00465
00466 bu_log("db_pr_dir(x%x): Dump of directory for file %s [%s]\n",
00467 dbip, dbip->dbi_filename,
00468 dbip->dbi_read_only ? "READ-ONLY" : "Read/Write" );
00469
00470 bu_log("Title = %s\n", dbip->dbi_title);
00471
00472
00473 for( i = 0; i < RT_DBNHASH; i++ ) {
00474 for( dp = dbip->dbi_Head[i]; dp != DIR_NULL; dp=dp->d_forw ) {
00475 if( dp->d_flags & DIR_SOLID )
00476 flags = "SOL";
00477 else if( (dp->d_flags & (DIR_COMB|DIR_REGION)) ==
00478 (DIR_COMB|DIR_REGION) )
00479 flags = "REG";
00480 else if( (dp->d_flags & (DIR_COMB|DIR_REGION)) ==
00481 DIR_COMB )
00482 flags = "COM";
00483 else
00484 flags = "Bad";
00485 bu_log("x%.8x %s %s=x%.8x len=%.5d use=%.2d nref=%.2d %s",
00486 dp,
00487 flags,
00488 dp->d_flags & RT_DIR_INMEM ? " ptr " : "d_addr",
00489 dp->d_addr,
00490 dp->d_len,
00491 dp->d_uses,
00492 dp->d_nref,
00493 dp->d_namep );
00494 if( dp->d_animate )
00495 bu_log(" anim=x%x\n", dp->d_animate );
00496 else
00497 bu_log("\n");
00498 }
00499 }
00500 }
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510 void
00511 db_get_directory(register struct resource *resp)
00512 {
00513 register struct directory *dp;
00514 register int bytes;
00515
00516 RT_CK_RESOURCE(resp);
00517 BU_CK_PTBL( &resp->re_directory_blocks );
00518
00519 BU_ASSERT_PTR( resp->re_directory_hd, ==, NULL );
00520
00521
00522 bytes = bu_malloc_len_roundup(1024*sizeof(struct directory));
00523 dp = (struct directory *)bu_malloc(bytes, "re_directory_blocks from db_get_directory() " BU_FLSTR);
00524
00525
00526 bu_ptbl_ins( &resp->re_directory_blocks, (long *)dp );
00527
00528 while( bytes >= sizeof(struct directory) ) {
00529 dp->d_magic = RT_DIR_MAGIC;
00530 dp->d_forw = resp->re_directory_hd;
00531 resp->re_directory_hd = dp;
00532 dp++;
00533 bytes -= sizeof(struct directory);
00534 }
00535 }
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558 struct bu_ptbl *
00559 db_lookup_by_attr(struct db_i *dbip, int dir_flags, struct bu_attribute_value_set *avs, int op)
00560 {
00561 struct bu_attribute_value_set obj_avs;
00562 struct directory *dp;
00563 struct bu_ptbl *tbl;
00564 int match_count=0;
00565 int attr_count;
00566 int i,j;
00567 int draw;
00568
00569 RT_CK_DBI(dbip);
00570
00571 if( avs ) {
00572 BU_CK_AVS( avs );
00573 attr_count = avs->count;
00574 } else {
00575 attr_count = 0;
00576 }
00577 tbl = (struct bu_ptbl *)bu_malloc( sizeof( struct bu_ptbl ), "wdb_get_by_attr ptbl" );
00578 bu_ptbl_init( tbl, 128, "wdb_get_by_attr ptbl_init" );
00579 FOR_ALL_DIRECTORY_START(dp,dbip)
00580 if( (dp->d_flags & dir_flags) == 0 ) continue;
00581 if(attr_count ) {
00582 if( db5_get_attributes( dbip, &obj_avs, dp ) < 0 ) {
00583 bu_log( "ERROR: failed to get attributes for %s\n", dp->d_namep );
00584 return( (struct bu_ptbl *)NULL );
00585 }
00586
00587 draw = 0;
00588 match_count = 0;
00589 for( i=0 ; i<avs->count ; i++ ) {
00590 for( j=0 ; j<obj_avs.count ; j++ ) {
00591 if( !strcmp( avs->avp[i].name, obj_avs.avp[j].name ) ) {
00592 if( !strcmp( avs->avp[i].value, obj_avs.avp[j].value ) ) {
00593 if( op == 2 ) {
00594 draw = 1;
00595 break;
00596 } else {
00597 match_count++;
00598 }
00599 }
00600 }
00601 }
00602 if( draw ) break;
00603 }
00604 bu_avs_free( &obj_avs );
00605 } else {
00606 draw = 1;
00607 }
00608 if( draw || match_count == attr_count ) {
00609 bu_ptbl_ins( tbl , (long *)dp );
00610 }
00611 FOR_ALL_DIRECTORY_END
00612
00613 return( tbl );
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625