Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize string #11

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
481 changes: 394 additions & 87 deletions include/TINYSTL/string.h
Original file line number Diff line number Diff line change
@@ -38,170 +38,477 @@ namespace tinystl {
string();
string(const string& other);
string(const char* sz);
string(const char* first, const char* last);
string(const char* sz, size_t len);
~string();

string& operator=(const string& other);
string& operator=(char ch);
string& operator=(const char* sz);

string& operator+=(const string& other);
string& operator+=(char ch);
string& operator+=(const char* sz);

const char* c_str() const;
bool empty() const;
size_t size() const;
size_t capacity() const;

typedef char* iterator;
iterator begin();
iterator end();

typedef const char* const_iterator;
const_iterator begin() const;
const_iterator end() const;

char operator[](size_t pos) const;
char& operator[](size_t pos);

int compare(const string& other) const;
int compare(const char* sz) const;

void reserve(size_t size);
void resize(size_t size);
void reserve(size_t capacity);
void resize(size_t n);
void resize(size_t n, char ch);

void clear();

void assign(char ch);
void assign(const char* sz);
void assign(const char* first, const char* last);
void assign(const string& other);

void push_back(char ch);
void append(const char* sz);
void append(const char* first, const char* last);
void append(const string& other);
void insert(iterator where, char ch);
void insert(iterator where, const char* sz);
void insert(iterator where, const char* first, const char* last);
void insert(iterator where, const string& other);
void erase(iterator first, iterator last);

void swap(string& other);

private:
typedef char* pointer;
pointer m_first;
pointer m_last;
pointer m_capacity;

static const size_t c_nbuffer = 12;
char m_buffer[12];
static const size_t c_nbuffer = 16;
static const size_t c_longflag = ((size_t)1) << (sizeof(size_t) * 8 - 1);
size_t m_size;
union {
struct {
pointer m_first;
pointer m_capacity;
};
char m_buffer[c_nbuffer];
};
};

inline string::string()
: m_first(m_buffer)
, m_last(m_buffer)
, m_capacity(m_buffer + c_nbuffer)
: m_size(0)
{
resize(0);
m_buffer[0] = 0;
}

inline string::string(const string& other)
: m_first(m_buffer)
, m_last(m_buffer)
, m_capacity(m_buffer + c_nbuffer)
: m_size(0)
{
reserve(other.size());
append(other.m_first, other.m_last);
assign(other);
}

inline string::string(const char* sz)
: m_first(m_buffer)
, m_last(m_buffer)
, m_capacity(m_buffer + c_nbuffer)
: m_size(0)
{
size_t len = 0;
for (const char* it = sz; *it; ++it)
++len;
assign(sz);
}

reserve(len);
append(sz, sz + len);
inline string::string(const char* first, const char* last)
: m_size(0)
{
assign(first, last);
}

inline string::string(const char* sz, size_t len)
: m_first(m_buffer)
, m_last(m_buffer)
, m_capacity(m_buffer + c_nbuffer)
: m_size(0)
{
reserve(len);
append(sz, sz + len);
}

inline string::~string() {
if (m_first != m_buffer)
if (m_size & c_longflag)
TINYSTL_ALLOCATOR::static_deallocate(m_first, m_capacity - m_first);
}

inline string& string::operator=(const string& other) {
string(other).swap(*this);
if (this != &other)
assign(other);
return *this;
}

inline string& string::operator=(char ch) {
assign(ch);
return *this;
}

inline string& string::operator=(const char* sz) {
assign(sz);
return *this;
}

inline string& string::operator+=(const string& other) {
append(other);
return *this;
}

inline string& string::operator+=(char ch) {
push_back(ch);
return *this;
}

inline string& string::operator+=(const char* sz) {
append(sz);
return *this;
}

inline const char* string::c_str() const {
return m_first;
if (m_size & c_longflag)
return m_first;
else
return m_buffer;
}

