NcValues* NcAtt::values( void ) const
{
    NcValues* valp = get_space();
    int status;
    switch (type()) {
    case ncFloat:
	status = NcError::set_err(
				  nc_get_att_float(the_file->id(), the_variable->id(), the_name,
				   (float *)valp->base())
				  );
	break;
    case ncDouble:
	status = NcError::set_err(
				  nc_get_att_double(the_file->id(), the_variable->id(), the_name,
				   (double *)valp->base())
				  );
	break;
    case ncInt64:
	status = NcError::set_err(
				  nc_get_att_longlong(the_file->id(), the_variable->id(), the_name,
				(long long *)valp->base())
				  );
	break;
    case ncUInt64:
	status = NcError::set_err(
				  nc_get_att_ulonglong(the_file->id(), the_variable->id(), the_name,
				(unsigned long long *)valp->base())
				  );
	break;
    case ncInt:
	status = NcError::set_err(
				  nc_get_att_int(the_file->id(), the_variable->id(), the_name,
				(int *)valp->base())
				  );
	break;
    case ncShort:
	status = NcError::set_err(
				  nc_get_att_short(the_file->id(), the_variable->id(), the_name,
				  (short *)valp->base())
				  );
	break;
    case ncByte:
	status = NcError::set_err(
				  nc_get_att_schar(the_file->id(), the_variable->id(), the_name,
				  (signed char *)valp->base())
				  );
	break;
    case ncChar:
	status = NcError::set_err(
				  nc_get_att_text(the_file->id(), the_variable->id(), the_name,
				  (char *)valp->base())
				  );
	break;
    case ncNoType:
    default:
	return 0;
    }
    if (status != NC_NOERR) {
	delete valp;
	return 0;
    }
    return valp;
}
Exemplo n.º 2
0
int
main(int argc, char **argv)
{
    (void) signal(SIGFPE, SIG_IGN);

   printf("\n*** Testing netcdf-4 attribute functions.\n");
   printf("*** testing really simple global atts...");
#define NUM_SIMPLE_ATTS 9
   {
      int ncid;
      char name[NUM_SIMPLE_ATTS][ATT_MAX_NAME + 1] = {"Gc", "Gb", "Gs", "Gi", "Gf", 
						      "Gd", "G7", "G8", "G9"};
      char name_in[NC_MAX_NAME];
      int j;

      /* Create a file with some global atts. */
      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLOBBER, &ncid)) ERR;
      for (j = 0; j < NUM_SIMPLE_ATTS; j++)
	 if (nc_put_att_int(ncid, NC_GLOBAL, name[j], NC_INT, 0, NULL)) ERR;      
      if (nc_close(ncid)) ERR;
      
      /* Reopen the file and check the order. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      for (j = 0; j < NUM_SIMPLE_ATTS; j++)
      {
	 if (nc_inq_attname(ncid, NC_GLOBAL, j, name_in)) ERR;
	 if (strcmp(name_in, name[j])) ERR;
      }

      /* Close up shop. */
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** testing simple global atts...");
   {      
      int ncid;
      nc_type att_type;
      size_t att_len;
      int i;

      char *speech_in;
      signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
      unsigned char uchar_in[ATT_LEN], uchar_out[ATT_LEN] = {0, 128, NC_MAX_CHAR};
      short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
      int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
      float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
      double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};
      unsigned short ushort_in[ATT_LEN], ushort_out[ATT_LEN] = {0, 128, NC_MAX_USHORT};
      unsigned int uint_in[ATT_LEN], uint_out[ATT_LEN] = {0, 128, NC_MAX_UINT};
      unsigned long long uint64_in[ATT_LEN], uint64_out[ATT_LEN] = {0, 128, 18446744073709551612ULL};
      long long int64_in[ATT_LEN], int64_out[ATT_LEN] = {NC_MIN_INT64, 128, NC_MAX_INT64};


      /* This won't work, because classic files can't create these types. */
      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_put_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, NC_USHORT, ATT_LEN, 
			    ushort_out) != NC_ESTRICTNC3) ERR;      
      if (nc_put_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, NC_UINT, ATT_LEN, 
			  uint_out) != NC_ESTRICTNC3) ERR;      
      if (nc_put_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, NC_INT64, ATT_LEN, 
			      int64_out) != NC_ESTRICTNC3) ERR;      
      if (nc_put_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, NC_UINT64, ATT_LEN, 
			       uint64_out) != NC_ESTRICTNC3) ERR;      
      if (nc_close(ncid)) ERR;

      /* Create a file with a global attribute of each type. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR;      
      if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UBYTE, ATT_LEN, uchar_out)) ERR;
      if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, ATT_LEN, short_out)) ERR;      
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN, int_out)) ERR;      
      if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, ATT_LEN, float_out)) ERR;      
      if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, ATT_LEN, double_out)) ERR;      
      if (nc_put_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, NC_USHORT, ATT_LEN, ushort_out)) ERR;      
      if (nc_put_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, NC_UINT, ATT_LEN, uint_out)) ERR;      
      if (nc_put_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, NC_INT64, ATT_LEN, int64_out)) ERR;      
      if (nc_put_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, NC_UINT64, ATT_LEN, uint64_out)) ERR;      
      if (nc_close(ncid)) ERR;

      /* Open the file and check attributes. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      /* Check text. */
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &att_type, &att_len))
	 ERR;
      if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
      if (!(speech_in = malloc(att_len + 1))) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in)) ERR;      
      if (strcmp(speech, speech_in)) ERR;
      free(speech_in);
      /* Check numeric values. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != schar_out[i]) ERR;
      if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, uchar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (uchar_in[i] != uchar_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != short_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != int_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != float_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != double_out[i]) ERR;
      if (nc_get_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, ushort_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (ushort_in[i] != ushort_out[i]) ERR;
      if (nc_get_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, uint_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (uint_in[i] != uint_out[i]) ERR;
      if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, int64_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int64_in[i] != int64_out[i]) ERR;
      if (nc_get_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, uint64_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (uint64_in[i] != uint64_out[i]) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** testing attribute data type conversions...");

   {
      int ncid;
      int i;

      signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
      short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
      int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
      float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
      double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};
      unsigned short ushort_in[ATT_LEN];
      unsigned int uint_in[ATT_LEN];
      unsigned long long uint64_in[ATT_LEN];
      long long int64_in[ATT_LEN];

      /* Reopen the file and try different type conversions. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;

      /* No text conversions are allowed, and people who try them shold
       * be locked up, away from decent folk! */
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_TEXT_NAME, short_in) != NC_ECHAR) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_TEXT_NAME, int_in) != NC_ECHAR) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_TEXT_NAME, float_in) != NC_ECHAR) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_TEXT_NAME, double_in) != NC_ECHAR) ERR;
/*   if (nc_get_att_ubyte(ncid, NC_GLOBAL, ATT_TEXT_NAME, uchar_in) != NC_ECHAR) ERR;*/
      if (nc_get_att_ushort(ncid, NC_GLOBAL, ATT_TEXT_NAME, ushort_in) != NC_ECHAR) ERR;
      if (nc_get_att_uint(ncid, NC_GLOBAL, ATT_TEXT_NAME, uint_in) != NC_ECHAR) ERR;
      if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_TEXT_NAME, int64_in) != NC_ECHAR) ERR;
      if (nc_get_att_ulonglong(ncid, NC_GLOBAL, ATT_TEXT_NAME, uint64_in) != NC_ECHAR) ERR;

      /* Read all atts (except text) as double. */
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_SCHAR_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != schar_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_SHORT_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != short_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_INT_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != int_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_FLOAT_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != float_out[i]) ERR;
      /* Read all atts (except text) as float. */
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_SCHAR_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != schar_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_SHORT_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != short_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_INT_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != (float)int_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != (float)double_out[i]) ERR;
      /* Read all atts (except text) as int. */
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_SCHAR_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != schar_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_SHORT_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != short_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_FLOAT_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != (int)float_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != (int)double_out[i]) ERR;
      /* Read all atts (except text) as short. */
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SCHAR_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != schar_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_INT_NAME, short_in) != NC_ERANGE) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != (short)int_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_FLOAT_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != (short)float_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != (short)double_out[i]) ERR;
      /* Read all atts (except text) as schar. Some range errors will
       * result converting to schar. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in) != NC_ERANGE) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != (signed char)short_out[i]) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in) != NC_ERANGE) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != (signed char)int_out[i]) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != (signed char)float_out[i]) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != (signed char)double_out[i]) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** testing simple variable atts...");
   {
      int ncid, varid, dimids[2];
      nc_type att_type;
      size_t att_len;
      int i, v;

      char *speech_in;
      signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
      short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
      int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
      float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
      double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};

      /* Create a file with two vars, attaching to each an attribute of
       * each type. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
      if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1])) ERR;
      if (nc_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid)) ERR;
      if (nc_put_att_text(ncid, varid, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_put_att_schar(ncid, varid, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR;      
      if (nc_put_att_short(ncid, varid, ATT_SHORT_NAME, NC_SHORT, 3, short_out)) ERR;      
      if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;      
      if (nc_put_att_float(ncid, varid, ATT_FLOAT_NAME, NC_FLOAT, 3, float_out)) ERR;      
      if (nc_put_att_double(ncid, varid, ATT_DOUBLE_NAME, NC_DOUBLE, 3, double_out)) ERR;      
      if (nc_def_var(ncid, VAR2_NAME, NC_UINT, 2, dimids, &varid)) ERR;
      if (nc_put_att_text(ncid, varid, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_put_att_schar(ncid, varid, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR; 
      if (nc_put_att_short(ncid, varid, ATT_SHORT_NAME, NC_SHORT, 3, short_out)) ERR;           
      if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;      
      if (nc_put_att_float(ncid, varid, ATT_FLOAT_NAME, NC_FLOAT, 3, float_out)) ERR;      
      if (nc_put_att_double(ncid, varid, ATT_DOUBLE_NAME, NC_DOUBLE, 3, double_out)) ERR;      
      if (nc_close(ncid)) ERR;

      /* Open the file and check attributes. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      for (v=0; v<2; v++)
      {
	 if (nc_inq_att(ncid, v, ATT_TEXT_NAME, &att_type, &att_len)) ERR;
	 if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
	 if (!(speech_in = malloc(att_len + 1))) ERR;
	 if (nc_get_att_text(ncid, v, ATT_TEXT_NAME, speech_in)) ERR;      
	 if (strcmp(speech, speech_in)) ERR;
	 free(speech_in);
	 if (nc_get_att_schar(ncid, v, ATT_SCHAR_NAME, schar_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (schar_in[i] != schar_out[i]) ERR;
	 if (nc_get_att_short(ncid, v, ATT_SHORT_NAME, short_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (short_in[i] != short_out[i]) ERR;
	 if (nc_get_att_int(ncid, v, ATT_INT_NAME, int_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (int_in[i] != int_out[i]) ERR;
	 if (nc_get_att_float(ncid, v, ATT_FLOAT_NAME, float_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (float_in[i] != float_out[i]) ERR;
	 if (nc_get_att_double(ncid, v, ATT_DOUBLE_NAME, double_in)) ERR;      
	 for (i = 0; i < ATT_LEN; i++)
	    if (double_in[i] != double_out[i]) ERR;
      }
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   printf("*** testing zero-length attributes...");
   {
      int ncid;

      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/

      /* Create a file with a global attribute of each type of zero length. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL)) ERR;
      if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL)) ERR;
/*   if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UCHAR, ATT_LEN, uchar_out)) ERR;*/
      if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL)) ERR;
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL)) ERR;
      if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL)) ERR;
      if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, 0, NULL)) ERR;
      if (nc_close(ncid)) ERR;
   }

   /* Make sure we can read all these zero-length atts. */
   {
      int ncid;
      signed char schar_in[ATT_LEN];
      short short_in[ATT_LEN];
      /*int int_in[ATT_LEN], int_out[ATT_LEN] = {NC_MIN_INT, 128, NC_MAX_INT};*/
      int int_in[ATT_LEN];
      float float_in[ATT_LEN];
      double double_in[ATT_LEN];
      size_t len;
      nc_type xtype;

      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, NULL)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_CHAR) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_SCHAR_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_BYTE) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_SHORT_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_SHORT) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_INT_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_INT) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_FLOAT_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_FLOAT) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, &xtype, &len)) ERR;
      if (len || xtype != NC_DOUBLE) ERR;
      /* Conversions no longer result in range errors, since there's no data. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in)) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** testing zero-length attributes and redef...(this test skipped for HDF5-1.8.0 beta1");
   {
      int ncid;
      signed char schar_in[ATT_LEN];
      short short_in[ATT_LEN];
      int int_in[ATT_LEN];
      float float_in[ATT_LEN];
      double double_in[ATT_LEN];


      /* Create a file with a global attribute of each type of zero length. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_enddef(ncid)) ERR;
      if (nc_redef(ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, 0, NULL)) ERR;
      if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, 0, NULL)) ERR;
/*   if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UCHAR, ATT_LEN, uchar_out)) ERR;*/
      if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, 0, NULL)) ERR;
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, 0, NULL)) ERR;
      if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, 0, NULL)) ERR;
      if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, 0, NULL)) ERR;
      if (nc_close(ncid)) ERR;

      /* Make sure we can read all these zero-length atts added during a
       * redef. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, NULL)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;
      /* Conversions no longer result in range errors, since there's no data. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_FLOAT_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_INT_NAME, schar_in)) ERR;
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SHORT_NAME, schar_in)) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;

   printf("*** testing attribute deletes and renames...");
   {
      int ncid, varid, dimids[2];
      nc_type att_type;
      size_t att_len;
      char *speech_in;
      char name_in[NC_MAX_NAME + 1];
      int attid_in, natts_in;
      int int_out[ATT_LEN] = {-100000, 128, 100000};

      /* Create a file with a global attribute. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, 
			  speech)) ERR;      
      if (nc_close(ncid)) ERR;
      
      /* Rename it. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq_attid(ncid, NC_GLOBAL, ATT_TEXT_NAME, &attid_in)) ERR;
      if (attid_in != 0) ERR;
      if (nc_inq_attname(ncid, NC_GLOBAL, attid_in, name_in)) ERR;
      if (strcmp(name_in, ATT_TEXT_NAME)) ERR;
      if (nc_rename_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, ATT_TEXT_NAME2)) ERR;      
      if (nc_inq_attname(ncid, NC_GLOBAL, attid_in, name_in)) ERR;
      if (strcmp(name_in, ATT_TEXT_NAME2)) ERR;
      if (nc_close(ncid)) ERR;

      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME2, &att_type, &att_len)) ERR;
      if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
      if (!(speech_in = malloc(att_len + 1))) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME2, speech_in)) ERR;      
      if (strcmp(speech, speech_in)) ERR;
      free(speech_in);
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in) != NC_ENOTATT) ERR;      
      if (nc_close(ncid)) ERR;

      /* Now delete the att. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_del_att(ncid, NC_GLOBAL, ATT_TEXT_NAME2)) ERR;
      if (nc_close(ncid)) ERR;

      /* Now create a file with a variable, which has an att. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
      if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1])) ERR;
      if (nc_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid)) ERR;
      if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;      
      if (nc_close(ncid)) ERR;
      
      /* Reopen the file and delete it. Make sure it's gone. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_del_att(ncid, 0, ATT_INT_NAME)) ERR;
      if (nc_close(ncid)) ERR;

      /* Reopen the file and readd the attribute. Enddef and redef,
       * and delete it, then check to make sure it's gone. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_put_att_int(ncid, varid, ATT_INT_NAME, NC_INT, 3, int_out)) ERR;      
      if (nc_enddef(ncid)) ERR;
      if (nc_redef(ncid)) ERR;
      if (nc_del_att(ncid, 0, ATT_INT_NAME)) ERR;
      if (nc_inq_varnatts(ncid, 0, &natts_in)) ERR;
      if (natts_in != 0) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** testing attribute create order...");

#define ATT0 "Maturin"
#define ATT1 "Aubery"
   {
      int ncid, varid, dimids[2];
      int attid_in;
      const int number = 42;

      /* Create a file with several global attributes. */
      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT0, NC_INT, 1, &number)) ERR;
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT1, NC_INT, 1, &number)) ERR;
      if (nc_close(ncid)) ERR;
      
      /* Open it and check the order. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq_attid(ncid, NC_GLOBAL, ATT0, &attid_in)) ERR;
      if (attid_in != 0) ERR;
      if (nc_inq_attid(ncid, NC_GLOBAL, ATT1, &attid_in)) ERR;
      if (attid_in != 1) ERR;
      if (nc_close(ncid)) ERR;

      /* Now create a file with a variable, which has two atts. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_def_dim(ncid, DIM1_NAME, DIM1_LEN, &dimids[0])) ERR;
      if (nc_def_dim(ncid, DIM2_NAME, DIM2_LEN, &dimids[1])) ERR;
      if (nc_def_var(ncid, VAR1_NAME, NC_INT, 2, dimids, &varid)) ERR;
      if (nc_put_att_int(ncid, varid, ATT0, NC_INT, 1, &number)) ERR;
      if (nc_put_att_int(ncid, varid, ATT1, NC_INT, 1, &number)) ERR;
      if (nc_close(ncid)) ERR;
      
      /* Reopen the file and check the order of the attributes on the var. */
      if (nc_open(FILE_NAME, NC_WRITE, &ncid)) ERR;
      if (nc_inq_attid(ncid, 0, ATT0, &attid_in)) ERR;
      if (attid_in != 0) ERR;
      if (nc_inq_attid(ncid, 0, ATT1, &attid_in)) ERR;
      if (attid_in != 1) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** testing attribute ordering some more...");

