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