inline size_t string::size() const
{
return (size_t)(m_last - m_first);
inline bool string::empty() const {
return size() == 0;
}

inline void string::reserve(size_t capacity) {
if (m_first + capacity + 1 <= m_capacity)
return;
inline size_t string::size() const {
return m_size & ~c_longflag;
}

const size_t size = (size_t)(m_last - m_first);
inline size_t string::capacity() const {
if (m_size & c_longflag)
return m_capacity - m_first - 1;
else
return c_nbuffer - 1;
}

inline string::iterator string::begin() {
if (m_size & c_longflag)
return m_first;
else
return m_buffer;
}

inline string::iterator string::end() {
if (m_size & c_longflag)
return m_first + (m_size & ~c_longflag);
else
return m_buffer + m_size;
}

pointer newfirst = (pointer)TINYSTL_ALLOCATOR::static_allocate(capacity + 1);
for (pointer it = m_first, newit = newfirst, end = m_last; it != end; ++it, ++newit)
inline string::const_iterator string::begin() const {
if (m_size & c_longflag)
return m_first;
else
return m_buffer;
}

inline string::const_iterator string::end() const {
if (m_size & c_longflag)
return m_first + (m_size & ~c_longflag);
else
return m_buffer + m_size;
}

inline char string::operator[](size_t pos) const {
return begin()[pos];
}

inline char& string::operator[](size_t pos) {
return begin()[pos];
}

inline int string::compare(const string& other) const {
return compare(other.c_str());
}

inline int string::compare(const char* sz) const {
const char* it = c_str();
for (; *it && *sz && (*it == *sz); ++it, ++sz);
return *it - *sz;
}

inline void string::reserve(size_t cap) {
if (cap <= capacity())
return;

pointer newfirst = (pointer)TINYSTL_ALLOCATOR::static_allocate(cap + 1);
for (pointer it = begin(), newit = newfirst, e = end() + 1; it != e; ++it, ++newit)
*newit = *it;
if (m_first != m_buffer)
if (m_size & c_longflag)
TINYSTL_ALLOCATOR::static_deallocate(m_first, m_capacity - m_first);

else
m_size |= c_longflag;
m_first = newfirst;
m_last = newfirst + size;
m_capacity = m_first + capacity;
m_capacity = m_first + cap + 1;
}

inline void string::resize(size_t n) {
resize(n, 0);
}

inline void string::resize(size_t n, char ch) {
if (size() < n) {
reserve(n);
for (pointer it = end(), e = begin() + n; it != e; ++it)
*it = ch;
}
pointer it = begin() + n;
*it = 0;
m_size = n | (m_size & c_longflag);
}

inline void string::clear() {
resize(0);
}

inline void string::assign(char ch) {
pointer it = begin();
*it = ch;
*(it + 1) = 0;
m_size = 1 | (m_size & c_longflag);
}

inline void string::assign(const char* sz) {
size_t len = 0;
for (const char *it = sz; *it; ++it)
++len;

assign(sz, sz + len);
}

inline void string::resize(size_t size) {
reserve(size);
for (pointer it = m_last, end = m_first + size + 1; it < end; ++it)
*it = 0;
inline void string::assign(const char* first, const char* last) {
size_t newsize = last - first;
reserve(newsize);

m_last += size;
pointer newit = begin();
for (const char* it = first; it != last; ++it, ++newit)
*newit = *it;
*newit = 0;
m_size = newsize | (m_size & c_longflag);
}

inline void string::assign(const string& other) {
assign(other.begin(), other.end());
}

inline void string::push_back(char ch) {
if (size() != capacity()) {
pointer it = end();
*it = ch;
*(it + 1) = 0;
++m_size;
} else {
append(&ch, &ch + 1);
}
}

inline void string::append(const char *sz) {
size_t len = 0;
for (const char *it = sz; *it; ++it)
++len;
append(sz, sz + len);
}

inline void string::append(const char* first, const char* last) {
const size_t newsize = (size_t)((m_last - m_first) + (last - first) + 1);
if (m_first + newsize > m_capacity)
const size_t newsize = (size_t)(size() + (last - first));
if (newsize > capacity())
reserve((newsize * 3) / 2);

for (; first != last; ++m_last, ++first)
*m_last = *first;
*m_last = 0;
pointer newit = end();
for (const char* it = first; it != last; ++it, ++newit)
*newit = *it;
*newit = 0;
m_size = newsize | (m_size & c_longflag);
}

inline void string::swap(string& other) {
const pointer tfirst = m_first, tlast = m_last, tcapacity = m_capacity;
m_first = other.m_first, m_last = other.m_last, m_capacity = other.m_capacity;
other.m_first = tfirst, other.m_last = tlast, other.m_capacity = tcapacity;
inline void string::append(const string& other) {
append(other.begin(), other.end());
}

char tbuffer[c_nbuffer];
inline void string::insert(iterator where, char ch) {
insert(where, &ch, &ch + 1);
}

inline void string::insert(iterator where, const char* sz) {
size_t len = 0;
for (const char *it = sz; *it; ++it)
++len;
insert(where, sz, sz + len);
}

inline void string::insert(iterator where, const char* first, const char* last) {
if (first == last)
return;

const size_t w = where - begin();
const size_t newsize = (size_t)(size() + (last - first));
if (newsize > capacity())
reserve((newsize * 3) / 2);

if (m_first == other.m_buffer)
for (pointer it = other.m_buffer, end = m_last, out = tbuffer; it != end; ++it, ++out)
*out = *it;
pointer newit = begin() + newsize;
for (pointer it = end(), e = begin() + w; it >= e; --it, --newit)
*newit = *it;

newit = begin() + w;
for (const char* it = first; it != last; ++it, ++newit)
*newit = *it;
m_size = newsize | (m_size & c_longflag);
}

inline void string::insert(iterator where, const string& other) {
insert(where, other.begin(), other.end());
}

inline void string::erase(iterator first, iterator last) {
if (first == last)
return;

const size_t newsize = (size_t)(size() + (first - last));
pointer newit = first;
for (pointer it = last, e = end(); it != e; ++it, ++newit)
*newit = *it;
*newit = 0;
m_size = newsize | (m_size & c_longflag);
}

if (other.m_first == m_buffer) {
other.m_last = other.m_last - other.m_first + other.m_buffer;
other.m_first = other.m_buffer;
other.m_capacity = other.m_buffer + c_nbuffer;
inline void string::swap(string& other) {
const size_t tsize = m_size;
pointer tfirst, tcapacity;
char tbuffer[c_nbuffer];

for (pointer it = other.m_first, end = other.m_last, in = m_buffer; it != end; ++it, ++in)
*it = *in;
*other.m_last = 0;
if (tsize & c_longflag) {
tfirst = m_first;
tcapacity = m_capacity;
} else {
for (pointer it = m_buffer, newit = tbuffer, e = m_buffer + tsize + 1; it != e; ++it, ++newit)
*newit = *it;
}

if (m_first == other.m_buffer) {
m_last = m_last - m_first + m_buffer;
m_first = m_buffer;
m_capacity = m_buffer + c_nbuffer;
m_size = other.m_size;
if (other.m_size & c_longflag) {
m_first = other.m_first;
m_capacity = other.m_capacity;
} else {
for (pointer it = other.m_buffer, newit = m_buffer, e = other.m_buffer + m_size + 1; it != e; ++it, ++newit)
*newit = *it;
}

for (pointer it = m_first, end = m_last, in = tbuffer; it != end; ++it, ++in)
*it = *in;
*m_last = 0;
other.m_size = tsize;
if (tsize & c_longflag) {
other.m_first = tfirst;
other.m_capacity = tcapacity;
} else {
for (pointer it = tbuffer, newit = other.m_buffer, e = tbuffer + tsize + 1; it != e; ++it, ++newit)
*newit = *it;
}
}

inline bool operator==(const string& lhs, const string& rhs) {
typedef const char* pointer;
inline string operator+(const string& lhs, const string& rhs) {
string ret;
ret.reserve(lhs.size() + rhs.size());
ret += lhs;
ret += rhs;
return ret;
}

inline string operator+(const string& lhs, const char* rhs) {
string ret = lhs;
ret += rhs;
return ret;
}

const size_t lsize = lhs.size(), rsize = rhs.size();
if (lsize != rsize)
inline string operator+(const char* lhs, const string& rhs) {
string ret = lhs;
ret += rhs;
return ret;
}

inline bool operator==(const string& lhs, const string& rhs) {
if (lhs.size() != rhs.size())
return false;

pointer lit = lhs.c_str(), rit = rhs.c_str();
pointer lend = lit + lsize;
while (lit != lend)
if (*lit++ != *rit++)
return false;
return lhs.compare(rhs) == 0;
}

inline bool operator==(const string& lhs, const char* rhs) {
return lhs.compare(rhs) == 0;
}

inline bool operator==(const char* lhs, const string& rhs) {
return rhs.compare(lhs) == 0;
}

inline bool operator!=(const string& lhs, const string& rhs) {
return !(lhs == rhs);
}

inline bool operator!=(const string& lhs, const char* rhs) {
return !(lhs == rhs);
}

inline bool operator!=(const char* lhs, const string& rhs) {
return !(lhs == rhs);
}

inline bool operator<(const string& lhs, const string& rhs) {
return lhs.compare(rhs) < 0;
}

inline bool operator<(const string& lhs, const char* rhs) {
return lhs.compare(rhs) < 0;
}

inline bool operator<(const char* lhs, const string& rhs) {
return rhs.compare(lhs) > 0;
}

inline bool operator>(const string& lhs, const string& rhs) {
return rhs < lhs;
}

inline bool operator>(const string& lhs, const char* rhs) {
return rhs < lhs;
}

inline bool operator>(const char* lhs, const string& rhs) {
return rhs < lhs;
}

inline bool operator<=(const string& lhs, const string& rhs) {
return !(rhs < lhs);
}

inline bool operator<=(const string& lhs, const char* rhs) {
return !(rhs < lhs);
}

inline bool operator<=(const char* lhs, const string& rhs) {
return !(rhs < lhs);
}

inline bool operator>=(const string& lhs, const string& rhs) {
return !(lhs < rhs);
}

inline bool operator>=(const string& lhs, const char* rhs) {
return !(lhs < rhs);
}

return true;
inline bool operator>=(const char* lhs, const string& rhs) {
return !(lhs < rhs);
}

static inline size_t hash(const string& value) {
123 changes: 123 additions & 0 deletions test/string_assign.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/*-
* Copyright 2012-2015 Matthew Endsley
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/

#include <TINYSTL/string.h>
#include <UnitTest++.h>
#include <string.h>

TEST(test_empty) {
tinystl::string s;
CHECK(s.empty());
CHECK(s.capacity() == 15);
CHECK(s.begin() == s.end());
CHECK(strlen(s.c_str()) == 0);
CHECK(s == "");
}

TEST(test_small) {
tinystl::string s1("");
CHECK(s1.empty());
CHECK(s1.capacity() == 15);
CHECK(s1.begin() == s1.end());
CHECK(strlen(s1.c_str()) == 0);
CHECK(s1 == "");

tinystl::string s2("hello");
CHECK(s2.size() == 5);
CHECK(s2.capacity() == 15);
CHECK(s2.begin() + 5 == s2.end());
CHECK(strlen(s2.c_str()) == 5);
CHECK(s2 == "hello");

tinystl::string s3("exactly 15 char");
CHECK(s3.size() == 15);
CHECK(s3.capacity() == 15);
CHECK(s3.begin() + 15 == s3.end());
CHECK(strlen(s3.c_str()) == 15);
CHECK(s3 == "exactly 15 char");
}

TEST(test_long) {
const char* origin = "very long string larger than large string limit";
size_t len = strlen(origin);
tinystl::string s(origin);
CHECK(s.size() == len);
CHECK(s.capacity() == len);
CHECK(s.begin() + len == s.end());
CHECK(strlen(s.c_str()) == len);
CHECK(s == origin);
}

TEST(test_assign) {
tinystl::string s;
const char* originshort = "short";
size_t lenshort = strlen(originshort);
s = originshort;
CHECK(s.size() == lenshort);
CHECK(s.capacity() == 15);
CHECK(s.begin() + lenshort == s.end());
CHECK(strlen(s.c_str()) == lenshort);
CHECK(s == originshort);

const char* originlong = "long long long long long long long long long long long long";
size_t lenlong = strlen(originlong);
s = originlong;
CHECK(s.size() == lenlong);
CHECK(s.capacity() == lenlong);
CHECK(s.begin() + lenlong == s.end());
CHECK(strlen(s.c_str()) == lenlong);
CHECK(s == originlong);

s = originshort;
CHECK(s.size() == lenshort);
CHECK(s.capacity() == lenlong);
CHECK(s.begin() + lenshort == s.end());
CHECK(strlen(s.c_str()) == lenshort);
CHECK(s == originshort);
}

TEST(test_swap) {
tinystl::string ss1("short");
tinystl::string ss2("another");
tinystl::string sl1("long string for testing purposes");
tinystl::string sl2("another long string for testing purposes");

ss1.swap(ss2);
CHECK(ss1 == "another");
CHECK(ss2 == "short");

sl1.swap(sl2);
CHECK(sl1 == "another long string for testing purposes");
CHECK(sl2 == "long string for testing purposes");

ss1.swap(sl2);
CHECK(ss1 == "long string for testing purposes");
CHECK(sl2 == "another");

sl1.swap(ss2);
CHECK(sl1 == "short");
CHECK(ss2 == "another long string for testing purposes");
}
70 changes: 70 additions & 0 deletions test/string_compare.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*-
* Copyright 2012-2015 Matthew Endsley
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/

#include <TINYSTL/string.h>
#include <UnitTest++.h>
TEST(test_equal) {
tinystl::string s("hello");
CHECK(s == tinystl::string("hello"));
CHECK(s == "hello");
CHECK("hello" == s);
CHECK(s != tinystl::string("hello world"));
CHECK(s != "hello world");
CHECK("hello world" != s);
}

TEST(test_ltgt) {
tinystl::string s("hello");
CHECK(!(s < "hello"));
CHECK(s < "helloo");
CHECK(s < "hello0");
CHECK(s > "he1");
CHECK(s > "hell");
CHECK(s > "a");
CHECK(s < "z");
CHECK(s > "aaaaaaaa");
CHECK(s < "zzzzzzzz");
CHECK(s > "hella");
CHECK(s < "hellz");
CHECK(s < "hellz");
}

TEST(test_lege) {
tinystl::string s("hello");
CHECK(s <= "hello");
CHECK(s >= "hello");
CHECK(s <= "helloo");
CHECK(s <= "hello0");
CHECK(s >= "he1");
CHECK(s >= "hell");
CHECK(s >= "a");
CHECK(s <= "z");
CHECK(s >= "aaaaaaaa");
CHECK(s <= "zzzzzzzz");
CHECK(s >= "hella");
CHECK(s <= "hellz");
CHECK(s <= "hellz");
}
71 changes: 71 additions & 0 deletions test/string_modify.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*-
* Copyright 2012-2015 Matthew Endsley
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/

#include <TINYSTL/string.h>
#include <UnitTest++.h>

TEST(test_append) {
tinystl::string s;
s += "hello";
s += ' ';
s += "world";
CHECK(s == "hello world");
s += " and this is a very long string";
CHECK(s == "hello world and this is a very long string");
}

TEST(test_add) {
CHECK(tinystl::string("hello") + tinystl::string(" world") == "hello world");
CHECK(tinystl::string("hello") + " world" == "hello world");
CHECK(tinystl::string("hello") + " " + "world" == "hello world");
CHECK("hello" + tinystl::string(" ") + "world" == "hello world");
}

TEST(test_insert) {
tinystl::string s("world");
s.insert(s.end(), '!');
CHECK(s == "world!");
s.insert(s.begin(), "hello");
CHECK(s == "helloworld!");
s.insert(s.begin() + 5, " ");
CHECK(s == "hello world!");
s.insert(s.end() - 1, ", prepend a huge string to check");
CHECK(s == "hello world, prepend a huge string to check!");
}

TEST(test_erase) {
tinystl::string s("hello");
s.erase(s.begin(), s.end());
CHECK(s.empty());
s = "hello";
s.erase(s.end() - 1, s.end());
CHECK(s == "hell");
s = "hello world and this is a very long string";
s.erase(s.begin(), s.begin() + 4);
CHECK(s == "o world and this is a very long string");
s.erase(s.begin(), s.end());
CHECK(s.empty());
}
61 changes: 61 additions & 0 deletions test/string_resize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*-
* Copyright 2012-2015 Matthew Endsley
* All rights reserved
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted providing 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.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/

#include <TINYSTL/string.h>
#include <UnitTest++.h>
#include <string.h>

TEST(test_reserve) {
tinystl::string s;
s.reserve(0);
CHECK(s.capacity() == 15);
s.reserve(10);
s = "short";
CHECK(s.capacity() == 15);
CHECK(s == "short");
s.reserve(15);
CHECK(s.capacity() == 15);
CHECK(s == "short");
s.reserve(100);
CHECK(s.capacity() == 100);
CHECK(s == "short");
s.reserve(101);
CHECK(s.capacity() == 101);
CHECK(s == "short");
}

TEST(test_resize) {
tinystl::string s;
s.resize(1, ' ');
CHECK(s == " ");
s.resize(16, '+');
CHECK(s == " +++++++++++++++");
s.clear();
s.resize(16, '@');
CHECK(s == "@@@@@@@@@@@@@@@@");
s.resize(12, '-');
CHECK(s == "@@@@@@@@@@@@");
}