Wed, 20 Jul 2016 17:47:42 +0300
Made String::vsprintf behave properly with long strings.
/* Copyright 2014 - 2016 Teemu Piippo All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include <deque> #include <string> #include <stdarg.h> #include "basics.h" #include "list.h" BEGIN_ZFC_NAMESPACE class String { public: typedef std::string::iterator Iterator; typedef std::string::const_iterator ConstIterator; String(); String(char a); String(const char* data); String(const std::string& data); String(const Vector<char>& data); void append(const char* text); void append(char character); void append(const String& text); ConstIterator begin() const; Iterator begin(); int compare(const String &other) const; int count(char character) const; const char* chars() const; void clear(); ConstIterator end() const; Iterator end(); bool endsWith(const String &other) const; int find(const char* subString, int startingPosition = 0) const; int find(char character, int startingPosition = 0) const; int indexDifference(int a, int b); void insert(int position, char character); void insert(int position, const char* string); bool isEmpty() const; bool isNumeric() const; void modifyIndex(int &a) const; int findLast(const char* subString, int startingPosition = -1) const; int length() const; bool maskAgainst(const String &pattern) const; String md5() const; String mid(int rangeBegin, int rangeEnd) const; void normalize(int(*filter)(int) = &isspace); String normalized(int(*filter)(int) = &isspace) const; void prepend(String text); void remove(int position, int length); void removeAt(int position); void removeFromEnd(int length); void removeFromStart(int length); void replace(const char* text, const char* replacement); void replace(int position, int amount, const String &text); String right(int length) const; void shrinkToFit(); class StringList split(const String &delimeter) const; class StringList split(char delimeter) const; void __cdecl sprintf(const char* fmtstr, ...); bool startsWith(const String &other) const; const std::string& stdString() const; void strip(char unwanted); void strip(const List<char> &unwanted); double toDouble(bool* ok = nullptr) const; float toFloat(bool* ok = nullptr) const; long toInt(bool* ok = nullptr, int base = 10) const; String toLowerCase() const; String toUpperCase() const; void vsprintf(const char* fmtstr, va_list args); static String fromNumber(short int a); static String fromNumber(int a); static String fromNumber(long int a); static String fromNumber(unsigned short int a); static String fromNumber(unsigned int a); static String fromNumber(unsigned long int a); static String fromNumber(double a); String operator+(const String& data) const; String operator+(const char* data) const; String operator+(int num) const; String& operator+=(const String& data); String& operator+=(const char* data); String& operator+=(int num); String& operator+=(char data); char& operator[](int i); char operator[](int i) const; bool operator==(const String& other) const; bool operator==(const char* other) const; bool operator!=(const String& other) const; bool operator!=(const char* other) const; bool operator>(const String& other) const; bool operator<(const String& other) const; bool operator>=(const String& other) const; bool operator<=(const String& other) const; operator const char*() const; operator const std::string&() const; private: std::string m_string; }; class StringList : public List<String> { public: StringList(); StringList(int numvalues); StringList(const List<String>& other); String join(const String& delim); }; inline bool operator==(const char* a, const String& b); inline String operator+(const char* a, const String& b); // -------------------------------------------------------------------------------------------------------------------- /*! * \brief Constructs an empty string. */ inline String::String() {} /*! * \brief Constructs a string from a single character. * \param character Character to create a string out of. */ inline String::String(char character) { char buffer[2] = { character, '\0' }; m_string = buffer; } /*! * \brief Constructs a string from a char-array. * \param string char-array to convert. */ inline String::String(const char* string) : m_string(string) {} /*! * \brief Constructs a string out of a \c std::string . * \param string \c std::string to base the construction on. */ inline String::String(const std::string& string) : m_string(string) {} /*! * \brief Constructs a string out of a vector of characters. The vector does not have to be null-terminated. * \param charVector Vector of characters to construct the string out of. */ inline String::String(const Vector<char>& charVector) : m_string(charVector.data(), charVector.size()) {} /*! * \returns a constant iterator to the beginning of the string. */ inline String::ConstIterator String::begin() const { return m_string.cbegin(); } /*! * \returns the string's contents as a char-array. */ inline const char* String::chars() const { return m_string.c_str(); } /*! * \returns the string's constant end-iterator. */ inline String::ConstIterator String::end() const { return m_string.end(); } /*! * \returns whether or not the string is empty. */ inline bool String::isEmpty() const { return m_string[0] == '\0'; } /*! * \returns the length of the string. */ inline int String::length() const { return m_string.length(); } /*! * \returns the underlying \c std::string . */ inline const std::string& String::stdString() const { return m_string; } /*! * \brief Adds text from a char-array to the end of the string. * \param text Text to append. */ inline void String::append(const char* text) { m_string.append(text); } /*! * \brief Adds text to the end of the string. * \param text Text to append. */ inline void String::append(char character) { m_string.push_back(character); } /*! * \brief Adds text from another string to the end of this string. * \param text Text to append. */ inline void String::append(const String& text) { m_string.append(text.chars()); } /*! * \returns a mutable iterator to the beginning of the string. */ inline String::Iterator String::begin() { return m_string.begin(); } /*! * \brief Clears the string. */ inline void String::clear() { m_string.clear(); } /*! * \returns the string's mutable end-iterator. */ inline String::Iterator String::end() { return m_string.end(); } /*! * \brief Compares two string indices, supporting negatives as offsets from the end of string. * \param a First index to compare * \param b Second index to compare * \returns the difference of two indices. */ inline int String::indexDifference(int a, int b) { modifyIndex(a); modifyIndex(b); return b - a; } /*! * \brief Inserts a character into the string. * \param position Position in the string where to insert the character into. * \param character Character to insert into the string. */ inline void String::insert(int position, char character) { m_string.insert(m_string.begin() + position, character); } /*! * \brief Inserts a substring into the string. * \param position Position in the string where to insert the substring. * \param string Substring to insert. */ inline void String::insert(int position, const char* string) { m_string.insert(position, string); } /*! * \brief Modifies the given index so that if it is negative, it is translated into a positive index starting from the * end of the string. For example, an index of -1 will be modified to point to the last character in the string, * -2 to the second last, etc. * \param index Index to translate. */ inline void String::modifyIndex(int& index) const { if (index < 0) index = length() - index; } /*! * \brief Prepends the given text to the beginning of the string. * \param text Text to prepend. */ inline void String::prepend(String text) { m_string = (text + m_string).stdString(); } /*! * \brief Removes a range of text from the string. * \param position Position where to start removing text. * \param length Amount of characters to remove. */ inline void String::remove(int position, int length) { m_string.replace(position, length, ""); } /*! * \brief Removes a single character from the string. * \param position Position of the character to remove string from. */ inline void String::removeAt(int position) { m_string.erase(m_string.begin() + position); } /*! * \brief Removes a number of characters from the end of the string. * \param length Amount of characters to remove. */ inline void String::removeFromEnd(int length) { remove(this->length() - length, length); } /*! * \brief Removes a number of characters from the beginning of the string. * \param length Amount of characters to remove. */ inline void String::removeFromStart(int length) { remove(0, length); } /*! * \brief Replaces a range of text in the string with another. * \param position Position where to start replacing text. * \param amount Amount of characters to replace. * \param text Replacement string. */ inline void String::replace(int position, int amount, const String& text) { m_string.replace(position, amount, text.chars()); } /*! * \brief Shrinks the string so that it does not allocate more characters than necessary. */ inline void String::shrinkToFit() { m_string.shrink_to_fit(); } /*! * \brief Converts a number into a string, and returns a new string with the number appended to the end of the string. * \param number Number to convert and append. * \returns the resulting string. */ inline String String::operator+(int number) const { return *this + String::fromNumber(number); } /*! * \brief Appends text into the string. * \param text Text to append. * \returns a reference to this string. */ inline String& String::operator+=(const String& text) { append(text); return *this; } /*! * \brief Appends text into the string. * \param text Text to append. * \returns a reference to this string. */ inline String& String::operator+=(const char* text) { append(text); return *this; } /*! * \brief Converts a number into a string, and appends it into this string. * \param number The number to append. * \returns a refence to this string. */ inline String& String::operator+=(int number) { return operator+=(String::fromNumber(number)); } /*! * \brief Appends a character into this string. * \param character The character to append. * \return a reference to this string. */ inline String& String::operator+=(char character) { append(character); return *this; } /*! * \param index Index referring to a character of this string. * \returns an editable reference to the character pointed by the given index. */ inline char& String::operator[](int index) { return m_string[index]; } /*! * \param index Index referring to a character of this string. * \returns an const reference to the character pointed by the given index. */ inline char String::operator[](int index) const { return m_string[index]; } /*! * \param other String to compare with. * \returns whether or not this string is the same as the other string. */ inline bool String::operator==(const String& other) const { return stdString() == other.stdString(); } /*! * \param other String to compare with. * \returns whether or not this string is the same as the other string. */ inline bool String::operator==(const char* other) const { return m_string == other; } /*! * \param other String to compare with. * \returns whether or not this string is different than the other string. */ inline bool String::operator!=(const String& other) const { return stdString() != other.stdString(); } /*! * \param other String to compare with. * \returns whether or not this string is different than the other string. */ inline bool String::operator!=(const char* other) const { return m_string != other; } /*! * \param other String to compare with. * \return whether or not this string is lexicographically greater than the other string. */ inline bool String::operator>(const String& other) const { return stdString() > other.stdString(); } /*! * \param other String to compare with. * \return whether or not this string is lexicographically lesser than the other string. */ inline bool String::operator<(const String& other) const { return stdString() < other.stdString(); } /*! * \param other String to compare with. * \return whether or not this string is lexicographically at least as great as the other string. */ inline bool String::operator>=(const String& other) const { return stdString() >= other.stdString(); } /*! * \param other String to compare with. * \return whether or not this string is lexicographically at most as great as the other string. */ inline bool String::operator<=(const String& other) const { return stdString() <= other.stdString(); } /*! * \returns a char-array representation of this string. */ inline String::operator const char*() const { return chars(); } /*! * \returns the underlying \c std::string of this string. */ inline String::operator const std::string&() const { return stdString(); } /*! * \brief Constructs an empty string list. */ inline StringList::StringList() {} /*! * \brief Constructs a string list containing \c numvalues empty strings. * \param numvalues Amount of empty strings to fill. */ inline StringList::StringList(int numvalues) : List<String>(numvalues) {} /*! * \brief Constructs a string list from another list of strings. * \param other The list of strings to use for construction. */ inline StringList::StringList(const List<String>& other) : List<String>(other) {} /*! * \brief An \c operator== implementation that allows a char-array to be at the left side of a string comparison * with a \c String. * \param one A char-array representation of a string to compare. * \param other A string to compare. * \returns whether or not the two parameters are equal. */ inline bool operator==(const char* one, const String& other) { return other == one; } /*! * \brief An \c operator+ implementation that allows a char-array to be at the left side of a string catenation * with a \c String. * \param one A char-array representation of a string to catenate. * \param other A string to catenate. * \returns the catenated string. */ inline String operator+(const char* one, const String& other) { return String(one) + other; } END_ZFC_NAMESPACE