#define VAR_NAME "i"
#define A1_NAME "i"      
#define A2_NAME "f"      
#define A3_NAME "d"      
#define A1_LEN 3
#define A2_LEN 4
#define A3_LEN 5
   {
      int ncid;
      int varid, natts, nvars;
      double dvalue[] = {999.99, 999.99, 999.99, 999.99, 999.99};
      int varids[1];
      char name_in[NC_MAX_NAME + 1];

      /* Create a file with one var, and attach three atts to it. */
      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL, &ncid)) ERR;
      if (nc_def_var(ncid, VAR_NAME, NC_INT, 0, NULL, &varid)) ERR;
      if (nc_put_att_double(ncid, varid, A1_NAME, NC_INT, A1_LEN, dvalue)) ERR;      
      if (nc_put_att_double(ncid, varid, A2_NAME, NC_INT, A2_LEN, dvalue)) ERR;      
      if (nc_put_att_double(ncid, varid, A3_NAME, NC_INT, A3_LEN, dvalue)) ERR;      
      if (nc_close(ncid)) ERR;
      
      /* Reopen the file and check. */
      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      if (nc_inq_varids(ncid, &nvars, varids)) ERR;
      if (nvars != 1 || varids[0] != 0) ERR;
      if (nc_inq_varnatts(ncid, 0, &natts)) ERR;
      if (natts != 3) ERR;
      if (nc_inq_attname(ncid, 0, 0, name_in)) ERR;
      if (strcmp(name_in, A1_NAME)) ERR;
      if (nc_inq_attname(ncid, 0, 1, name_in)) ERR;
      if (strcmp(name_in, A2_NAME)) ERR;
      if (nc_inq_attname(ncid, 0, 2, name_in)) ERR;
      if (strcmp(name_in, A3_NAME)) ERR;

      /* Close up shop. */
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** testing attribute ordering even more...");

   /* Test the ordering of atts for each cmode. */
   if (tst_att_ordering(NC_CLOBBER)) ERR;
   if (tst_att_ordering(NC_CLOBBER|NC_64BIT_OFFSET)) ERR;
   if (tst_att_ordering(NC_CLOBBER|NC_NETCDF4)) ERR;
   if (tst_att_ordering(NC_CLOBBER|NC_NETCDF4|NC_CLASSIC_MODEL)) ERR;

   SUMMARIZE_ERR;
   printf("*** testing attributes and enddef/redef...");

