summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/H5MM.c47
-rw-r--r--src/H5MMprivate.h1
-rw-r--r--src/H5private.h3
-rw-r--r--src/H5system.c44
-rw-r--r--src/H5win32defs.h9
-rw-r--r--src/uthash.h45
-rw-r--r--test/CMakeLists.txt1
-rw-r--r--test/Makefile.am2
-rw-r--r--test/testhdf5.c1
-rw-r--r--test/testhdf5.h2
-rw-r--r--test/th5_system.c90
11 files changed, 215 insertions, 30 deletions
diff --git a/src/H5MM.c b/src/H5MM.c
index ad55132..84c345d 100644
--- a/src/H5MM.c
+++ b/src/H5MM.c
@@ -503,6 +503,53 @@ done:
} /* end H5MM_strdup() */
/*-------------------------------------------------------------------------
+ * Function: H5MM_strndup
+ *
+ * Purpose: Duplicates a string, including memory allocation, but only
+ * copies at most `n` bytes from the string to be duplicated.
+ * If the string to be duplicated is longer than `n`, only `n`
+ * bytes are copied and a terminating null byte is added.
+ * NULL is NOT an acceptable value for the input string.
+ *
+ * If the string to be duplicated is the NULL pointer, then
+ * an error will be raised.
+ *
+ * Return: Success: Pointer to a new string
+ * Failure: NULL
+ *-------------------------------------------------------------------------
+ */
+char *
+H5MM_strndup(const char *s, size_t n)
+{
+#if defined H5_MEMORY_ALLOC_SANITY_CHECK
+ size_t len;
+#endif
+ char *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI(NULL)
+
+ if (!s)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "NULL string not allowed");
+
+#if defined H5_MEMORY_ALLOC_SANITY_CHECK
+ for (len = 0; len < n && s[len] != '\0'; len++)
+ ;
+
+ if (NULL == (ret_value = H5MM_malloc(len + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
+
+ H5MM_memcpy(ret_value, s, len);
+ ret_value[len] = '\0';
+#else
+ if (NULL == (ret_value = HDstrndup(s, n)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "string duplication failed");
+#endif
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5MM_strndup() */
+
+/*-------------------------------------------------------------------------
* Function: H5MM_xfree
*
* Purpose: Just like free(3) except null pointers are allowed as
diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h
index 10e536d..1eedce5 100644
--- a/src/H5MMprivate.h
+++ b/src/H5MMprivate.h
@@ -43,6 +43,7 @@ H5_DLL void *H5MM_calloc(size_t size);
H5_DLL void *H5MM_realloc(void *mem, size_t size);
H5_DLL char *H5MM_xstrdup(const char *s);
H5_DLL char *H5MM_strdup(const char *s);
+H5_DLL char *H5MM_strndup(const char *s, size_t n);
H5_DLL void *H5MM_xfree(void *mem);
H5_DLL void *H5MM_xfree_const(const void *mem);
H5_DLL void *H5MM_memcpy(void *dest, const void *src, size_t n);
diff --git a/src/H5private.h b/src/H5private.h
index 9e6be7e..12be702 100644
--- a/src/H5private.h
+++ b/src/H5private.h
@@ -1367,6 +1367,9 @@ H5_DLL H5_ATTR_CONST int Nflock(int fd, int operation);
#ifndef HDstrncpy
#define HDstrncpy(X, Y, Z) strncpy(X, Y, Z)
#endif
+#ifndef HDstrndup
+#define HDstrndup(S, N) strndup(S, N)
+#endif
#ifndef HDstrpbrk
#define HDstrpbrk(X, Y) strpbrk(X, Y)
#endif
diff --git a/src/H5system.c b/src/H5system.c
index 08a039b..6e55545 100644
--- a/src/H5system.c
+++ b/src/H5system.c
@@ -918,6 +918,50 @@ done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5_expand_windows_env_vars() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5_strndup
+ *
+ * Purpose: Similar to strndup() for use on Windows. Allocates a new
+ * string and copies at most `n` bytes from the original
+ * string into the new string. If the original string is
+ * longer than `n`, only `n` bytes are copied from the
+ * original string. In either case, the string being returned
+ * is guaranteed to be terminated with a null byte.
+ *
+ * The returned pointer is allocated by H5MM_malloc in this
+ * routine and must be freed by the caller with H5MM_free or
+ * H5MM_xfree.
+ *
+ * Return: Pointer to copied string on success
+ * NULL on failure
+ *
+ *-------------------------------------------------------------------------
+ */
+char *
+H5_strndup(const char *s, size_t n)
+{
+ size_t len;
+ char *ret_value = NULL;
+
+ FUNC_ENTER_NOAPI_NOINIT
+
+ if (!s)
+ HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "string cannot be NULL")
+
+ for (len = 0; len < n && s[len] != '\0'; len++)
+ ;
+
+ if (NULL == (ret_value = H5MM_malloc(len + 1)))
+ HGOTO_ERROR(H5E_RESOURCE, H5E_CANTALLOC, NULL, "can't allocate buffer for string")
+
+ H5MM_memcpy(ret_value, s, len);
+ ret_value[len] = '\0';
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+}
+
#endif /* H5_HAVE_WIN32_API */
/* Global variables */
diff --git a/src/H5win32defs.h b/src/H5win32defs.h
index 659adf1..e0ec3c3 100644
--- a/src/H5win32defs.h
+++ b/src/H5win32defs.h
@@ -17,13 +17,6 @@
*
*/
-/* _MSC_VER = 193x VS2022
- * _MSC_VER = 192x VS2019
- * _MSC_VER = 191x VS2017
- * _MSC_VER = 1900 VS2015
- * _MSC_VER = 1800 VS2013
- * _MSC_VER = 1700 VS2012
- */
#ifdef H5_HAVE_WIN32_API
/* __int64 is the correct type for the st_size field of the _stati64 struct.
@@ -83,6 +76,7 @@ struct timezone {
#define HDstat(S, B) _stati64(S, B)
#define HDstrcasecmp(A, B) _stricmp(A, B)
#define HDstrdup(S) _strdup(S)
+#define HDstrndup(S, N) H5_strndup(S, N)
#define HDstrtok_r(X, Y, Z) strtok_s(X, Y, Z)
#define HDtzset() _tzset()
#define HDunlink(S) _unlink(S)
@@ -104,6 +98,7 @@ H5_DLL wchar_t *H5_get_utf16_str(const char *s);
H5_DLL int Wopen_utf8(const char *path, int oflag, ...);
H5_DLL int Wremove_utf8(const char *path);
H5_DLL int H5_get_win32_times(H5_timevals_t *tvs);
+H5_DLL char *H5_strndup(const char *s, size_t n);
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/src/uthash.h b/src/uthash.h
index ecf512d..b1e5cbb 100644
--- a/src/uthash.h
+++ b/src/uthash.h
@@ -699,28 +699,29 @@ typedef unsigned char uint8_t;
hashv += (unsigned)(keylen); \
switch (_hj_k) { \
case 11: \
- hashv += ((unsigned)_hj_key[10] << 24); /* FALLTHROUGH */ \
- case 10: \
- hashv += ((unsigned)_hj_key[9] << 16); /* FALLTHROUGH */ \
- case 9: \
- hashv += ((unsigned)_hj_key[8] << 8); /* FALLTHROUGH */ \
- case 8: \
- _hj_j += ((unsigned)_hj_key[7] << 24); /* FALLTHROUGH */ \
- case 7: \
- _hj_j += ((unsigned)_hj_key[6] << 16); /* FALLTHROUGH */ \
- case 6: \
- _hj_j += ((unsigned)_hj_key[5] << 8); /* FALLTHROUGH */ \
- case 5: \
- _hj_j += _hj_key[4]; /* FALLTHROUGH */ \
- case 4: \
- _hj_i += ((unsigned)_hj_key[3] << 24); /* FALLTHROUGH */ \
- case 3: \
- _hj_i += ((unsigned)_hj_key[2] << 16); /* FALLTHROUGH */ \
- case 2: \
- _hj_i += ((unsigned)_hj_key[1] << 8); /* FALLTHROUGH */ \
- case 1: \
- _hj_i += _hj_key[0]; /* FALLTHROUGH */ \
- default:; \
+ hashv += ((unsigned)_hj_key[10] << 24); \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 10 : hashv += ((unsigned)_hj_key[9] << 16); \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 9 : hashv += ((unsigned)_hj_key[8] << 8); \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 8 : _hj_j += ((unsigned)_hj_key[7] << 24); \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 7 : _hj_j += ((unsigned)_hj_key[6] << 16); \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 6 : _hj_j += ((unsigned)_hj_key[5] << 8); \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 5 : _hj_j += _hj_key[4]; \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 4 : _hj_i += ((unsigned)_hj_key[3] << 24); \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 3 : _hj_i += ((unsigned)_hj_key[2] << 16); \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 2 : _hj_i += ((unsigned)_hj_key[1] << 8); \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ case 1 : _hj_i += _hj_key[0]; \
+ H5_ATTR_FALLTHROUGH /* FALLTHROUGH */ \
+ default:; \
} \
HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
} while (0)
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index e7f9e86..3dc9ef0 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -184,6 +184,7 @@ set (testhdf5_SOURCES
${HDF5_TEST_SOURCE_DIR}/tattr.c
${HDF5_TEST_SOURCE_DIR}/tchecksum.c
${HDF5_TEST_SOURCE_DIR}/tconfig.c
+ ${HDF5_TEST_SOURCE_DIR}/th5_system.c
${HDF5_TEST_SOURCE_DIR}/tcoords.c
${HDF5_TEST_SOURCE_DIR}/tfile.c
${HDF5_TEST_SOURCE_DIR}/tgenprop.c
diff --git a/test/Makefile.am b/test/Makefile.am
index 95d9e4f..551c695 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -214,7 +214,7 @@ CHECK_CLEANFILES+=accum.h5 cmpd_dset.h5 compact_dataset.h5 dataset.h5 dset_offse
# Sources for testhdf5 executable
testhdf5_SOURCES=testhdf5.c tarray.c tattr.c tchecksum.c tconfig.c tfile.c \
- tgenprop.c th5o.c th5s.c tcoords.c tid.c titerate.c tmeta.c tmisc.c \
+ tgenprop.c th5o.c th5s.c th5_system.c tcoords.c tid.c titerate.c tmeta.c tmisc.c \
trefer.c trefstr.c tselect.c tskiplist.c tsohm.c ttime.c tunicode.c \
tvlstr.c tvltypes.c
diff --git a/test/testhdf5.c b/test/testhdf5.c
index 587d916..e4d5c3e 100644
--- a/test/testhdf5.c
+++ b/test/testhdf5.c
@@ -42,6 +42,7 @@ main(int argc, char *argv[])
/* Tests are generally arranged from least to most complexity... */
AddTest("config", test_configure, cleanup_configure, "Configure definitions", NULL);
+ AddTest("h5system", test_h5_system, cleanup_h5_system, "H5system routines", NULL);
AddTest("metadata", test_metadata, cleanup_metadata, "Encoding/decoding metadata", NULL);
AddTest("checksum", test_checksum, cleanup_checksum, "Checksum algorithm", NULL);
AddTest("skiplist", test_skiplist, NULL, "Skip Lists", NULL);
diff --git a/test/testhdf5.h b/test/testhdf5.h
index 8abe890..eb2d464 100644
--- a/test/testhdf5.h
+++ b/test/testhdf5.h
@@ -219,6 +219,7 @@ void test_iterate(void);
void test_array(void);
void test_genprop(void);
void test_configure(void);
+void test_h5_system(void);
void test_misc(void);
void test_ids(void);
void test_skiplist(void);
@@ -242,6 +243,7 @@ void cleanup_iterate(void);
void cleanup_array(void);
void cleanup_genprop(void);
void cleanup_configure(void);
+void cleanup_h5_system(void);
void cleanup_sohm(void);
void cleanup_misc(void);
void cleanup_unicode(void);
diff --git a/test/th5_system.c b/test/th5_system.c
new file mode 100644
index 0000000..e25e4a0
--- /dev/null
+++ b/test/th5_system.c
@@ -0,0 +1,90 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * All rights reserved. *
+ * *
+ * This file is part of HDF5. The full HDF5 copyright notice, including *
+ * terms governing use, modification, and redistribution, is contained in *
+ * the COPYING file, which can be found at the root of the source code *
+ * distribution tree, or in https://www.hdfgroup.org/licenses. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#define H5_SYSTEM_TEST_PATH_MAX 4096
+
+/***********************************************************
+ *
+ * Test program: th5_system
+ *
+ * Testing for the routines available in H5system.c
+ *
+ *************************************************************/
+
+#include "testhdf5.h"
+
+#include "H5MMprivate.h"
+
+static void
+test_h5_strndup(void)
+{
+#ifdef H5_HAVE_WIN32_API
+ const char *const teststr = "myteststring";
+ char *str = NULL;
+
+ MESSAGE(5, ("Testing H5_strndup\n"));
+
+ /* Check that H5_strndup fails for a NULL string pointer */
+ H5E_BEGIN_TRY
+ {
+ str = H5_strndup(NULL, 20);
+ }
+ H5E_END_TRY
+ CHECK_PTR_NULL(str, "H5_strndup with NULL string pointer");
+ H5Eclear2(H5E_DEFAULT);
+
+ /* Check that H5_strndup correctly performs a 0-byte copy */
+ str = H5_strndup(teststr, 0);
+ CHECK_PTR(str, "H5_strndup for 0-byte copy");
+ if (str)
+ VERIFY_STR(str, "", "comparing H5_strndup for 0-byte copy to empty string");
+ str = H5MM_xfree(str);
+
+ /* Check that H5_strndup correctly performs partial copies */
+ str = H5_strndup(teststr, 6);
+ CHECK_PTR(str, "H5_strndup for partial copy");
+ if (str)
+ VERIFY_STR(str, "mytest", "comparing H5_strndup for partial copy to partial string");
+ str = H5MM_xfree(str);
+
+ /* Check that H5_strndup correctly performs identical copies */
+ str = H5_strndup(teststr, HDstrlen(teststr));
+ CHECK_PTR(str, "H5_strndup for identical copy");
+ if (str)
+ VERIFY_STR(str, teststr, "comparing H5_strndup for identical copy to original string");
+ str = H5MM_xfree(str);
+
+ /*
+ * Check that H5_strndup correctly performs copies when
+ * `n` is greater than the original string
+ */
+ str = H5_strndup(teststr, HDstrlen(teststr) + 2);
+ CHECK_PTR(str, "H5_strndup for larger 'n'");
+ if (str)
+ VERIFY_STR(str, teststr, "comparing H5_strndup with larger 'n' value to original string");
+ str = H5MM_xfree(str);
+#endif /* H5_HAVE_WIN32_API */
+}
+
+void
+test_h5_system(void)
+{
+ MESSAGE(5, ("Testing H5system routines\n"));
+
+ test_h5_strndup();
+}
+
+void
+cleanup_h5_system(void)
+{
+ /* Nothing to cleanup yet */
+}