From 727abf4f062d97d3725d9b301fe4f08cbc578b00 Mon Sep 17 00:00:00 2001 From: Axel Huebl Date: Fri, 8 Jan 2016 11:03:38 +0100 Subject: [PATCH] Plugins: Common String Helpers (Splash) Adds ArrayOfString helpers for libSplash write calls. See https://github.com/ComputationalRadiationPhysics/libSplash/issues/220 for the description of the problem. If a user wants to write an array of strings they need to be padded to the longest one. This helper does that. Use it like this: ```C++ #include "plugins/common/stringHelpers.hpp" // [...] // create some strings std::list myListOfStr; myListOfStr.push_back("short"); myListOfStr.push_back("middle"); myListOfStr.push_back("loooong"); // convert to splash format helper::GetSplashArrayOfString getSplashArrayOfString; helper::GetSplashArrayOfString::Result myArrOfStr; myArrOfStr = getSplashArrayOfString( myListOfStr ); // splash calls dc->writeGlobalAttribute( threadParams->currentStep, myArrOfStr.colType, "someListOfStr", 1u, /* ndims: 1D array */ Dimensions(myListOfStr.size(),0,0), /* size of 1D array */ &(myArrOfStr.buffers.at(0)) ); ``` Also adds a `helper::` namespace to avoid polluting the `PIConGPU` namespace. --- .../include/plugins/common/stringHelpers.hpp | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/picongpu/include/plugins/common/stringHelpers.hpp b/src/picongpu/include/plugins/common/stringHelpers.hpp index aac309821cf..0ab257e8d32 100644 --- a/src/picongpu/include/plugins/common/stringHelpers.hpp +++ b/src/picongpu/include/plugins/common/stringHelpers.hpp @@ -23,9 +23,17 @@ #include #include #include +// libSplash +#if(ENABLE_HDF5 == 1) +# include +# include +# include +#endif namespace picongpu +{ +namespace helper { /** Return the current date as string * @@ -50,4 +58,86 @@ namespace picongpu return dateString.str(); } +#if(ENABLE_HDF5 == 1) + /** Create c-strings suitable for libSplash + * + * Convert a std::list of strings to a format that is suitable to + * be written into libSplash attributes (\0-concated and padded + * array of constant c-strings). + * Each string will be padded to the length of the longest string. + * + * Independent of the padding you chose, the final strings will be '\0' + * terminated. + */ + class GetSplashArrayOfString + { + private: + // compare two std::string by their size + struct CompStrBySize + { + bool operator()( std::string i, std::string j) + { + return i.size() < j.size(); + } + }; + + public: + // resulting type containing all attributes for a libSplash write call + struct Result + { + splash::ColTypeString colType; + std::vector listIndex; + std::vector buffers; // all of same length + }; + + Result operator()( + std::list listOfStrings, + char padding = '\0' + ) + { + // find length of longest string in list + CompStrBySize compStrBySize; + std::string longestString = *std::max_element( + listOfStrings.begin(), + listOfStrings.end(), + compStrBySize + ); + size_t lenMax = longestString.size(); + + // create libSplash data type suitable for longest string + Result result; + result.colType = splash::ColTypeString(lenMax); + + // prepare buffer with padding + // size per buffer must include terminator \0 ! + const size_t bytesPerEntry = lenMax + 1; + const size_t lenAllBuffers = listOfStrings.size() * bytesPerEntry; + result.buffers.assign( lenAllBuffers, padding ); + + // copy buffers + std::list::iterator listIt = listOfStrings.begin(); + for( + size_t i = 0; + i < listOfStrings.size(); + ++i, ++listIt + ) + { + // index points to each part of the buffer individually + const size_t startIdx = i * bytesPerEntry; + char* start = &result.buffers.at( startIdx ); + result.listIndex.push_back( start ); + + // copy byte wise + std::copy( listIt->c_str(), listIt->c_str() + bytesPerEntry, start ); + if( padding != '\0' ) + result.buffers.at( startIdx + lenMax ) = '\0'; + } + + // return + return result; + } + }; +#endif + +} // namespace helper } // namespace picongpu