home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / drgrnd.zip / dbaccess.c next >
C/C++ Source or Header  |  1993-07-18  |  18KB  |  396 lines

  1. /*********************************************************************
  2.  *                                                                   *
  3.  * MODULE NAME :  dbaccess.c             AUTHOR:  Rick Fishman       *
  4.  * DATE WRITTEN:  07-16-93                                           *
  5.  *                                                                   *
  6.  * MODULE DESCRIPTION:                                               *
  7.  *                                                                   *
  8.  *  Part of the 'DRGRENDR' drag/drop sample program.                 *
  9.  *                                                                   *
  10.  *  Access module that provides functions to access the data in the  *
  11.  *  'database'.                                                      *
  12.  *                                                                   *
  13.  * NOTES:                                                            *
  14.  *                                                                   *
  15.  *  This 'database' is structured with multiple dbase_?.db files     *
  16.  *  that each have multiple database 'tables'. Each table is marked  *
  17.  *  by a TABLEKEY=> line that provides a table name. Following that  *
  18.  *  line are the rows of that table. The table is delimited by       *
  19.  *  the next TABLEKEY=> line. The file is delimited by this line:    *
  20.  *                                                                   *
  21.  *  TABLEKEY=>end_of_database                                        *
  22.  *                                                                   *
  23.  *  Yes, IBM has been after me to incorporate this amazing database  *
  24.  *  technology into their mainframe databases <g>.... NOT!           *
  25.  *                                                                   *
  26.  *  Have a look at the dbase_?.db files that were supplied with this *
  27.  *  sample for further clarification.                                *
  28.  *                                                                   *
  29.  * FUNCTIONS AVALABLE TO OTHER MODULES:                              *
  30.  *                                                                   *
  31.  *   dbBeginEnumTables                                               *
  32.  *   dbGetNextTable                                                  *
  33.  *   dbEndEnumTables                                                 *
  34.  *   dbRenderToFile                                                  *
  35.  *                                                                   *
  36.  *                                                                   *
  37.  * HISTORY:                                                          *
  38.  *                                                                   *
  39.  *  07-16-93 - Program coding started.                               *
  40.  *                                                                   *
  41.  *  Rick Fishman                                                     *
  42.  *  Code Blazers, Inc.                                               *
  43.  *  4113 Apricot                                                     *
  44.  *  Irvine, CA. 92720                                                *
  45.  *  CIS ID: 72251,750                                                *
  46.  *                                                                   *
  47.  *********************************************************************/
  48.  
  49. #pragma strings(readonly)   // used for debug version of memory mgmt routines
  50.  
  51. /*********************************************************************/
  52. /*------- Include relevant sections of the OS/2 header files --------*/
  53. /*********************************************************************/
  54.  
  55. #define  INCL_DOSERRORS
  56. #define  INCL_DOSFILEMGR
  57. #define  INCL_WINSTDCNR
  58.  
  59. /**********************************************************************/
  60. /*----------------------------- INCLUDES -----------------------------*/
  61. /**********************************************************************/
  62.  
  63. #include <os2.h>
  64. #include <stdio.h>
  65. #include <stdlib.h>
  66. #include <string.h>
  67. #include "drgrendr.h"
  68.  
  69. /*********************************************************************/
  70. /*------------------- APPLICATION DEFINITIONS -----------------------*/
  71. /*********************************************************************/
  72.  
  73. #define DATABASE_FILESPEC      "dbase_?.db"   // File spec for database files
  74. #define TABLEKEY_LITERAL       "TABLEKEY=>"   // On first line of each table
  75. #define DB_END_LITERAL         "end_of_database"  // Marks end of database file
  76.  
  77. /**********************************************************************/
  78. /*---------------------------- STRUCTURES ----------------------------*/
  79. /**********************************************************************/
  80.  
  81.  
  82. /**********************************************************************/
  83. /*----------------------- FUNCTION PROTOTYPES ------------------------*/
  84. /**********************************************************************/
  85.  
  86.  
  87. /**********************************************************************/
  88. /*------------------------ GLOBAL VARIABLES --------------------------*/
  89. /**********************************************************************/
  90.  
  91.  
  92. /**********************************************************************/
  93. /*------------------------ dbBeginEnumTables -------------------------*/
  94. /*                                                                    */
  95. /*  START AN ENUMERATON OF THE DATABASE TABLE NAMES.                  */
  96. /*                                                                    */
  97. /*  PARMS: nothing                                                    */
  98. /*                                                                    */
  99. /*  NOTES: We open the first 'database' file that we find in the      */
  100. /*         current directory and fill in information into our         */
  101. /*         ENUMSTRUCT structure. We will pass a pointer to this       */
  102. /*         structure back to the caller. This pointer will be used    */
  103. /*         as an 'enum handle' for further calls to the enumeration   */
  104. /*         functions.                                                 */
  105. /*                                                                    */
  106. /*  RETURNS: HENUMTABLES handle for accessing the enumeration         */
  107. /*                                                                    */
  108. /*--------------------------------------------------------------------*/
  109. /**********************************************************************/
  110. HENUMTABLES dbBeginEnumTables()
  111. {
  112.     HENUMTABLES henum = (HENUMTABLES) malloc( sizeof( ENUMSTRUCT ) );
  113.  
  114.     if( henum )
  115.     {
  116.         FILEFINDBUF3 ffb;
  117.         APIRET       rc;
  118.         ULONG        cFiles = 1;
  119.  
  120.         (void) memset( henum, 0, sizeof henum );
  121.  
  122.         henum->hdir = HDIR_SYSTEM;
  123.  
  124.         rc = DosFindFirst( DATABASE_FILESPEC, &henum->hdir, FILE_NORMAL,
  125.                            &ffb, sizeof ffb, &cFiles, FIL_STANDARD );
  126.  
  127.         if( rc )
  128.         {
  129.             free( henum );
  130.             henum = NULL;
  131.         }
  132.         else
  133.         {
  134.             henum->stream = fopen( ffb.achName, "r" );
  135.             if( henum->stream )
  136.             {
  137.                 PCH pchDot = strchr( ffb.achName, '.' );
  138.  
  139.                 if( pchDot )
  140.                     *pchDot = 0;
  141.  
  142.                 strcpy( henum->szFileName, ffb.achName );
  143.             }
  144.             else
  145.             {
  146.                 (void) DosFindClose( henum->hdir );
  147.                 free( henum );
  148.                 henum = NULL;
  149.             }
  150.         }
  151.     }
  152.     else
  153.         Msg( "Out of memory in dbBeginEnumTables!" );
  154.  
  155.     return henum;
  156. }
  157.  
  158. /**********************************************************************/
  159. /*------------------------- dbGetNextTable ---------------------------*/
  160. /*                                                                    */
  161. /*  GET THE NEXT TABLE NAME IN THE ENUMERATION.                       */
  162. /*                                                                    */
  163. /*  PARMS: HENUMTABLES handle of the enumeration,                     */
  164. /*                                                                    */
  165. /*  NOTES: Find the next 'table' in the enumerated databases. The     */
  166. /*         beginning of a table is marked by a line in the file that  */
  167. /*         has a table-key statement.                                 */
  168. /*                                                                    */
  169. /*  RETURNS: TRUE if table name available, FALSE if not. FALSE is     */
  170. /*           returned at end-of-database.                             */
  171. /*                                                                    */
  172. /*--------------------------------------------------------------------*/
  173. /**********************************************************************/
  174. BOOL dbGetNextTable( HENUMTABLES henum, PSZ pszTableName, INT cbTableName )
  175. {
  176.     BOOL fSuccess = FALSE;
  177.  
  178.     (void) memset( pszTableName, 0, cbTableName );
  179.  
  180.     if( henum )
  181.     {
  182.         while( !feof( henum->stream ) && !fSuccess )
  183.         {
  184.             // It is not valid to hit end-of-file since we have a file
  185.             // delimeter that we look for. If we hit end-of-file before hitting
  186.             // our delimiter then the database file got hosed somehow.
  187.  
  188.             if( !fgets( pszTableName, cbTableName, henum->stream ) )
  189.             {
  190.                 if( feof( henum->stream ) )
  191.                     Msg( "No end_of_database statement in database file!\n" );
  192.                 else
  193.                     Msg( "fgets got a bad return code in dbGetNextTable!\n" );
  194.  
  195.                 break;
  196.             }
  197.  
  198.             if( strstr( pszTableName, TABLEKEY_LITERAL ) )
  199.             {
  200.                 PSZ pszTableFound = pszTableName + strlen( TABLEKEY_LITERAL );
  201.  
  202.                 // If we hit end-of-database, find the next database if there
  203.                 // is one.
  204.  
  205.                 if( strstr( pszTableFound, DB_END_LITERAL ) )
  206.                 {
  207.                     FILEFINDBUF3 ffb;
  208.                     ULONG        cFiles = 1;
  209.                     APIRET       rc;
  210.  
  211.                     rc = DosFindNext( henum->hdir, &ffb, sizeof ffb, &cFiles );
  212.                     if( rc )
  213.                     {
  214.                         if( rc != ERROR_NO_MORE_FILES )
  215.                             Msg( "DosFindNext RC(%u)", rc );
  216.                         break;
  217.                     }
  218.                     else
  219.                     {
  220.                         // We found the next database so close the current one
  221.                         // and open the new one.
  222.  
  223.                         fclose( henum->stream );
  224.                         henum->stream = fopen( ffb.achName, "r" );
  225.                         if( henum->stream )
  226.                         {
  227.                             PCH pchDot = strchr( ffb.achName, '.' );
  228.  
  229.                             if( pchDot )
  230.                                 *pchDot = 0;
  231.  
  232.                             strcpy( henum->szFileName, ffb.achName );
  233.                         }
  234.                         else
  235.                             break;
  236.                     }
  237.                 }
  238.                 else
  239.                 {
  240.                     char szFullName[ CCHMAXPATH ];
  241.  
  242.                     // We found a record in the file that indicates the start
  243.                     // of a new table. Piece together the full 'dbase:table'
  244.                     // string and return to the caller.
  245.  
  246.                     strcpy( szFullName, henum->szFileName );
  247.                     strcat( szFullName, ":" );
  248.                     strcat( szFullName, pszTableFound );
  249.                     strncpy( pszTableName, szFullName, cbTableName );
  250.                     if( pszTableName[ strlen( pszTableName ) - 1 ] == '\n' )
  251.                         pszTableName[ strlen( pszTableName ) - 1 ] = 0;
  252.  
  253.                     fSuccess = TRUE;
  254.                 }
  255.             }
  256.         }
  257.     }
  258.  
  259.     return fSuccess;
  260. }
  261.  
  262. /**********************************************************************/
  263. /*------------------------- dbEndEnumTables --------------------------*/
  264. /*                                                                    */
  265. /*  END AN ENUMERATON OF THE DATABASE TABLE NAMES.                    */
  266. /*                                                                    */
  267. /*  PARMS: HENUMTABLES handle from the enumeration                    */
  268. /*                                                                    */
  269. /*  NOTES:                                                            */
  270. /*                                                                    */
  271. /*  RETURNS: nothing                                                  */
  272. /*                                                                    */
  273. /*--------------------------------------------------------------------*/
  274. /**********************************************************************/
  275. void dbEndEnumTables( HENUMTABLES henum )
  276. {
  277.     if( henum )
  278.     {
  279.         if( henum->stream )
  280.             fclose( henum->stream );
  281.  
  282.         if( henum->hdir )
  283.             DosFindClose( henum->hdir );
  284.  
  285.         free( henum );
  286.     }
  287. }
  288.  
  289. /**********************************************************************/
  290. /*-------------------------- dbRenderToFile --------------------------*/
  291. /*                                                                    */
  292. /*  COPY THE ROWS IN A TABLE TO A FILE.                               */
  293. /*                                                                    */
  294. /*  PARMS: table name in 'dbase:table' format,                        */
  295. /*         file name to copy rows to                                  */
  296. /*                                                                    */
  297. /*  NOTES: Given a 'dbase:table' key, open the 'dbase' file and       */
  298. /*         search for the 'table' key. When we find it, read all the  */
  299. /*         rows until we get to the next table and place the rows that*/
  300. /*         we read into the output file whose name was passed to us.  */
  301. /*                                                                    */
  302. /*  RETURNS: TRUE if successful, FALSE if not                         */
  303. /*                                                                    */
  304. /*--------------------------------------------------------------------*/
  305. /**********************************************************************/
  306. BOOL dbRenderToFile( PSZ pszTableName, PSZ pszFileName )
  307. {
  308.     BOOL fTrue = TRUE;
  309.     BOOL fSuccess = TRUE;
  310.     FILE *fhDbase = NULL, *fhOutfile = NULL;
  311.     char szNames[ CCHMAXPATH ];
  312.     char szLine[ CCHMAXPATH ];
  313.     PSZ  pszTable, pszDbase = szNames;
  314.  
  315.     // Here's what we're doing here. Let's say the pszTableName passed to us is
  316.     // dbase_1:table_1. We are converting that to this:
  317.     // dbase_1.db  table_1. The 'dbase_1.db' file will be opened and searched
  318.     // for a table key of 'table_1'.
  319.  
  320.     strcpy( szNames, pszTableName );
  321.     pszTable = strchr( pszDbase, ':' );
  322.     *(pszTable++) = 0;
  323.     memmove( pszTable + 5, pszTable, strlen( pszTable ) + 1 );
  324.     pszTable += 5;
  325.     strcat( pszDbase, ".db" );
  326.  
  327.     fhDbase = fopen( pszDbase, "r" );
  328.     if( fhDbase )
  329.     {
  330.         while( !feof( fhDbase ) )
  331.         {
  332.             if( !fgets( szLine, sizeof szLine, fhDbase ) )
  333.             {
  334.                 if( feof( fhDbase ) )
  335.                     Msg( "No end_of_database statement in database file!\n" );
  336.                 else
  337.                     Msg( "fgets got a bad return code in dbRenderToFile!\n" );
  338.  
  339.                 break;
  340.             }
  341.  
  342.             if( strstr( szLine, TABLEKEY_LITERAL ) )
  343.             {
  344.                 if( strstr( szLine, DB_END_LITERAL ) )
  345.                 {
  346.                     Msg( "Table %s not found in %s!", pszTable, pszDbase );
  347.                     break;
  348.                 }
  349.                 else if( strstr( szLine, pszTable ) )
  350.                 {
  351.                     fhOutfile = fopen( pszFileName, "w" );
  352.                     if( !fhOutfile )
  353.                     {
  354.                         Msg( "Could not open output file %s", pszFileName );
  355.                         break;
  356.                     }
  357.  
  358.                     while( fTrue )
  359.                     {
  360.                         if( !fgets( szLine, sizeof szLine, fhDbase ) )
  361.                         {
  362.                             if( feof( fhDbase ) )
  363.                                 Msg( "No end_of_database statement in database "
  364.                                      "file!\n" );
  365.                             else
  366.                                 Msg( "fgets got a bad return code in"
  367.                                      "dbRenderToFile!\n" );
  368.                             break;
  369.                         }
  370.  
  371.                         if( strstr( szLine, TABLEKEY_LITERAL ) )
  372.                             break;
  373.                         else
  374.                             if( fputs( szLine, fhOutfile ) == EOF )
  375.                             {
  376.                                 Msg( "Out of disk space!" );
  377.                                 break;
  378.                             }
  379.                     }
  380.  
  381.                     fclose( fhOutfile );
  382.                     break;
  383.                 }
  384.             }
  385.         }
  386.  
  387.         fclose( fhDbase );
  388.     }
  389.  
  390.     return fSuccess;
  391. }
  392.  
  393. /*************************************************************************
  394.  *                     E N D     O F     S O U R C E                     *
  395.  *************************************************************************/
  396.