/* # <> # Copyright 2019, Lawrence Livermore National Security, LLC. # This file is part of the gidiplus package (https://github.com/LLNL/gidiplus). # gidiplus is licensed under the MIT license (see https://opensource.org/licenses/MIT). # SPDX-License-Identifier: MIT # <> */ #ifndef MCGIDI_STRING_HPP #define MCGIDI_STRING_HPP /* Modified from Karsten Burger's version 2017 * Made changes to make it more compatible with GPUs. * Allow for data to be initialized to nullptr. * * Modified from public domain software: * Karsten Burger 2014 * * Sourceforge project "Simple C++ String Class" * http://sourceforge.net/projects/simplecstringclass/ * This a simple C++ string class based on class my_string by * Christian Stigen Larsen, 2007, http://csl.name/programming/my_string/ * * It only uses the C-string functions and is thus independent of the * standard C++ library. * * It is public domain, in the hope, that you find it useful. * Please note that there is no guarantee of any kind: it is supplied * without any warranty; without even the implied warranty of * merchantability or fitness for a particular purpose. * * You can probably replace std::string with this one in many * cases, but a lot of stuff is missing, and I would recommend * you stick to std::string anyway. * * I want to point out that there is nothing fancy about this class. * It keeps every string in its own buffer, and copies as often as * needed. * The data always contains a trailing NUL char. * * However, I believe that is a good approach. For instance, it * uses malloc rather than new, which makes it possible to use * realloc. On many systems, realloc will try to use up "invisible" * space that was used by malloc to pad a string for memory alignment. * That makes it potentially fast for small concatenations. * * I don't propose to use this class for anything practical, since * we already have std::string, but it may be an interesting read * for C++ novices at the very least. Also, additional functions can * easily be expanded. * * Also I met a case, where I had to avoid std::string because of * link problems with an application using mixed libraries, especially * one compiled with an old Intel compiler icc 7. * * Bugs/suggestions to info [at) dr-burger ]dot[ com * or via the Sourceforge project page. */ #include // size_t #include #include /** @brief Simple C++ string class, useful as replacement for std::string if this cannot be used, or just for fun. */ namespace MCGIDI { class String { char* p; ///< The data size_t allocated_; ///< The allocated memory size (including trailing NUL) size_t size_; ///< The currently used memory size (excluding trailing NUL) public: typedef size_t size_type; static const size_type npos; LUPI_HOST_DEVICE String(); LUPI_HOST_DEVICE ~String(); LUPI_HOST_DEVICE String(const String&); LUPI_HOST_DEVICE String(const char*); LUPI_HOST_DEVICE String& operator=(const char*); LUPI_HOST_DEVICE String& operator=(const String&); LUPI_HOST_DEVICE String& operator+=(const String&); LUPI_HOST_DEVICE String& operator+=(const char*); LUPI_HOST_DEVICE String& operator+=(char); LUPI_HOST_DEVICE void push_back(char); friend String LUPI_HOST_DEVICE operator+(const String& lhs, const String& rhs); LUPI_HOST_DEVICE bool operator==(const char*) const; LUPI_HOST_DEVICE bool operator==(const String&) const; LUPI_HOST_DEVICE void clear(); // set string to empty string (memory remains reserved) LUPI_HOST_DEVICE void clearMemory(); // set string to empty string (memory is free'd) LUPI_HOST_DEVICE size_type size() const { return size_; } ///< size without terminating NUL LUPI_HOST_DEVICE size_type length() const { return size_; } ///< as size() // size if fully used LUPI_HOST_DEVICE size_type capacity() const { return allocated_-1; } // 8 byte alligned size LUPI_HOST_DEVICE size_t internalSize() const { size_t delta = allocated_; size_t sub = delta % 8; if (sub != 0) delta += (8-sub); return delta * sizeof(char); } LUPI_HOST_DEVICE bool empty() const { return size_ == 0; } LUPI_HOST_DEVICE const char* c_str() const { return p; } ///< raw data /** Reserve internal string memory so that n characters can be put into the string (plus 1 for the NUL char). If there is already enough memory, nothing happens, if not, the memory will be realloated to exactly this amount. */ LUPI_HOST_DEVICE void reserve( size_type n, char ** address = nullptr); /** Resize string. If n is less than the current size, the string will be truncated. If n is larger, then the memory will be reallocated to exactly this amount, and the additional characters will be NUL characters. */ LUPI_HOST_DEVICE void resize( size_type n, char ** address = nullptr); /** Resize string. If n is less than the current size, the string will be truncated. If n is larger, then the memory will be reallocated to exactly this amount, and the additional characters will be c characters. */ LUPI_HOST_DEVICE void resize( size_type n, char c, char ** address = nullptr); /// swap contents LUPI_HOST_DEVICE void swap( String& ); LUPI_HOST_DEVICE String substr(const size_type pos, size_type length) const; // unchecked access: LUPI_HOST_DEVICE char& operator[](const size_type i) { return p[i]; } LUPI_HOST_DEVICE char operator[](const size_type i) const { return p[i]; } // checked access: LUPI_HOST_DEVICE char& at(const size_type i); LUPI_HOST_DEVICE char at(const size_type i) const; /// erase len characters at position pos LUPI_HOST_DEVICE String& erase(size_type pos, size_type len); /// Append n characters of a string LUPI_HOST_DEVICE String& append(const char* str, size_type n); LUPI_HOST_DEVICE int compare( size_type pos, size_type len, const String& str ) const; LUPI_HOST_DEVICE int compare( size_type pos, size_type len, const char* str ) const; private: // reallocate the internal memory LUPI_HOST_DEVICE void my_realloc( size_type n, char ** address = nullptr); LUPI_HOST_DEVICE char* strdup_never_null(const char* other); }; // class LUPI_HOST_DEVICE bool operator<(const String&, const String&); } #endif