diff --git a/src/util/pack.c b/src/util/pack.c index 38745b6a2e..4e522fe418 100644 --- a/src/util/pack.c +++ b/src/util/pack.c @@ -501,6 +501,7 @@ return (OMPI_SUCCESS); switch(type) { case OMPI_BYTE: memcpy(dest, src, n); + break; case OMPI_PACKED: return OMPI_ERROR; case OMPI_INT16: @@ -536,3 +537,104 @@ return (OMPI_SUCCESS); return OMPI_SUCCESS; } + + +/* + * fuctions to handle strings, which use the length arguments differently to normal pack routines + * + * @param buffer the destination for the packed data + * @param str pointer to start of NULL terminated string + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + * + */ + + int ompi_pack_string (ompi_buffer_t buffer, char *str) + { + uint32_t op_size=0; + int rc; + + if (!str) { + return OMPI_ERROR; + } + + if (!buffer) { return (OMPI_ERROR); } + + op_size = (uint32_t) strlen (str); + + /* a packed string consists of a packed length, and the non terminated string */ + rc = ompi_pack(buffer, (void*) &op_size, 1, OMPI_INT32); + + if (OMPI_ERROR==rc) { return (rc); } + + if (op_size>0) { + rc = ompi_pack(buffer, (void*) str, op_size, OMPI_BYTE); + } + + return (rc); + } + +/** + * This function unpacks a string from the buffer. This routine ALLOCATES memory + * for this string. Allocating means users DO NOT need to define max string lengths for any + * strings they pass (allowing the use of unrestricted naming in the GPR f.e.) + * if this string is zero length we return a NULL pointer + * + * @param buffer the source of the packed string data + * @param pointer to a character pointer of the unpacked string or NULL for zero length + * string + * @param type the type of the data to unpack + * + * @retval number of characters unpacked (INCLUDING the NULL character) + * If this value is '0' this indicates an empty string was passed. + * @retval OMPI_ERROR + * + */ + + int ompi_unpack_string(ompi_buffer_t buffer, char ** str) + { + char *inptr; + uint32_t inlen=0; + uint32_t outlen=0; /* always inlen+1 I hope */ + int rc; + + if (!str) { + return OMPI_ERROR; + } + + if (!buffer) { return (OMPI_ERROR); } + + /* first unpack the length of the packed string */ + + rc = ompi_unpack (buffer, (void*) &inlen, 1, OMPI_INT32); + + if (OMPI_ERROR==rc) { return (rc); } + + if (!inlen) { /* if we have a zero length string... set str pointer to NULL and return 0 length */ + *str = NULL; + return (0); + } + else { + outlen = inlen +1; + } + + /* no zero length string, so allocate memory for it */ + inptr = (char*) calloc (outlen, 1); + + if (!inptr) { return (OMPI_ERROR); } + + /* have memory, unpack as byte, null terminate and then return */ + rc = ompi_unpack (buffer, (void*) inptr, inlen, OMPI_BYTE); + + if (OMPI_ERROR==rc) { return (rc); } + + inptr[inlen] = '\0'; /* NULL terminate */ + + *str = (char*) inptr; /* copy the string over */ + + return (outlen); + } + + + diff --git a/src/util/pack.h b/src/util/pack.h index 4ebefdaff9..e899345ec7 100644 --- a/src/util/pack.h +++ b/src/util/pack.h @@ -160,6 +160,38 @@ extern "C" { int ompi_unpack(ompi_buffer_t buffer, void * dest, size_t n, ompi_pack_type_t type); +/* + * fuctions to handle strings, which use the length arguments different + * + * @param buffer the destination for the packed data + * @param str pointer to start of NULL terminated string + * + * @retval OMPI_SUCCESS + * @retval OMPI_ERROR + * + */ + + int ompi_pack_string (ompi_buffer_t buffer, char *str); + +/** + * This function unpacks a string from the buffer. This routine ALLOCATES memory + * for this string. Allocating means users DO NOT need to define max string lengths for any + * strings they pass (allowing the use of unrestricted naming in the GPR f.e.) + * if this string is zero length we return a NULL pointer + * + * @param buffer the source of the packed string data + * @param pointer to a character pointer of the unpacked string or NULL for zero length string + * @param type the type of the data to unpack + * + * @retval number of characters unpacked (INCLUDING the NULL character) + * If this value is '0' this indicates an empty string was passed. + * @retval OMPI_ERROR + * + */ + int ompi_unpack_string(ompi_buffer_t buffer, char ** str); + + + #if defined(c_plusplus) || defined(__cplusplus) } diff --git a/test/util/ompi_pack.c b/test/util/ompi_pack.c index 04a4535e22..deb29547bc 100644 --- a/test/util/ompi_pack.c +++ b/test/util/ompi_pack.c @@ -30,6 +30,7 @@ static bool test4(void); /* verify pack a packed buffer */ static bool test5(void); /* verify unpack */ static bool test6(void); /* verify free */ static bool test7(void); /* verify preallocated buffer init, pack and unpack */ +static bool test8(void); /* verify string pack and unpack */ int main (int argc, char* argv[]) { @@ -85,6 +86,13 @@ int main (int argc, char* argv[]) test_failure("ompi_pack test7 failed"); } + if (test8()) { + test_success(); + } + else { + test_failure("ompi_pack test8 failed"); + } + /* if (testN()) { */ /* test_success(); */ @@ -264,6 +272,63 @@ static bool test7(void) /* verify preallocated buffer init, pack and unpa return (true); } + +static bool test8(void) /* verify string pack and unpack */ +{ + + int rc; + char *str1; + char *str2; + + rc = ompi_buffer_init (&bufA, 0); + if (OMPI_ERROR==rc) { test_comment ("ompi_buffer_init failed"); return(false);} + + rc = ompi_buffer_init (&bufB, 10); + if (OMPI_ERROR==rc) { test_comment ("ompi_buffer_init failed"); return(false);} + + rc = ompi_buffer_init (&bufC, 16); + if (OMPI_ERROR==rc) { test_comment ("ompi_buffer_init failed"); return(false);} + + rc = ompi_pack_string (bufA, "HELLO "); + if (OMPI_ERROR==rc) { test_comment ("ompi_pack_string failed"); return(false);} + + rc = ompi_pack_string (bufB, "WORLD!"); + if (OMPI_ERROR==rc) { test_comment ("ompi_pack_string failed"); return(false);} + + rc = ompi_pack (bufC, bufA, 1, OMPI_PACKED); + if (OMPI_ERROR==rc) { test_comment ("ompi_pack failed"); return(false);} + rc = ompi_pack (bufC, bufB, 1, OMPI_PACKED); + if (OMPI_ERROR==rc) { test_comment ("ompi_pack failed"); return(false);} + + /* we now have a buffer with two strings in it */ + rc = ompi_unpack_string (bufC, &str1); + if (OMPI_ERROR==rc) { test_comment ("ompi_pack_string failed"); return(false);} + + rc = strcmp ("HELLO ", str1); + if (rc) { test_comment ("strcmp returns no zero value."); return (false); } + + rc = ompi_unpack_string (bufC, &str2); + if (OMPI_ERROR==rc) { test_comment ("ompi_pack_string failed"); return(false);} + + rc = strcmp ("WORLD!", str2); + if (rc) { test_comment ("strcmp returns no zero value."); return (false); } + + + rc = ompi_buffer_free (bufA); + if (OMPI_ERROR==rc) { test_comment ("ompi_buffer_free failed"); return(false);} + + rc = ompi_buffer_free (bufB); + if (OMPI_ERROR==rc) { test_comment ("ompi_buffer_free failed"); return(false);} + + rc = ompi_buffer_free (bufC); + if (OMPI_ERROR==rc) { test_comment ("ompi_buffer_free failed"); return(false);} + + if (str1) { free (str1); } + if (str2) { free (str2); } + + return (true); +} + /* int dump_buf (ompi_buffer_t buf) */ /* { */ /* int rc, i, out; */