Revision: 76955
          http://sourceforge.net/p/brlcad/code/76955
Author:   d_rossberg
Date:     2020-08-26 10:54:40 +0000 (Wed, 26 Aug 2020)
Log Message:
-----------
functions to read the binary database data (as it is contained in a .g file) 
from RAM into an in-memory database instance
the main function to use is rt_dirbuild_inmem()
very early alpha status, but can be tested

Modified Paths:
--------------
    brlcad/trunk/include/rt/db_io.h
    brlcad/trunk/src/librt/db5_scan.c
    brlcad/trunk/src/librt/dir.c

Modified: brlcad/trunk/include/rt/db_io.h
===================================================================
--- brlcad/trunk/include/rt/db_io.h     2020-08-26 03:06:49 UTC (rev 76954)
+++ brlcad/trunk/include/rt/db_io.h     2020-08-26 10:54:40 UTC (rev 76955)
@@ -639,6 +639,7 @@
  * -1 failure
  */
 RT_EXPORT extern int db_dirbuild(struct db_i *dbip);
+RT_EXPORT extern int db_dirbuild_inmem(struct db_i *dbip, const void *data, 
b_off_t data_size);
 RT_EXPORT extern struct directory *db5_diradd(struct db_i *dbip,
                                              const struct db5_raw_internal 
*rip,
                                              b_off_t laddr,
@@ -657,6 +658,14 @@
                                              b_off_t addr,
                                              void *client_data),
                              void *client_data);
+RT_EXPORT extern int db5_scan_inmem(struct db_i *dbip,
+                                   void (*handler)(struct db_i *,
+                                                   const struct 
db5_raw_internal *,
+                                                   b_off_t addr,
+                                                   void *client_data),
+                                   void *client_data,
+                                   const void *data,
+                                   b_off_t data_size);
 
 /**
  * obtain the database version for a given database instance.
@@ -664,6 +673,7 @@
  * presently returns only a 4 or 5 accordingly.
  */
 RT_EXPORT extern int db_version(struct db_i *dbip);
+RT_EXPORT extern int db_version_inmem(struct db_i *dbip, const void *data, 
b_off_t data_size);
 
 
 /* db_corrupt.c */
@@ -922,6 +932,7 @@
  * Read named MGED db, build toc.
  */
 RT_EXPORT extern struct rt_i *rt_dirbuild(const char *filename, char *buf, int 
len);
+RT_EXPORT extern struct rt_i *rt_dirbuild_inmem(const void *data, b_off_t 
data_size, char *buf, int len);
 
 
 /* db5_types.c */

Modified: brlcad/trunk/src/librt/db5_scan.c
===================================================================
--- brlcad/trunk/src/librt/db5_scan.c   2020-08-26 03:06:49 UTC (rev 76954)
+++ brlcad/trunk/src/librt/db5_scan.c   2020-08-26 10:54:40 UTC (rev 76955)
@@ -110,6 +110,57 @@
 }
 
 