#define ATT_1 "a"
#define ATT_2 "b"
#define ATT_3 "c"
   {
      int ncid, att = 1;

      if (nc_create(FILE_NAME, NC_NETCDF4|NC_CLASSIC_MODEL|NC_CLOBBER, &ncid)) ERR;
      if (nc_enddef(ncid)) ERR;
      if (nc_redef(ncid)) ERR;
      if (nc_put_att(ncid, NC_GLOBAL, ATT_1, NC_INT, 1, &att)) ERR;
      if (nc_put_att(ncid, NC_GLOBAL, ATT_2, NC_INT, 1, &att)) ERR;
      if (nc_put_att(ncid, NC_GLOBAL, ATT_3, NC_INT, 1, &att)) ERR;

      if (nc_close(ncid)) ERR;

      if (nc_open(FILE_NAME, 0, &ncid)) ERR;
      if (nc_close(ncid)) ERR;
   }

   SUMMARIZE_ERR;
   printf("*** testing copy of simple global atts...");
   {      
      int ncid, ncid2;
      nc_type att_type;
      size_t att_len;
      int i;

      char *speech_in;
      signed char schar_in[ATT_LEN], schar_out[ATT_LEN] = {NC_MIN_BYTE, 1, NC_MAX_BYTE};
      unsigned char uchar_in[ATT_LEN], uchar_out[ATT_LEN] = {0, 128, NC_MAX_CHAR};
      short short_in[ATT_LEN], short_out[ATT_LEN] = {NC_MIN_SHORT, -128, NC_MAX_SHORT};
      int int_in[ATT_LEN], int_out[ATT_LEN] = {-100000, 128, 100000};
      float float_in[ATT_LEN], float_out[ATT_LEN] = {.5, 0.25, 0.125};
      double double_in[ATT_LEN], double_out[ATT_LEN] = {0.25, .5, 0.125};
      unsigned short ushort_in[ATT_LEN], ushort_out[ATT_LEN] = {0, 128, NC_MAX_USHORT};
      unsigned int uint_in[ATT_LEN], uint_out[ATT_LEN] = {0, 128, NC_MAX_UINT};
      unsigned long long uint64_in[ATT_LEN], uint64_out[ATT_LEN] = {0, 128, 18446744073709551612ULL};
      long long int64_in[ATT_LEN], int64_out[ATT_LEN] = {NC_MIN_INT64, 128, NC_MAX_INT64};

      /* Create a file with a global attribute of each type. */
      if (nc_create(FILE_NAME, NC_NETCDF4, &ncid)) ERR;
      if (nc_put_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, strlen(speech)+1, speech)) ERR;      
      if (nc_put_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, NC_BYTE, ATT_LEN, schar_out)) ERR;      
      if (nc_put_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, NC_UBYTE, ATT_LEN, uchar_out)) ERR;
      if (nc_put_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, NC_SHORT, ATT_LEN, short_out)) ERR;      
      if (nc_put_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, NC_INT, ATT_LEN, int_out)) ERR;      
      if (nc_put_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, NC_FLOAT, ATT_LEN, float_out)) ERR;      
      if (nc_put_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, NC_DOUBLE, ATT_LEN, double_out)) ERR;      
      if (nc_put_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, NC_USHORT, ATT_LEN, ushort_out)) ERR;      
      if (nc_put_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, NC_UINT, ATT_LEN, uint_out)) ERR;      
      if (nc_put_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, NC_INT64, ATT_LEN, int64_out)) ERR;      
      if (nc_put_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, NC_UINT64, ATT_LEN, uint64_out)) ERR;      

      /* Create another file and copy all the attributes. */
      if (nc_create(FILE_NAME2, NC_NETCDF4, &ncid2)) ERR;      
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_SCHAR_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_UCHAR_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_SHORT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_INT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_FLOAT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_USHORT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_UINT_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_INT64_NAME, ncid2, NC_GLOBAL)) ERR;
      if (nc_copy_att(ncid, NC_GLOBAL, ATT_UINT64_NAME, ncid2, NC_GLOBAL)) ERR;

      /* Close both files. */
      if (nc_close(ncid)) ERR;
      if (nc_close(ncid2)) ERR;

      /* Open the file and check attributes. */
      if (nc_open(FILE_NAME2, 0, &ncid)) ERR;
      /* Check text. */
      if (nc_inq_att(ncid, NC_GLOBAL, ATT_TEXT_NAME, &att_type, &att_len)) ERR;
      if (att_type != NC_CHAR || att_len != strlen(speech) + 1) ERR;
      if (!(speech_in = malloc(att_len + 1))) ERR;
      if (nc_get_att_text(ncid, NC_GLOBAL, ATT_TEXT_NAME, speech_in)) ERR;      
      if (strcmp(speech, speech_in)) ERR;
      free(speech_in);
      /* Check numeric values. */
      if (nc_get_att_schar(ncid, NC_GLOBAL, ATT_SCHAR_NAME, schar_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (schar_in[i] != schar_out[i]) ERR;
      if (nc_get_att_uchar(ncid, NC_GLOBAL, ATT_UCHAR_NAME, uchar_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (uchar_in[i] != uchar_out[i]) ERR;
      if (nc_get_att_short(ncid, NC_GLOBAL, ATT_SHORT_NAME, short_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (short_in[i] != short_out[i]) ERR;
      if (nc_get_att_int(ncid, NC_GLOBAL, ATT_INT_NAME, int_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (int_in[i] != int_out[i]) ERR;
      if (nc_get_att_float(ncid, NC_GLOBAL, ATT_FLOAT_NAME, float_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (float_in[i] != float_out[i]) ERR;
      if (nc_get_att_double(ncid, NC_GLOBAL, ATT_DOUBLE_NAME, double_in)) ERR;      
      for (i = 0; i < ATT_LEN; i++)
	 if (double_in[i] != double_out[i]) ERR;
      if (nc_get_att_ushort(ncid, NC_GLOBAL, ATT_USHORT_NAME, ushort_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (ushort_in[i] != ushort_out[i]) ERR;
      if (nc_get_att_uint(ncid, NC_GLOBAL, ATT_UINT_NAME, uint_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (uint_in[i] != uint_out[i]) ERR;
      if (nc_get_att_longlong(ncid, NC_GLOBAL, ATT_INT64_NAME, int64_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (int64_in[i] != int64_out[i]) ERR;
      if (nc_get_att_ulonglong(ncid, NC_GLOBAL, ATT_UINT64_NAME, uint64_in)) ERR;
      for (i = 0; i < ATT_LEN; i++)
	 if (uint64_in[i] != uint64_out[i]) ERR;
      if (nc_close(ncid)) ERR;
   }
   SUMMARIZE_ERR;
   FINAL_RESULTS;
}