On Sun, Oct 19, 2014 at 12:44 PM, Gurwinder Singh Bains <gswithba...@gmail.com> wrote: > BRL-CAD stores database into binary format. I am trying to store it in > text format. I have read that in binary .g file information is stored > as Header, Title of database, Units, Objects, Matter, Combination etc. > and in last Footer. There is g2asc which converts binary data into ASC > but when I use command "g2asc .g_file_name .asc_file_name", it doesn't > write Header, Footer and other contents which are in binary file. > Is there any way to get or store our brl-cad's .g into text format? I > have searched brlcad's directory, there are many flex and bison file > that are used for parsing the binary file, can they help me in doing this? > > Which function( location ) is used for reading binary data and store > them into memory? How can I read data and then store all the binary > information into text form without doing any conversion?
Gurwinder, I'm not sure why you want to convert to text, but there is a program I wrote on one of the dev branches which, if I remember correctly, will do at least part of what you wish. >From sourceforge, check out the "attr-extension-mods" branch, build it, and try the "admin-db" program. Comments welcome. ... Unfortunately it hasn't been checked in, but attached is the source file (I'll tidy up my dev branch later): Best regards, -Tom
#include "common.h" #include <string> #include <map> #include <stdlib.h> #include <sys/stat.h> #include "bio.h" #include "bu_arg_parse.h" // includes bu.h #include "raytrace.h" using namespace std; static const char usage[] = "Example: admin-db [...options] db.g [db2.g]\n"; /* purpose: manage various aspects of a BRL-CAD database * * description: Enables the user to perform various tasks on a BRL-CAD * database (DB) file including reporting statistics and shortening * the DB file by removing unused free space. The original DB file * is opened read-only and is not modified in any way. * * The only option at the moment is to compress the input DB by removing * unused free space which accumulates during the construction of a BRL-CAD model. * The shortened copy of the input DB is written to a new file which may be named * by the user, otherwise the new file is name "<input file name>.compressed". * * As an example of how much a DB can grow during construction, creating a model * consisting of 1,000 spheres and killing all of them, and doing that 10 times, * creates a 45 Mb file. Then converting it to ASCII and back reduces * the file size to 250 Kb. (Note the use of g2asc and asc2g may allow mathematical * errors to creep in so their use is not recommended for production models.) */ string get_dli_type_name(const int typ); string get_minor_type_name(const int typ); string get_major_type_name(const int typ); int main(int argc, char** argv) { // db pointers FILE *in = NULL; FILE *out = NULL; int res = 0; // for function returns struct stat sb; const char DBSUF[] = ".compressed"; // vars expected from cmd line parsing int arg_err = 0; int has_force = 0; int has_help = 0; int has_compress = 0; char db_fname[BU_ARG_PARSE_BUFSZ] = {0}; char db2_fname[BU_ARG_PARSE_BUFSZ] = {0}; // FIXME: this '-?' arg doesn't work correctly due to some TCLAPisms static bu_arg_switch_t h_arg; // define a force option to allow user to shoot himself in the foot static bu_arg_switch_t f_arg; // define a compress option static bu_arg_switch_t c_arg; // input file names static bu_arg_unlabeled_value_t db_arg; // the output file name (optional) static bu_arg_unlabeled_value_t db2_arg; // place the arg pointers in an array (note the array is of // type void* to hold the heterogeneous arg type structs) static void *args[] = { &h_arg, &f_arg, &c_arg, &db_arg, &db2_arg, NULL }; BU_ARG_SWITCH_INIT( h_arg, "?", "short-help", "Same as '-h' or '--help'" ); BU_ARG_SWITCH_INIT( f_arg, "f", "force", "Allow overwriting existing files." ); BU_ARG_SWITCH_INIT( c_arg, "c", "compress", "Create a copy with no free space." ); // input file name BU_ARG_UNLABELED_VALUE_INIT( db_arg, "", "DB_infile", "DB input file name", BU_ARG_REQUIRED, BU_ARG_STRING, "" ); // the output file name (optional) BU_ARG_UNLABELED_VALUE_INIT( db2_arg, "", "DB_outfile", "DB output file name", BU_ARG_OPTIONAL, BU_ARG_STRING, "" ); // parse the args arg_err = bu_arg_parse(args, argc, argv); if (arg_err == BU_ARG_PARSE_ERR) { // the TCLAP exception handler has fired with its own message // so need no message here bu_exit(EXIT_SUCCESS, NULL); } // Get the value parsed by each arg. has_force = bu_arg_get_bool(&f_arg); has_help = bu_arg_get_bool(&h_arg); has_compress = bu_arg_get_bool(&c_arg); bu_arg_get_string(&db_arg, db_fname); bu_arg_get_string(&db2_arg, db2_fname); // take appropriate action... // note this exit is SUCCESS because it is expected // behavior--important for good auto-man-page handling if (has_help) { bu_exit(EXIT_SUCCESS, usage); } if (has_compress) { if (!db2_fname[0]) { bu_strlcpy(db2_fname, db_fname, BU_ARG_PARSE_BUFSZ); bu_strlcat(db2_fname, DBSUF, BU_ARG_PARSE_BUFSZ); } } // open the db file read-only // TCLAP doesn't check for existing files (FIXME: add to TCLAP) if (stat(db_fname, &sb)) { bu_exit(EXIT_FAILURE, "non-existent input file '%s'\n", db_fname); } in = fopen(db_fname, "r"); if (!in) { perror(db_fname); bu_exit(EXIT_FAILURE, "ERROR: input file open failure\n"); } if (has_compress) { // TCLAP doesn't check for confusion in file names if (BU_STR_EQUAL(db_fname, db2_fname)) { bu_exit(EXIT_FAILURE, "overwriting an input file\n"); } // check for existing file if (!stat(db2_fname, &sb)) { if (has_force) { printf("WARNING: overwriting an existing file...\n"); bu_file_delete(db2_fname); } else { bu_exit(EXIT_FAILURE, "overwriting an existing file (use the '-f' option to continue)\n"); } } out = fopen(db2_fname, "w"); if (!out) { perror(db2_fname); bu_exit(EXIT_FAILURE, "ERROR: output file open failure\n"); } } // database analysis ======================== // a struct to hold a raw db object (see db5.h) struct db5_raw_internal r; // track dli, major, and minor types map<int,int> dli_count; map<int,int> major_count; map<int,int> minor_count; int nobj = 0; int fobj = 0; int nsiz = 0; int free_bytes = 0; int named_obj = 0; int ncombs = 0; int nregs = 0; int wattrs = 0; // write an output header int fnsiz = strlen(db_fname); string eqs = ""; for (int i = 0; i < fnsiz; ++i) eqs += '='; printf("=======================================%s=\n", eqs.c_str()); printf(" Objects found in BRL-CAD V5 database: %s \n", db_fname); printf("=======================================%s=\n", eqs.c_str()); printf("\n"); // start reading the input file r.magic = DB5_RAW_INTERNAL_MAGIC; // see db5_io.c for the reading function: while ((res = db5_get_raw_internal_fp(&r, in)) == 0) { RT_CK_RIP(&r); ++nobj; // new primary type info in h flags (DLI) (see db5.h): // 0 = app data object; 1 = header object; 2 = free storage int typ = static_cast<int>(r.h_dli); // get major and minor type int M = static_cast<int>(r.major_type); int m = static_cast<int>(r.minor_type); if (dli_count.find(M) != dli_count.end()) ++dli_count[typ]; else { dli_count[typ] = 1; string s = get_dli_type_name(typ); int len = static_cast<int>(s.size()); if (len > nsiz) nsiz = len; } // named object? bool has_name = static_cast<bool>(r.h_name_present); string name("(none)"); if (has_name) { ++named_obj; size_t len = r.name.ext_nbytes; name = ""; for (size_t i = 0; i < len; ++i) name += r.name.ext_buf[i]; } if (major_count.find(M) != major_count.end()) ++major_count[M]; else { major_count[M] = 1; string s = get_major_type_name(typ); int len = static_cast<int>(s.size()); if (len > nsiz) nsiz = len; } if (minor_count.find(m) != minor_count.end()) ++minor_count[m]; else { minor_count[m] = 1; string s = get_minor_type_name(typ); int len = static_cast<int>(s.size()); if (len > nsiz) nsiz = len; } printf("Object DLI type/major/minor type: %3d/%3d/%3d name: %s\n", typ, M, m, name.c_str()); // has attributes? if (r.a_present) { printf(" Has one or more attributes.\n"); ++wattrs; } if (m == DB5_MINORTYPE_BRLCAD_COMBINATION) { ++ncombs; printf(" Is a combination"); // is it a region? // extract attributes size_t len = r.attributes.ext_nbytes; string a= ""; for (size_t i = 0; i < len; ++i) { if (r.attributes.ext_buf[i]) { char c = tolower(r.attributes.ext_buf[i]); if (a.empty() && c != 'r') continue; a += c; } } if (a.find("region") != string::npos) { printf(" (a region)"); ++nregs; } printf(".\n"); } // FIXME: (will have to do more decoding for that answer) if (typ == DB5HDR_HFLAGS_DLI_FREE_STORAGE) { // free space, count bytes (object counted above) free_bytes += static_cast<int>(r.object_length); ++fobj; } else if (has_compress) { // write the object to the output file size_t nw = fwrite(r.buf, 1, r.object_length, out); if (nw != r.object_length) bu_bomb("nw != r.object_length"); } // free the heap stuff if (r.buf) { bu_free(r.buf, "r.buf"); } } printf("\n"); printf("==================================%s=\n", eqs.c_str()); printf(" Summary for BRL-CAD V5 database: %s\n", db_fname); printf("==================================%s=\n", eqs.c_str()); printf("\n"); printf("Found %d objects:\n", nobj); printf(" free space: %6d\n", fobj); printf(" named : %6d\n", named_obj); printf(" other : %6d\n", nobj - fobj - named_obj); bool sepr(false); if (ncombs) { sepr = true; printf("\n"); printf("%d objects are combinations (%d of which are regions).\n", ncombs, nregs); } if (wattrs) { if (!sepr) { sepr = true; printf("\n"); } printf("%d objects have one or more attributes.\n", wattrs); } printf("\n"); printf("Object DLI types (the main category: defined in H Flags):\n"); for (map<int,int>::iterator i = dli_count.begin(); i != dli_count.end(); ++i) { // get name of dli type string tname = get_dli_type_name(i->first); int tlen = static_cast<int>(tname.size()); int bsiz = nsiz - tlen + 3; printf(" %3d (%-s)%-*.*s: %6d\n", i->first, tname.c_str(), bsiz, bsiz, " ", i->second); } printf("Object major types:\n"); for (map<int,int>::iterator i = major_count.begin(); i != major_count.end(); ++i) { // get name of major type string tname = get_major_type_name(i->first); int tlen = static_cast<int>(tname.size()); int bsiz = nsiz - tlen + 3; printf(" %3d (%-s)%-*.*s: %6d\n", i->first, tname.c_str(), bsiz, bsiz, " ", i->second); } printf("Object minor types:\n"); for (map<int,int>::iterator i = minor_count.begin(); i != minor_count.end(); ++i) { // get name of minor type string tname = get_minor_type_name(i->first); int tlen = static_cast<int>(tname.size()); int bsiz = nsiz - tlen + 3; printf(" %3d (%-s)%-*.*s: %6d\n", i->first, tname.c_str(), bsiz, bsiz, " ", i->second); } printf("\n"); if (fobj) { const double kb = 1024; const double mb = kb * 1000; printf("Free space: %d bytes", free_bytes); if (free_bytes > mb) printf(" (%.3f Mb)", free_bytes/mb); else if (free_bytes > kb) printf(" (%.3f Kb)", free_bytes/kb); printf("\n"); } if (res == -1) printf("\nNote: file read ended normally at EOF.\n"); else printf("\nNote: file read ended early with an error!\n"); if (has_compress) printf("See compressed file '%s'.\n", db2_fname); return 0; } // main string get_dli_type_name(const int typ) { // list from db5.h: switch(typ) { case 0: return "APPLICATION_DATA_OBJECT"; break; case 1: return "HEADER_OBJECT"; break; case 2: return "FREE_STORAGE"; break; default: return "unknown"; break; } } // get_dli_type_name string get_major_type_name(const int typ) { // list from db5.h: switch(typ) { case 0: return "RESERVED"; break; case 1: return "BRLCAD"; break; case 2: return "ATTRIBUTE_ONLY"; break; case 9: return "BINARY_UNIF"; break; case 10: return "BINARY_MIME"; break; default: return "unknown"; break; } } // get_major_type_name string get_minor_type_name(const int typ) { // list from db5.h: switch(typ) { case 0: return "RESERVED"; break; case 1: return "TOR"; break; case 2: return "TGC"; break; case 3: return "ELL"; break; case 4: return "ARB8"; break; case 5: return "ARS"; break; case 6: return "HALF"; break; case 7: return "REC"; break; case 8: return "POLY"; break; case 9: return "BSPLINE"; break; case 10: return "SPH"; break; case 11: return "NMG"; break; case 12: return "EBM"; break; case 13: return "VOL"; break; case 14: return "ARBN"; break; case 15: return "PIPE"; break; case 16: return "PARTICLE"; break; case 17: return "RPC"; break; case 18: return "RHC"; break; case 19: return "EPA"; break; case 20: return "EHY"; break; case 21: return "ETO"; break; case 22: return "GRIP"; break; case 23: return "JOINT"; break; case 24: return "HF"; break; case 25: return "DSP"; break; case 26: return "SKETCH"; break; case 27: return "EXTRUDE"; break; case 28: return "SUBMODEL"; break; case 29: return "CLINE"; break; case 30: return "BOT"; break; case 31: return "COMBINATION"; break; case 35: return "SUPERELL"; break; case 36: return "METABALL"; break; case 37: return "BREP"; break; case 38: return "HYP"; break; case 39: return "CONSTRAINT"; break; case 40: return "REVOLVE"; break; case 41: return "ANNOTATION"; break; case 42: return "HRT"; break; default: return "unknown"; break; } } // get_minor_type_name
------------------------------------------------------------------------------
_______________________________________________ BRL-CAD Developer mailing list brlcad-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/brlcad-devel