+int
+db5_scan_inmem(
+    struct db_i *dbip,
+    void (*handler)(struct db_i *,
+                   const struct db5_raw_internal *,
+                   b_off_t addr, void *client_data),
+    void *client_data,
+    const void *data,
+    b_off_t data_size)
+{
+    unsigned char header[8];
+    struct db5_raw_internal raw;
+    size_t nrec;
+    b_off_t addr;
+    const unsigned char *cp = (const unsigned char *)data;
+
+    RT_CK_DBI(dbip);
+    if (RT_G_DEBUG&RT_DEBUG_DB) bu_log("db5_scan_inmem(%p, %lx)\n",
+                                   (void *)dbip, (long unsigned int)handler);
+
+    raw.magic = DB5_RAW_INTERNAL_MAGIC;
+    nrec = 0L;
+
+    if (db5_header_is_valid(cp) == 0) {
+       bu_log("db5_scan_inmem ERROR:  data is lacking a proper BRL-CAD v5 
database header\n");
+       goto fatal;
+    }
+    cp += sizeof(header);
+    addr = (b_off_t)sizeof(header);
+    while (addr < data_size) {
+       const unsigned char *current_data = cp;
+       void *dp_copy;
+       if ((cp = db5_get_raw_internal_ptr(&raw, cp)) == NULL) {
+           goto fatal;
+       }
+       dp_copy = bu_malloc(raw.object_length, "db5_scan_inmem raw dp data");
+       memcpy(dp_copy, current_data, raw.object_length);
+       (*handler)(dbip, &raw, (b_off_t)dp_copy, client_data);
+       nrec++;
+       addr += (b_off_t)raw.object_length;
+    }
+
+    dbip->dbi_nrec = nrec;             /* # obj in db, not inc. header */
+    return 0;                  /* success */
+
+fatal:
+    dbip->dbi_read_only = 1;   /* Writing could corrupt it worse */
+    return -1;                 /* fatal error */
+}
+
+
 struct directory *
 db_diradd5(
     struct db_i *dbip,
@@ -252,6 +303,8 @@
     }
     if (rip->h_name_hidden)
        dp->d_flags |= RT_DIR_HIDDEN;
+    if (dbip->dbi_wdbp->type == RT_WDB_TYPE_DB_INMEM)
+       dp->d_flags |= RT_DIR_INMEM;
     dp->d_len = rip->object_length;            /* in bytes */
     BU_LIST_INIT(&dp->d_use_hd);
     dp->d_animate = NULL;
@@ -417,6 +470,112 @@
 
 
 int
+db_dirbuild_inmem(struct db_i *dbip, const void *data, b_off_t data_size)
+{
+    int version;
+
+    if (!dbip)
+       return -1;
+
+    RT_CK_DBI(dbip);
+
+    /* First, determine what version database this is */
+    version = db_version_inmem(dbip, data, data_size);
+
+    if (version == 5) {
+       struct directory *dp;
+       struct bu_external ext;
+       struct db5_raw_internal raw;
+       struct bu_attribute_value_set avs;
+       const char *cp;
+
+       bu_avs_init_empty(&avs);
+
+       /* File is v5 format */
+       if (db5_scan_inmem(dbip, db5_diradd_handler, NULL, data, data_size) < 
0) {
+           bu_log("db_dirbuild_inmem(): db5_scan_inmem() failed\n");
+           return -1;
+       }
+
+       /* Need to retrieve _GLOBAL object and obtain title and units */
+       if ((dp = db_lookup(dbip, DB5_GLOBAL_OBJECT_NAME, LOOKUP_NOISY)) == 
RT_DIR_NULL) {
+           bu_log("db_dirbuild_inmem(): improper database, no %s object\n",
+                  DB5_GLOBAL_OBJECT_NAME);
+           dbip->dbi_title = bu_strdup(DB5_GLOBAL_OBJECT_NAME);
+           /* Missing _GLOBAL object so create it and set default title and 
units */
+           db5_update_ident(dbip, "Untitled BRL-CAD Database", 1.0);
+           return 0;   /* not a fatal error, user may have deleted it */
+       }
+
+       BU_EXTERNAL_INIT(&ext);
+
+       if (db_get_external(&ext, dp, dbip) < 0 ||
+           db5_get_raw_internal_ptr(&raw, ext.ext_buf) == NULL) {
+           bu_log("db_dirbuild_inmem(): improper database, unable to read %s 
object\n",
+                  DB5_GLOBAL_OBJECT_NAME);
+           return -1;
+       }
+
+       if (raw.major_type != DB5_MAJORTYPE_ATTRIBUTE_ONLY) {
+           bu_log("db_dirbuild_inmem(): improper database, %s exists but is 
not an attribute-only object\n",
+                  DB5_GLOBAL_OBJECT_NAME);
+           dbip->dbi_title = bu_strdup(DB5_GLOBAL_OBJECT_NAME);
+           return 0;   /* not a fatal error, need to let user proceed to fix 
it */
+       }
+
+       /* Parse out the attributes */
+       if (db5_import_attributes(&avs, &raw.attributes) < 0) {
+           bu_log("db_dirbuild_inmem(): improper database, corrupted 
attribute-only %s object\n",
+                  DB5_GLOBAL_OBJECT_NAME);
+           bu_free_external(&ext);
+           return -1;  /* this is fatal */
+       }
+
+       BU_CK_AVS(&avs);
+
+       /* 1/3: title */
+       if ((cp = bu_avs_get(&avs, "title")) != NULL)
+           dbip->dbi_title = bu_strdup(cp);
+       else
+           dbip->dbi_title = bu_strdup("Untitled BRL-CAD database");
+
+       /* 2/3: units */
+       if ((cp = bu_avs_get(&avs, "units")) != NULL) {
+           double dd;
+           if (sscanf(cp, "%lf", &dd) != 1 || NEAR_ZERO(dd, VUNITIZE_TOL)) {
+               bu_log("db_dirbuild_inmem(): improper database, %s object 
attribute 'units'=%s is invalid\n",
+                      DB5_GLOBAL_OBJECT_NAME, cp);
+               /* Not fatal, just stick with default value from db_open() */
+           } else {
+               dbip->dbi_local2base = dd;
+               dbip->dbi_base2local = 1/dd;
+           }
+       }
+
+       /* 3/3: color table */
+       if ((cp = bu_avs_get(&avs, "regionid_colortable")) != NULL)
+           /* Import the region-id coloring table */
+           db5_import_color_table((char *)cp);
+
+       bu_avs_free(&avs);
+       bu_free_external(&ext); /* not until after done with avs! */
+
+       return 0;               /* ok */
+    } else if (version == 4) {
+       /* things used to be pretty simple with v4 */
+       if (db_scan(dbip, db_diradd4, 1, NULL) < 0)
+           return -1;
+
+       return 0;               /* ok */
+    }
+
+    bu_log("ERROR: Cannot build object directory.\n\tData does not seem to be 
in BRL-CAD geometry database format.\n");
+
+    return -1;
+}
+
+
+int
 db_version(struct db_i *dbip)
 {
     unsigned char header[8];
@@ -451,6 +610,37 @@
 }
 
 
+int
+db_version_inmem(struct db_i *dbip, const void *data, b_off_t data_size)
+{
+    const unsigned char* header;
+
+    if (!dbip)
+       return -1;
+
+    RT_CK_DBI(dbip);
+
+    /* already calculated during db_open? */
+    if (dbip->dbi_version != 0)
+       return abs(dbip->dbi_version);
+
+    rewind(dbip->dbi_fp);
+    if (!data || (data_size < 8)) {
+       bu_log("ERROR: data chunk too short to be a BRL-CAD database\n");
+       return -1;
+    }
+
+    header = (const unsigned char *)data;
+
+    if (db5_header_is_valid(header))
+       return 5;
+    else if (header[0] == 'I')
+       return 4;
+
+    return -1;
+}
+
+
 /*
  * Local Variables:
  * mode: C

Modified: brlcad/trunk/src/librt/dir.c
===================================================================
--- brlcad/trunk/src/librt/dir.c        2020-08-26 03:06:49 UTC (rev 76954)
+++ brlcad/trunk/src/librt/dir.c        2020-08-26 10:54:40 UTC (rev 76955)
@@ -72,6 +72,47 @@
 }
 
 
+/**
+ * Builds an in-memory database directory of the object names read
+ * from an array with the raw data, i.e. a .g database file content.
+ *
+ * Allocate and initialize information for this instance of an RT
+ * model database.
+ *
+ * Returns -
+ * (struct rt_i *) Success
+ * RTI_NULL Fatal Error
+ */
+struct rt_i *
+rt_dirbuild_inmem(const void *data, b_off_t data_size, char *buf, int len)
+{
+    register struct rt_i *rtip;
+    register struct db_i *dbip;                /* Database instance ptr */
+
+    if (rt_uniresource.re_magic == 0)
+       rt_init_resource(&rt_uniresource, 0, NULL);
+
+    if ((dbip = db_open_inmem()) == DBI_NULL)
+       return RTI_NULL;                /* FAIL */
+    RT_CK_DBI(dbip);
+
+    if ((data != NULL) && (data_size > 0)) {
+       if (db_dirbuild_inmem(dbip, data, data_size) < 0) {
+           db_close(dbip);
+           return RTI_NULL;            /* FAIL */
+       }
+    }
+
+    rtip = rt_new_rti(dbip);           /* clones dbip */
+    db_close(dbip);                            /* releases original dbip */
+
+    if (buf != (char *)NULL)
+       bu_strlcpy(buf, dbip->dbi_title, len);
+
+    return rtip;                               /* OK */
+}
+
+
 int
 rt_db_get_internal(
     struct rt_db_internal *ip,

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.



_______________________________________________
BRL-CAD Source Commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/brlcad-commits

Reply via email to