#include "dbinc.h"
/*****************************************************************************
*                                                                            *
*      COMMON OCEANOGRAPHIC DATA ACCESS SYSTEM (CODAS)                       *
*                                                                            *
*      WRITTEN BY:  RAMON CABRERA, ERIC FIRING, and JULIE RANADA             *
*                   JOINT INSTITUTE FOR MARINE AND ATMOSPHERIC RESEARCH      *
*                   1000 POPE ROAD  MSB 312                                  *
*                   HONOLULU, HI 96822                                       *
*                                                                            *
*      VERSION:     3.10                                                     *
*                                                                            *
*      DATE:        APRIL 1989, AUGUST 1995                                  *
*                                                                            *
*****************************************************************************/
/*

       FILE:  dbgetput.c

              SYSTEM FUNCTIONS USED BY DBGET, DBGET_F, DBPUT & DBPUT_F
*/
/*-----------------------------------------------------------------------------

   FUNCTION:  get_access_param

      This function returns the number of bytes of the specified
      data type that are available for retrieval from a profile, and
      the offset to these data in the file.

   PARAMETERS:

      type = pointer to data type

      nb = pointer to number of bytes that can be retrieved from a profile

      ofs = pointer to offset to position to start retrieving from

   RETURNS:  VOID

*/
#if PROTOTYPE_ALLOWED
void get_access_param(int *type, unsigned int *nb, long *ofs)
#else
void get_access_param(type, nb, ofs)
int *type;
unsigned int *nb;
long *ofs;
#endif
{
   int ind;        /* index into data directory */

   if (db->data_list[*type].access_type == BLOCK_VAR_ACCESS_CODE)
   {
      *ofs = db->data_list[*type].access_0;
      *nb = min_val(db->data_list[*type].access_1, MAXUINT);  /*jr*/
   }
   else if (db->data_list[*type].access_type == PROFILE_VAR_ACCESS_CODE)
   {
      ind = db->data_list[*type].access_0;
      *nb = min_val(db->data_dir[ind].nbytes, MAXUINT);      /*jr*/
      *ofs = db->profile_dir_entry_ptr->ofs + db->data_dir[ind].ofs;
   }
}

/*-----------------------------------------------------------------------------

   FUNCTION:  dbget_flags

      It checks the necessary database status flags prior to retrieving
      data using DBGET or DBGET_F, or rewriting data using DBPUT or DBPUT_F.

   RETURNS:  0 if okay
             error code otherwise

*/
#if PROTOTYPE_ALLOWED
int dbget_flags(void)
#else
int dbget_flags()
#endif
{
   if ((!(db)) || first_database_call)
      return(DB_IS_NOT_OPEN);
   if (db->create_mode)
      return(OPEN_FOR_CREATE);
   if (!(db->block_is_open))
      return(NO_BLOCK_IS_OPEN);
   return(0);
}

/*-----------------------------------------------------------------------------

    FUNCTION:  load_block_strdef()

       It loads the block file structure definitions into memory.

    RETURNS:  0 if okay
              db->error_code otherwise

*/
#if PROTOTYPE_ALLOWED
int load_block_strdef(void)
#else
int load_block_strdef()
#endif
{
   unsigned int nb = 0, converted_nb, nentries;
   long file_ofs;
   char *dest_ptr;
   STRUCT_DEF_HDR_TYPE **link_address;
   int nelem, i;

   nentries = db->block_hdr.struct_def_nentries;
   if (nentries == 0)
      nentries++;
   else
   {
      nb = nentries * STRUCT_DEF_ENTRY_SIZE;
      file_ofs = db->block_hdr.data_list_ofs +
         db->block_hdr.data_list_nentries * DATA_LIST_ENTRY_SIZE;
   }
   if ((db->block_strdef = (STRUCT_DEF_HDR_TYPE *)
      malloc(nentries * STRUCT_DEF_ENTRY_SIZE)) == NULL)
   {
      db->error_code = INSUFFICIENT_MEMORY;
      db->error_data = STRUCTURE_DEF;
      goto error_found;
   }
   if (nb)
   {
      if ((db->error_code = read_data(db->fpblkdata, (char *) db->block_strdef,
         file_ofs, nb)) != 0)
      {
         db->error_data = STRUCTURE_DEF;
         free(db->block_strdef);
         db->block_strdef_loaded = 0;
         goto error_found;
      }
      if (db->block_host != HOST_ENVIRONMENT)
      {
         dest_ptr = (char *) db->block_strdef;
         do
         {
            if ( (converted_nb = convert_struct(dest_ptr,
                                                dest_ptr,
                                                db->block_host,
                                                HOST_ENVIRONMENT,
                                                "struct_def_hdr",
                                                &(dbint_sd[0].struct_def_hdr)))
                                                == BADUINT)
            {
               db->error_code = CONVERT_ERROR;
               db->error_data = STRUCTURE_DEF;
               goto error_found;
            }
            nelem = ((STRUCT_DEF_HDR_TYPE *)(dest_ptr))->nelem;
            dest_ptr += converted_nb;
            nb -= converted_nb;
            for (i = 0; i < nelem; i++)
            {
               if ((converted_nb = convert_struct(dest_ptr,
                                                  dest_ptr,
                                                  db->block_host,
                                                  HOST_ENVIRONMENT,
                                                  "struct_def_elem",
                                                  &(dbint_sd[0].struct_def_elem)))
                                                  == BADUINT)
               {
                  db->error_code = CONVERT_ERROR;
                  db->error_data = STRUCTURE_DEF;
                  goto error_found;
               }
               dest_ptr += converted_nb;
               nb -= converted_nb;
            }
         } while (nb > 0);
      }
   }
   if (db->prev_strdef == NULL)           /* block_strdef heads strdefs */
      db->struct_def = db->block_strdef;  /* must set main strdef to block */
   else                                   /* connect block strdef to previous */
   {
      link_address = (STRUCT_DEF_HDR_TYPE **) &( (db->prev_strdef)->LINK_PTR );
      *link_address = db->block_strdef;
   }
   link_address = (STRUCT_DEF_HDR_TYPE **)
      &( (db->block_strdef + (nentries - 1))->LINK_PTR );
   *link_address = db->next_strdef;
                               /* connect block_strdef trailer to next strdef */
   db->block_strdef_loaded = 1;
   db->formats_matched = 0;
   return(0);

   error_found:
      report_db_error("load_block_strdef");
      return(db->error_code);
}

