// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // // clr_std/string // // Copy of some key Standard Template Library functionality // // This was created for use with SuperPMI. It has the minimal functionality needed by SuperPMI. It hasn't // been tested elsewhere. #ifdef _MSC_VER #pragma once #endif #ifdef USE_STL #include #else #ifndef __clr_std_string_h__ #define __clr_std_string_h__ #include "clr_std/vector" namespace std { template class basic_string { public: typedef T value_type; typedef size_t size_type; typedef typename vector::iterator iterator; typedef typename vector::const_iterator const_iterator; basic_string() : m_string(1) // start with a string of length 1 for null terminator { m_string[0] = T(); } basic_string(const basic_string& _Right) { assign(_Right); } // Initialize a string with _Count characters from the string pointed at by _Ptr. // If you want to include the trailing null character, _Count needs to include that. basic_string(const value_type* _Ptr, size_type _Count) : m_string(_Count + 1) // add 1 for a null terminator { copy(_Ptr, _Count); } basic_string(const value_type* _Ptr) { this->basic_string::basic_string(_Ptr, c_len(_Ptr)); } void reserve(size_t newcapacity) { m_string.reserve(newcapacity + 1); // add 1 for the null terminator } // // Assignment // basic_string& operator=(const basic_string& _Right) { if (this != &_Right) { assign(_Right); } return (*this); } basic_string& assign(const basic_string& _Right) { m_string.resize(_Right.size() + 1); // +1 for null terminator copy(_Right); return (*this); } // // Basic data copying // void copy(const basic_string& _Right) { assert(size() >= _Right.size()); size_type i; for (i = 0; i < _Right.size(); i++) { m_string[i] = _Right.m_string[i]; } m_string[i] = T(); } void copy(const value_type* _Ptr, size_type _Count) { assert(size() >= _Count); size_type i; for (i = 0; i < _Count; i++) { m_string[i] = _Ptr[i]; } m_string[i] = T(); } // // Appending // // Append a C-style string to the string. basic_string& operator+=(const value_type* _Ptr) { size_type oldsize = size(); // doesn't include null terminator size_type addsize = c_len(_Ptr); // doesn't include null terminator size_type newsize = oldsize + addsize + 1; m_string.resize(newsize); size_type i; for (i = oldsize; i < newsize - 1; i++) { m_string[i] = *_Ptr++; } m_string[i] = T(); return (*this); } basic_string& operator+=(const basic_string& _Right) { size_type oldsize = size(); // doesn't include null terminator size_type addsize = _Right.size(); // doesn't include null terminator size_type newsize = oldsize + addsize + 1; m_string.resize(newsize); size_type new_index = oldsize, right_index = 0; while (right_index < addsize) { m_string[new_index] = _Right.m_string[right_index]; ++new_index; ++right_index; } m_string[new_index] = T(); return (*this); } ~basic_string() { // vector destructor does all the work } size_t size() const { assert(m_string.size() > 0); return m_string.size() - 1; // Don't report the null terminator. } T& operator[](size_t iIndex) { assert(iIndex < size() + 1); // allow looking at the null terminator return m_string[iIndex]; } const T* c_str() const { return m_string.data(); } iterator begin() { return m_string.begin(); } iterator end() { return m_string.end(); } const_iterator cbegin() const { return m_string.cbegin(); } const_iterator cend() const { return m_string.cend(); } basic_string substr(size_type _Off = 0, size_type _Count = npos) const { size_type cursize = size(); if (_Off >= cursize) { // result will be empty return basic_string(); } else { if ((_Count == npos) || // No count specified; take the whole string suffix (_Off + _Count > cursize)) // Count specified is too many characters; just take the whole suffix { _Count = cursize - _Off; } return basic_string(m_string.data() + _Off, _Count); } } size_type find_last_of(value_type _Ch) const { for (size_type _Off = size(); _Off != 0; _Off--) { if (m_string[_Off - 1] == _Ch) { return _Off - 1; } } return npos; } bool empty() const { return size() == 0; } int compare(const basic_string& _Str) const { size_type i; size_type compareSize = size(); if (_Str.size() < compareSize) { // This string is longer; compare character-by-character only as many characters as we have. compareSize = _Str.size(); } for (i = 0; i < compareSize; i++) { if (m_string[i] != _Str.m_string[i]) { if (m_string[i] < _Str.m_string[i]) { return -1; } else { return 1; } } } // All the characters we compared were identical, but one string might be longer than the other. if (size() == _Str.size()) { // We compared everything. return 0; } else if (size() < _Str.size()) { // _Str has more characters than this. return -1; } else { // this has more characters than _Str return 1; } } static const size_type npos = size_type(-1); private: // Compute the length in characters of a null-terminated C-style string, not including the trailing null character. // _Ptr must not be nullptr. size_type c_len(const value_type* _Ptr) { size_type count; for (count = 0; *_Ptr != T(); _Ptr++) { count++; } return count; } vector m_string; // use a vector<> to represent the string, to avoid reimplementing similar functionality }; // class basic_string // // String class instantiations // typedef basic_string string; // // Numeric conversions // // convert integer T to string template inline string _IntToString(const char *_Fmt, T _Val) { const size_t MaxIntBufSize = 21; /* can hold -2^63 and 2^64 - 1, plus NUL */ char buf[MaxIntBufSize]; int len = sprintf_s(buf, MaxIntBufSize, _Fmt, _Val); return (string(buf, len)); } inline string to_string(int _Val) { return (_IntToString("%d", _Val)); } inline string to_string(unsigned int _Val) { return (_IntToString("%u", _Val)); } inline string to_string(long _Val) { return (_IntToString("%ld", _Val)); } inline string to_string(unsigned long _Val) { return (_IntToString("%lu", _Val)); } inline string to_string(long long _Val) { return (_IntToString("%lld", _Val)); } inline string to_string(unsigned long long _Val) { return (_IntToString("%llu", _Val)); } // // Comparisons // template inline bool operator==( const basic_string& _Left, const basic_string& _Right) { return (_Left.compare(_Right) == 0); } template inline bool operator!=( const basic_string& _Left, const basic_string& _Right) { return (!(_Left == _Right)); } template inline bool operator<( const basic_string& _Left, const basic_string& _Right) { return (_Left.compare(_Right) < 0); } template inline bool operator>( const basic_string& _Left, const basic_string& _Right) { return (_Right < _Left); } template inline bool operator<=( const basic_string& _Left, const basic_string& _Right) { return (!(_Right < _Left)); } template inline bool operator>=( const basic_string& _Left, const basic_string& _Right) { return (!(_Left < _Right)); } // // String concatenation and other string operations // template inline basic_string operator+( const basic_string& _Left, const basic_string& _Right) { basic_string ret; ret.reserve(_Left.size() + _Right.size()); ret += _Left; ret += _Right; return ret; } }; // namespace std #endif /* __clr_std_string_h__ */ #endif // !USE_STL // Help the VIM editor figure out what kind of file this no-extension file is. // vim: filetype=cpp