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 #ifndef lint
00037 static const char RCSid[] = "@(#)$Header: /cvsroot/brlcad/brlcad/src/librt/db5_scan.c,v 14.13 2006/09/16 02:04:24 lbutler Exp $ (ARL)";
00038 #endif
00039
00040 #include "common.h"
00041
00042 #include <stdio.h>
00043 #ifdef HAVE_STRING_H
00044 # include <string.h>
00045 #else
00046 # include <strings.h>
00047 #endif
00048
00049 #include "machine.h"
00050 #include "bu.h"
00051 #include "vmath.h"
00052 #include "bn.h"
00053 #include "db5.h"
00054 #include "raytrace.h"
00055
00056 #include "./debug.h"
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 int
00067 db5_scan(
00068 struct db_i *dbip,
00069 void (*handler)(struct db_i *,
00070 const struct db5_raw_internal *,
00071 long addr, genptr_t client_data ),
00072 genptr_t client_data )
00073 {
00074 unsigned char header[8];
00075 struct db5_raw_internal raw;
00076 int got;
00077 long nrec;
00078 long addr;
00079
00080 RT_CK_DBI(dbip);
00081 if(RT_G_DEBUG&DEBUG_DB) bu_log("db5_scan( x%x, x%x )\n", dbip, handler);
00082
00083 raw.magic = DB5_RAW_INTERNAL_MAGIC;
00084 nrec = 0L;
00085
00086
00087 if( dbip->dbi_mf ) {
00088 const unsigned char *cp = (const unsigned char *)dbip->dbi_inmem;
00089 long eof;
00090
00091 BU_CK_MAPPED_FILE(dbip->dbi_mf);
00092 eof = dbip->dbi_mf->buflen;
00093
00094 if( db5_header_is_valid( cp ) == 0 ) {
00095 bu_log("db5_scan ERROR: %s is lacking a proper BRL-CAD v5 database header\n", dbip->dbi_filename);
00096 goto fatal;
00097 }
00098 cp += sizeof(header);
00099 addr = sizeof(header);
00100 while( addr < eof ) {
00101 if( (cp = db5_get_raw_internal_ptr( &raw, cp )) == NULL ) {
00102 goto fatal;
00103 }
00104 (*handler)(dbip, &raw, addr, client_data);
00105 nrec++;
00106 addr += raw.object_length;
00107 }
00108 dbip->dbi_eof = addr;
00109 BU_ASSERT_LONG( dbip->dbi_eof, ==, dbip->dbi_mf->buflen );
00110 } else {
00111
00112 rewind( dbip->dbi_fp );
00113 if( fread( header, sizeof header, 1, dbip->dbi_fp ) != 1 ||
00114 db5_header_is_valid( header ) == 0 ) {
00115 bu_log("db5_scan ERROR: %s is lacking a proper BRL-CAD v5 database header\n", dbip->dbi_filename);
00116 goto fatal;
00117 }
00118 for(;;) {
00119 addr = ftell( dbip->dbi_fp );
00120 if( (got = db5_get_raw_internal_fp( &raw, dbip->dbi_fp )) < 0 ) {
00121 if( got == -1 ) break;
00122 goto fatal;
00123 }
00124 (*handler)(dbip, &raw, addr, client_data);
00125 nrec++;
00126 if(raw.buf) {
00127 bu_free(raw.buf, "raw v5 object");
00128 raw.buf = NULL;
00129 }
00130 }
00131 dbip->dbi_eof = ftell( dbip->dbi_fp );
00132 rewind( dbip->dbi_fp );
00133 }
00134
00135 dbip->dbi_nrec = nrec;
00136 return 0;
00137
00138 fatal:
00139 dbip->dbi_read_only = 1;
00140 return -1;
00141 }
00142
00143
00144 struct directory *
00145 db_diradd5(
00146 struct db_i *dbip,
00147 const char *name,
00148 long laddr,
00149 unsigned char major_type,
00150 unsigned char minor_type,
00151 unsigned char name_hidden,
00152 long object_length,
00153 struct bu_attribute_value_set *avs)
00154 {
00155 struct directory **headp;
00156 register struct directory *dp;
00157 struct bu_vls local;
00158
00159 RT_CK_DBI( dbip );
00160
00161 bu_vls_init(&local);
00162 bu_vls_strcpy(&local, name);
00163 if (db_dircheck(dbip, &local, 0, &headp) < 0) {
00164 bu_vls_free(&local);
00165 return DIR_NULL;
00166 }
00167
00168 if( rt_uniresource.re_magic == 0 )
00169 rt_init_resource( &rt_uniresource, 0, NULL );
00170
00171
00172 RT_GET_DIRECTORY( dp, &rt_uniresource );
00173 RT_CK_DIR(dp);
00174 BU_LIST_INIT( &dp->d_use_hd );
00175 RT_DIR_SET_NAMEP(dp, bu_vls_addr( &local ));
00176 bu_vls_free( &local );
00177 dp->d_un.ptr = NULL;
00178 dp->d_un.file_offset = laddr;
00179 dp->d_major_type = major_type;
00180 dp->d_minor_type = minor_type;
00181 switch( major_type ) {
00182 case DB5_MAJORTYPE_BRLCAD:
00183 if( minor_type == ID_COMBINATION ) {
00184
00185 dp->d_flags = DIR_COMB;
00186 if( !avs || avs->count == 0 ) break;
00187
00188
00189
00190 if( bu_avs_get( avs, "region" ) != NULL )
00191 dp->d_flags = DIR_COMB|DIR_REGION;
00192 } else {
00193 dp->d_flags = DIR_SOLID;
00194 }
00195 break;
00196 case DB5_MAJORTYPE_BINARY_EXPM:
00197 case DB5_MAJORTYPE_BINARY_UNIF:
00198 case DB5_MAJORTYPE_BINARY_MIME:
00199
00200 dp->d_flags = DIR_NON_GEOM;
00201 break;
00202 case DB5_MAJORTYPE_ATTRIBUTE_ONLY:
00203 dp->d_flags = 0;
00204 }
00205 if( name_hidden )
00206 dp->d_flags |= DIR_HIDDEN;
00207 dp->d_len = object_length;
00208 BU_LIST_INIT( &dp->d_use_hd );
00209 dp->d_animate = NULL;
00210 dp->d_nref = 0;
00211 dp->d_uses = 0;
00212 dp->d_forw = *headp;
00213 *headp = dp;
00214
00215 return( dp );
00216 }
00217
00218
00219 struct directory *
00220 db5_diradd(struct db_i *dbip,
00221 const struct db5_raw_internal *rip,
00222 long laddr,
00223 genptr_t client_data )
00224 {
00225 struct directory **headp;
00226 register struct directory *dp;
00227 struct bu_vls local;
00228
00229 RT_CK_DBI( dbip );
00230
00231 bu_vls_init(&local);
00232 bu_vls_strcpy(&local, rip->name.ext_buf);
00233 if (db_dircheck(dbip, &local, 0, &headp) < 0) {
00234 bu_vls_free(&local);
00235 return DIR_NULL;
00236 }
00237
00238 if( rt_uniresource.re_magic == 0 )
00239 rt_init_resource( &rt_uniresource, 0, NULL );
00240
00241
00242 RT_GET_DIRECTORY( dp, &rt_uniresource );
00243 RT_CK_DIR(dp);
00244 BU_LIST_INIT( &dp->d_use_hd );
00245 RT_DIR_SET_NAMEP(dp, bu_vls_addr(&local));
00246 bu_vls_free(&local);
00247 dp->d_un.file_offset = laddr;
00248 dp->d_major_type = rip->major_type;
00249 dp->d_minor_type = rip->minor_type;
00250 switch( rip->major_type ) {
00251 case DB5_MAJORTYPE_BRLCAD:
00252 if( rip->minor_type == ID_COMBINATION ) {
00253 struct bu_attribute_value_set avs;
00254
00255 bu_avs_init_empty(&avs);
00256
00257 dp->d_flags = DIR_COMB;
00258 if( rip->attributes.ext_nbytes == 0 ) break;
00259
00260
00261
00262
00263 if( db5_import_attributes( &avs, &rip->attributes ) < 0 ) {
00264 bu_log("db5_diradd_handler: Bad attributes on combination '%s'\n",
00265 rip->name);
00266 break;
00267 }
00268 if( bu_avs_get( &avs, "region" ) != NULL )
00269 dp->d_flags = DIR_COMB|DIR_REGION;
00270 bu_avs_free( &avs );
00271 } else {
00272 dp->d_flags = DIR_SOLID;
00273 }
00274 break;
00275 case DB5_MAJORTYPE_BINARY_EXPM:
00276 case DB5_MAJORTYPE_BINARY_UNIF:
00277 case DB5_MAJORTYPE_BINARY_MIME:
00278
00279 dp->d_flags = DIR_NON_GEOM;
00280 break;
00281 case DB5_MAJORTYPE_ATTRIBUTE_ONLY:
00282 dp->d_flags = 0;
00283 }
00284 if( rip->h_name_hidden )
00285 dp->d_flags |= DIR_HIDDEN;
00286 dp->d_len = rip->object_length;
00287 BU_LIST_INIT( &dp->d_use_hd );
00288 dp->d_animate = NULL;
00289 dp->d_nref = 0;
00290 dp->d_uses = 0;
00291 dp->d_forw = *headp;
00292 *headp = dp;
00293
00294 return( dp );
00295 }
00296
00297
00298
00299
00300
00301
00302
00303 HIDDEN void
00304 db5_diradd_handler(
00305 struct db_i *dbip,
00306 const struct db5_raw_internal *rip,
00307 long laddr,
00308 genptr_t client_data )
00309 {
00310 RT_CK_DBI(dbip);
00311
00312 if( rip->h_dli == DB5HDR_HFLAGS_DLI_HEADER_OBJECT ) return;
00313 if( rip->h_dli == DB5HDR_HFLAGS_DLI_FREE_STORAGE ) {
00314
00315 rt_memfree( &(dbip->dbi_freep), rip->object_length, laddr );
00316 return;
00317 }
00318
00319
00320 if( rip->name.ext_buf == NULL ) return;
00321
00322 if(RT_G_DEBUG&DEBUG_DB) {
00323 bu_log("db5_diradd_handler(dbip=x%x, name='%s', addr=x%x, len=%d)\n",
00324 dbip, rip->name, laddr, rip->object_length );
00325 }
00326
00327 db5_diradd( dbip, rip, laddr, client_data );
00328
00329 return;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349 int
00350 db_dirbuild( struct db_i *dbip )
00351 {
00352 unsigned char header[8];
00353
00354 RT_CK_DBI(dbip);
00355
00356
00357 rewind(dbip->dbi_fp);
00358 if( fread( header, sizeof header, 1, dbip->dbi_fp ) != 1 ) {
00359 bu_log("db_dirbuild(%s) ERROR, file too short to be BRL-CAD database\n",
00360 dbip->dbi_filename);
00361 return -1;
00362 }
00363
00364 if( db5_header_is_valid( header ) ) {
00365 struct directory *dp;
00366 struct bu_external ext;
00367 struct db5_raw_internal raw;
00368 struct bu_attribute_value_set avs;
00369 const char *cp;
00370
00371 bu_avs_init_empty(&avs);
00372
00373
00374 dbip->dbi_version = 5;
00375 if( db5_scan( dbip, db5_diradd_handler, NULL ) < 0 ) {
00376 bu_log("db_dirbuild(%s): db5_scan() failed\n",
00377 dbip->dbi_filename);
00378 return -1;
00379 }
00380
00381
00382 if( (dp = db_lookup( dbip, DB5_GLOBAL_OBJECT_NAME, LOOKUP_NOISY )) == DIR_NULL ) {
00383 bu_log("db_dirbuild(%s): improper database, no %s object\n",
00384 dbip->dbi_filename, DB5_GLOBAL_OBJECT_NAME );
00385 dbip->dbi_title = bu_strdup(DB5_GLOBAL_OBJECT_NAME);
00386
00387 db5_update_ident(dbip, "Untitled BRL-CAD Database",1.0);
00388 return 0;
00389 }
00390 BU_INIT_EXTERNAL(&ext);
00391 if( db_get_external( &ext, dp, dbip ) < 0 ||
00392 db5_get_raw_internal_ptr( &raw, ext.ext_buf ) == NULL ) {
00393 bu_log("db_dirbuild(%s): improper database, unable to read %s object\n",
00394 dbip->dbi_filename, DB5_GLOBAL_OBJECT_NAME );
00395 return -1;
00396 }
00397 if( raw.major_type != DB5_MAJORTYPE_ATTRIBUTE_ONLY ) {
00398 bu_log("db_dirbuild(%s): improper database, %s exists but is not an attribute-only object\n",
00399 dbip->dbi_filename, DB5_GLOBAL_OBJECT_NAME );
00400 dbip->dbi_title = bu_strdup(DB5_GLOBAL_OBJECT_NAME);
00401 return 0;
00402 }
00403 if( db5_import_attributes( &avs, &raw.attributes ) < 0 ) {
00404 bu_log("db_dirbuild(%s): improper database, corrupted attribute-only %s object\n",
00405 dbip->dbi_filename, DB5_GLOBAL_OBJECT_NAME );
00406 bu_free_external(&ext);
00407 return -1;
00408 }
00409 BU_CK_AVS( &avs );
00410
00411
00412 if( (cp = bu_avs_get( &avs, "title" )) != NULL ) {
00413 dbip->dbi_title = bu_strdup( cp );
00414 } else {
00415 dbip->dbi_title = bu_strdup( "Untitled BRL-CAD database" );
00416 }
00417 if( (cp = bu_avs_get( &avs, "units" )) != NULL ) {
00418 double dd;
00419 if( sscanf( cp, "%lf", &dd ) != 1 ||
00420 NEAR_ZERO( dd, VUNITIZE_TOL ) ) {
00421 bu_log("db_dirbuild(%s): improper database, %s object attribute 'units'=%s is invalid\n",
00422 dbip->dbi_filename, DB5_GLOBAL_OBJECT_NAME,
00423 cp );
00424
00425 } else {
00426 dbip->dbi_local2base = dd;
00427 dbip->dbi_base2local = 1/dd;
00428 }
00429 }
00430 if( (cp = bu_avs_get( &avs, "regionid_colortable")) != NULL ) {
00431
00432 db5_import_color_table( (char *)cp);
00433 }
00434 bu_avs_free( &avs );
00435 bu_free_external(&ext);
00436 return 0;
00437 }
00438
00439
00440 if( header[0] == 'I' ) {
00441 dbip->dbi_version = 4;
00442 if( db_scan( dbip, (int (*)())db_diradd, 1, NULL ) < 0 ) {
00443 dbip->dbi_version = 0;
00444 return -1;
00445 }
00446 return 0;
00447 }
00448
00449 bu_log("db_dirbuild(%s) ERROR, file is not in BRL-CAD geometry database format\n",
00450 dbip->dbi_filename);
00451 return -1;
00452 }
00453
00454
00455 int
00456 db_get_version(struct db_i *dbip)
00457 {
00458 unsigned char header[8];
00459
00460 rewind(dbip->dbi_fp);
00461 if( fread( header, sizeof header, 1, dbip->dbi_fp ) != 1 ) {
00462 bu_log("db_get_version ERROR, file (%s) too short to be BRL-CAD database\n",
00463 dbip->dbi_filename);
00464 return -1;
00465 }
00466
00467 if( db5_header_is_valid( header ) )
00468 return( 5 );
00469 else if( header[0] == 'I' )
00470 return( 4 );
00471 else
00472 return( -1 );
00473
00474 }
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485