#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:  dbget_f.c

              SYSTEM FUNCTIONS FOR RETRIEVING SCALED DATA FROM AN
              EXISTING DATABASE

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

   FUNCTION DBGET_F:

      It retrieves user-defined data (types 0-99) from the database and
      automatically converts to floating-point values.

   PARAMETERS:

      type = pointer to user-defined data type

      data = floating-point array to store retrieved, rescaled values

                / on entry, contains the dimension of the data array
      user_nv =
                \ on exit, contains the number of values actually stored in data

      ierr = pointer to database error code

   RETURNS:  void

*/
#if PROTOTYPE_ALLOWED
void DBGET_F(int *type, FLOAT data[], unsigned int *user_nv, int *ierr)
#else
void DBGET_F(type, data, user_nv, ierr)
int *type, *ierr;
FLOAT data[];
unsigned int *user_nv;
#endif
{
   unsigned int nb;
   long ofs;

   if ( (*ierr = dbget_flags()) != 0) {*user_nv = 0; return;}
   if (!(*type >= 0 && *type < (int)db->block_hdr.data_list_nentries)) {*ierr = INVALID_TYPE_REQUEST; *user_nv = 0; return;}
   if (!db->profile_is_open) {*ierr = NO_PROFILE_IS_OPEN; *user_nv = 0; return;}
   if (db->data_list[*type].access_type == UNUSED) {*ierr = INVALID_TYPE_REQUEST; *user_nv = 0; return;}
   if (*user_nv == 0)   /* must be query on no. of values available */
   {
      get_access_param(type, &nb, &ofs);
      *user_nv = nb / VALUE_SIZE[db->data_list[*type].value_type];
      return;
   }
   if (db->data_list[*type].value_type >= BYTE_VALUE_CODE &&
      db->data_list[*type].value_type <= DOUBLE_VALUE_CODE)
   {
      if ( (*ierr = getf_profile_data(type, data, user_nv)) != 0)
      {
         *user_nv = 0;
         report_db_error("DBGET_F");
      }
      return;
   }
   /* else use DBGET for types 100-300 & complex/struct data types */
   *user_nv = 0;
   *ierr = INVALID_TYPE_REQUEST;
}

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

     FUNCTION: getf_profile_data

        It extracts data from current profile and automatically unscales these
        and converts to floating point.  It returns a floating-point array of
        unscaled, converted values.

     PARAMETERS:

        type = pointer to data type

        data = buffer array

                  / on entrance, contains no. of values that buffer array can hold
        user_nv =
                  \ on exit, contains no. of values placed in buffer array

     RETURNS: 0 or DATABASE ERROR

*/
#if PROTOTYPE_ALLOWED
int getf_profile_data(int *type, FLOAT data[], unsigned int *user_nv)
#else
int getf_profile_data(type, data, user_nv)
int *type;
FLOAT data[];
unsigned int *user_nv;
#endif
{
   char *temp_data;
   unsigned int nb, db_nv;
   long ofs;

   get_access_param(type, &nb, &ofs);
   db_nv = nb / VALUE_SIZE[db->data_list[*type].value_type];
   *user_nv = min_val(*user_nv, db_nv);
   nb = *user_nv * VALUE_SIZE[db->data_list[*type].value_type];
   if (nb > 0)
   {
      if ((temp_data = malloc(nb)) == NULL)
      {
         db->error_code = INSUFFICIENT_MEMORY;
         goto error_found;
      }
      if ((db->error_code = read_data(db->fpblkdata, temp_data, ofs, nb)) != 0)
      {
         free(temp_data);
         goto error_found;
      }
      if (db->block_host != HOST_ENVIRONMENT)
      {
         if (convert_select(temp_data, temp_data,
                            db->block_host, HOST_ENVIRONMENT,
                            *user_nv, db->data_list[*type].value_type,
                            db->data_list[*type].name,
                            db->struct_def) == BADUINT)
         {
            db->error_code = CONVERT_ERROR;
            db->error_data = *type;
            goto error_found;
         }
      }
      db->error_code = (*unscale[db->data_list[*type].value_type])
         (data, temp_data, &(db->data_list[*type].scale),
         &(db->data_list[*type].offset), user_nv);
      free(temp_data);
   }
   return(db->error_code);

   error_found:
      db->error_data = PROFILE_DATA;
      report_db_error("getf_profile_data");
      return(db->error_code);
}

