
#include <hdf5.h>
#include <stdlib.h>

#define FILE        "vlstra.h5"

int verbosity = 1;
int num_errs = 0;
#define FAIL -1

/* Use %ld to print the value because long should cover most cases. */
/* Used to make certain a return value _is_not_ a value */
#define CHECK(ret, val, where) do {					      \
    if (verbosity>0) fprintf(stderr, "   Call to routine: %15s at line %4d "  \
				"in %s returned %ld \n",		      \
				where, (int)__LINE__, __FILE__,		      \
				(long)ret);				      \
    if (ret == val) {							      \
	fprintf(stderr, "*** UNEXPECTED RETURN from %s is %ld at line %4d "   \
		   "in %s\n", where, (long)ret, (int)__LINE__, __FILE__);     \
	num_errs++;							      \
	H5Eprint (stdout);						      \
    }									      \
    H5Eclear();								      \
} while(0)


static void test_write_vl_string_attribute(void)
{
    hid_t file, root, dataspace, att;
    hid_t type;
    herr_t ret;
    const char *string_att = "This is the string for the attribute";
    char *string_att_check;

    file = H5Fcreate(FILE, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
    CHECK(file, FAIL, "H5Fcreate");

    /* Create a datatype to refer to. */
    type = H5Tcopy (H5T_C_S1);
    CHECK(type, FAIL, "H5Tcopy");

    ret = H5Tset_size (type, H5T_VARIABLE);
    CHECK(ret, FAIL, "H5Tset_size");

    root = H5Gopen(file, "/");
    CHECK(root, FAIL, "H5Gopen");

    dataspace = H5Screate(H5S_SCALAR);
    CHECK(dataspace, FAIL, "H5Screate");

    att = H5Acreate(root, "test_scalar", type, dataspace, H5P_DEFAULT);
    CHECK(att, FAIL, "H5Acreate");

    ret = H5Awrite(att, type, &string_att);
    CHECK(ret, FAIL, "H5Awrite");

    ret = H5Aread(att, type, &string_att_check);
    CHECK(ret, FAIL, "H5Aread");

    fprintf(stderr, "Attribute string read was '%s'\n", string_att_check);
    free(string_att_check);

    ret = H5Aclose(att);
    CHECK(ret, FAIL, "HAclose");

    ret = H5Gclose(root);
    CHECK(ret, FAIL, "H5Gclose");

    ret = H5Tclose(type);
    CHECK(ret, FAIL, "H5Tclose");

    ret = H5Sclose(dataspace);
    CHECK(ret, FAIL, "H5Sclose");

    ret = H5Fclose(file);
    CHECK(ret, FAIL, "H5Fclose");

    return;
}

static void test_read_vl_string_attribute(void)
{
    hid_t file, root, att;
    hid_t type;
    herr_t ret;
    char *string_att;

    file = H5Fopen(FILE, H5F_ACC_RDONLY, H5P_DEFAULT);
    CHECK(file, FAIL, "H5Fopen");

    /* Create a datatype to refer to. */
    type = H5Tcopy (H5T_C_S1);
    CHECK(type, FAIL, "H5Tcopy");

    ret = H5Tset_size (type, H5T_VARIABLE);
    CHECK(ret, FAIL, "H5Tset_size");

    root = H5Gopen(file, "/");
    CHECK(root, FAIL, "H5Gopen");

    att = H5Aopen_name(root, "test_scalar");
    CHECK(att, FAIL, "H5Aopen_name");

    ret = H5Aread(att, type, &string_att);
    CHECK(ret, FAIL, "H5Aread");

    fprintf(stderr, "Attribute string read was '%s'\n", string_att);
    free(string_att);

    ret = H5Aclose(att);
    CHECK(ret, FAIL, "HAclose");

    ret = H5Tclose(type);
    CHECK(ret, FAIL, "H5Tclose");

    ret = H5Gclose(root);
    CHECK(ret, FAIL, "H5Gclose");

    ret = H5Fclose(file);
    CHECK(ret, FAIL, "H5Fclose");

    return;
}

int main (int argc, char *argv[])
{
      test_write_vl_string_attribute();

/* with 5-1.4.2-patch1 the following call will fail 
      test_read_vl_string_attribute();
*/

      return 0;
}     
