home *** CD-ROM | disk | FTP | other *** search
- // dump.cpp - datafile dump utility sample code
- //
- // This is a part of the MetaKit library.
- // Copyright (c) 1996 Meta Four Software.
- // All rights reserved.
- /////////////////////////////////////////////////////////////////////////////
- //
- // This command-line utility displays different aspects of a datafile
- // created with the MetaKit library: field structure (-f), low-level
- // table structure (-s), low-level table contents dump (-d), or a
- // normal dump of the entire view contents (default).
- //
- /////////////////////////////////////////////////////////////////////////////
-
- #include "m4kit.h"
- #include "k4field.h"
- #include "k4table.h"
-
- #include <stdio.h>
- #include <string.h> // memcpy
-
- #if defined (unix)
- #define try
- #define catch(x) if (0)
- #endif
-
- #if defined (macintosh)
- #include /**/ <console.h>
- #define d4_InitMain(c,v) c = ccommand(&v)
- #endif
-
- typedef unsigned char uchar;
- typedef unsigned long ulong;
-
- /////////////////////////////////////////////////////////////////////////////
- // Recursively display the field structure, table contents is not used here.
-
- static void FieldDisplay(c4_Field& f_, int l_ =0)
- {
- printf("%*s FIELD %s off %d, width %d, depth %d : %s\n",
- l_, "",
- f_.IsRepeating() ? "[*] " : "",
- f_.Offset(), f_.Width(), f_.Depth(),
- (const char*) f_.Tag());
-
- int nc = f_.NumSubColumns();
- if (nc > 0)
- {
- printf("%*s columns:", l_, "");
- for (int i = 0; i < nc; ++i)
- printf(" %d.%s", i, (const char*) f_.SubColumn(i).Name());
- printf("\n");
- }
-
- int nf = f_.NumSubFields();
- if (nf > 0)
- {
- printf("%*s fields:", l_, "");
- for (int i = 0; i < nf; ++i)
- printf(" %d.%s", i, (const char*) f_.SubField(i).Name());
- printf("\n");
-
- for (int j = 0; j < nf; ++j)
- // skip first field in root to avoid infinite recursion
- if (l_ > 0 || j > 0)
- FieldDisplay(f_.SubField(j), l_ + 2);
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Recursively display the raw table structure (optionally also contents).
- // This code does not use views, and attempts to continue after all errors.
-
- static bool TableDisplay(c4_Table& t_, bool full_, int l_ =0)
- {
- int errors = 0;
-
- int nr = t_.NumRows();
- int nc = t_.NumColumns();
-
- printf("%*s TABLE %5d rows, %d cols\n", l_, "", nr, nc);
-
- for (int i = 0; i < nc; ++i)
- {
- c4_Field& f = t_.Field(i);
-
- if (f.IsRepeating())
- {
- for (int k = 0; k < nr; ++k)
- {
- printf("%*s %4d: subtable [%d] %s\n", l_, "", i, k,
- (const char*) f.Name());
-
- // skip first field in root to avoid infinite recursion
- if (l_ > 0 || i > 0)
- try
- {
- if (!TableDisplay(t_.SubTable(i, k), full_, l_ + 2))
- ++errors;
- }
- catch (...)
- {
- printf("*** Error in subtable (%s[%d].%s) ***\n",
- (const char*) t_.Definition().Tag(),
- k, (const char*) f.Name());
- ++errors;
- }
-
- if (errors >= 5)
- {
- printf("*** Too many errors, bailing out ***\n");
- break;
- }
- }
- }
- else
- {
- c4_Column& c = t_.Column(i);
- printf("%*s %4d:%5u @ %-5lu %s", l_, "", i,
- c.Size(), c.Position(), (const char*) f.Name());
-
- if (full_)
- {
- uchar data [16];
-
- // produces a readable hex/ascii dump of column c
- for (ulong j = 0; j < c.Size(); j += 16)
- {
- int n1;
- const uchar* ptr = t_.LoadColumn(i, j, n1);
- if (n1 > 16)
- n1 = 16;
- memcpy(data, ptr, n1);
-
- if (n1 < 16)
- {
- int n2;
- ptr = t_.LoadColumn(i, j + n1, n2);
- if (n1 + n2 > 16)
- n1 = 16 - n2;
- memcpy(data + n1, ptr, n2);
- }
-
- printf("\n %22lu: ", j);
-
- for (int k = 0; k < 16; ++k)
- {
- if (k % 4 == 0)
- printf(" ");
-
- if (j + k < c.Size())
- printf("%02X", data[k]);
- else
- printf(" ");
- }
-
- printf(" ");
-
- for (int l = 0; l < 16; ++l)
- {
- int ch = ' ';
- if (j + l < c.Size())
- {
- ch = data[l] & 0x7F;
- if (ch < ' ' || ch > '~')
- ch = ' ';
- }
-
- printf("%c", ch);
- }
- }
- }
-
- printf("\n");
- }
- }
-
- return errors == 0;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // Recursively display the entire view contents. The results shown do not
- // depend on file layout (free space, file positions, flat vs. on-demand).
-
- static void ViewDisplay(const c4_View& v_, int l_ =0)
- {
- c4_String types;
- bool hasData = false, hasSubs = false;
-
- // display header info and collect all data types
- printf("%*s VIEW %5d rows =", l_, "", v_.GetSize());
- for (int n = 0; n < v_.NumProperties(); ++n)
- {
- c4_Property prop = v_.NthProperty(n);
- char t = prop.Type();
-
- printf(" %s:%c", (const char*) prop.Name(), t);
-
- types += t;
-
- if (t == 'V')
- hasSubs = true;
- else
- hasData = true;
- }
- printf("\n");
-
- for (int j = 0; j < v_.GetSize(); ++j)
- {
- if (hasData) // data properties are all shown on the same line
- {
- printf("%*s %4d:", l_, "", j);
- c4_RowRef r = v_[j];
-
- for (int k = 0; k < types.GetLength(); ++k)
- {
- c4_Property p = v_.NthProperty(k);
-
- switch (types[k])
- {
- case 'I':
- printf(" %ld", (long) ((c4_IntProp&) p) (r));
- break;
-
- case 'F':
- printf(" %g", (double) ((c4_FloatProp&) p) (r));
- break;
-
- case 'D':
- printf(" %.12g", (double) ((c4_DoubleProp&) p) (r));
- break;
-
- case 'S':
- printf(" '%s'", (const char*) (c4_String)
- ((c4_StringProp&) p) (r));
- break;
-
- default:
- if (types[k] != 'V')
- printf(" (%c?)", types[k]);
- }
- }
-
- printf("\n");
- }
-
- if (hasSubs) // subviews are then shown, each as a separate block
- {
- for (int k = 0; k < types.GetLength(); ++k)
- {
- if (types[k] == 'V')
- {
- c4_Property prop = v_.NthProperty(k);
-
- printf("%*s %4d: subview '%s'\n", l_, "", j,
- (const char*) prop.Name());
-
- if (l_ > 0 || k > 0)
- {
- c4_ViewProp& vp = (c4_ViewProp&) prop;
-
- ViewDisplay(vp (v_[j]), l_ + 2);
- }
- }
- }
- }
- }
- }
-
- /////////////////////////////////////////////////////////////////////////////
-
- int main(int argc, char** argv)
- {
- #ifdef d4_InitMain
- d4_InitMain(argc, argv);
- #endif
-
- bool sFlag = false, dFlag = false, fFlag = false, wFlag = false;
-
- while (argc > 1 && (argv[1][0] == '-' || argv[1][0] == '/'))
- {
- --argc;
- switch ((*++argv)[1])
- {
- case 's': case 'S': sFlag = true; break;
- case 'd': case 'D': dFlag = true; break;
- case 'f': case 'F': fFlag = true; break;
- case 'w': case 'W': wFlag = true; break;
- }
- }
-
- const char* msg = 0;
-
- if (argc != 2)
- fprintf(stderr, "Usage: DUMP [-s|-d|-f|-w] file\n");
- else
- try
- {
- msg = "could not open data file";
-
- c4_Storage store (argv[1], false);
-
- msg = "file may be damaged";
-
- c4_View base = store.Contents().Container();
-
- printf("%s: %d properties\n %s\n\n",
- argv[1], base.NumProperties(),
- (const char*) store.Description());
-
-
- if (sFlag || dFlag || fFlag)
- {
- c4_Table& root = store.RootTable();
- c4_Field& field = root.Definition();
-
- if (fFlag)
- {
- FieldDisplay(field);
- msg = 0;
- }
- else if (TableDisplay(root, dFlag))
- msg = 0;
- }
- else
- {
- ViewDisplay(base);
-
- msg = 0;
- }
- }
- catch (...)
- {
- }
-
- if (msg)
- fprintf(stderr, "Abnormal termination, %s\n", msg);
-
- if (wFlag)
- getchar();
-
- return msg ? 1 : 0;
- }
-
- /////////////////////////////////////////////////////////////////////////////
- // $Id: dump.cpp,v 1.6 1996/12/06 22:33:10 jcw Exp $
-