refactored code, made new comments, extended manualtest.cpp, commented
out tests of unimplemented stuff in test.cpp
This commit is contained in:
		
							
								
								
									
										1
									
								
								Char.h
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								Char.h
									
									
									
									
									
								
							@@ -1,4 +1,5 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
#include "String.h"
 | 
					#include "String.h"
 | 
				
			||||||
class String;
 | 
					class String;
 | 
				
			||||||
class StringValue;
 | 
					class StringValue;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										92
									
								
								String.cpp
									
									
									
									
									
								
							
							
						
						
									
										92
									
								
								String.cpp
									
									
									
									
									
								
							@@ -1,7 +1,4 @@
 | 
				
			|||||||
#include "String.h"
 | 
					#include "String.h"
 | 
				
			||||||
#include "Char.h"
 | 
					 | 
				
			||||||
#include <cstring>
 | 
					 | 
				
			||||||
#include <memory>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,57 +43,68 @@ void swap(String& s1, String& s2) noexcept
 | 
				
			|||||||
    swap(s1._str, s2._str);
 | 
					    swap(s1._str, s2._str);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String::String(String&& other) noexcept : String()   // init via default ctor so _str is a nullptr
 | 
					String::String(String&& other) noexcept
 | 
				
			||||||
 | 
					:String()   // init via default ctor so _str is a nullptr
 | 
				
			||||||
{ swap(*this, other); }
 | 
					{ swap(*this, other); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String String::operator+(const String& rhs) const
 | 
					String String::operator+(const String& rhs) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto size = this->size() + rhs.size() + 1;      // plus a null-terminator
 | 
					    auto data = this->copy_and_concat(rhs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    String ret;
 | 
				
			||||||
 | 
					    ret._str = new StringValue(data);               // build new String from data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String& String::operator+=(const String& rhs)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    auto data = this->copy_and_concat(rhs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    _str->operator--();                             // release old data
 | 
				
			||||||
 | 
					    _str = new StringValue(data);                   // create new
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return *this;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// copies this and concats str
 | 
				
			||||||
 | 
					char* String::copy_and_concat(const String& str) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    auto size = this->size() + str.size() + 1;      // plus a null-terminator
 | 
				
			||||||
    auto data = new char[size];                     // make some space
 | 
					    auto data = new char[size];                     // make some space
 | 
				
			||||||
    std::strcpy(data, this->c_str());               // copy data of this
 | 
					    std::strcpy(data, this->c_str());               // copy data of this
 | 
				
			||||||
 | 
					    std::strcat(data, str.c_str());                 // concat str
 | 
				
			||||||
 | 
					    return data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					String String::operator+(char rhs) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    auto data = this->copy_and_concat(rhs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    String ret;
 | 
					    String ret;
 | 
				
			||||||
    ret._str = new StringValue(std::strcat(data, rhs.c_str()));     // append data of rsh
 | 
					    ret._str = new StringValue(data);               // build new String from data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return ret;
 | 
					    return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String& String::operator+=(const String& other)
 | 
					String& String::operator+=(char rhs)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto size = this->size() + other.size() + 1;     // plus a null-terminator
 | 
					    auto data = this->copy_and_concat(rhs);
 | 
				
			||||||
    auto data = new char[size];
 | 
					 | 
				
			||||||
    std::strcpy(data, this->c_str());                // copy our data
 | 
					 | 
				
			||||||
    std::strcat(data, other.c_str());                // append data of the other string
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    _str->operator--();                              // release old data
 | 
					    _str->operator--();                             // release old data
 | 
				
			||||||
    _str = new StringValue(data);
 | 
					    _str = new StringValue(data);                   // create new
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return *this;
 | 
					    return *this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
String String::operator+(char c) const
 | 
					// copies this and concats c
 | 
				
			||||||
 | 
					char* String::copy_and_concat(char c) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    auto data = new char[this->size() + 2];          // new char + null terminator
 | 
					    auto data = new char[this->size() + 2];         // plus new char & null terminator
 | 
				
			||||||
    std::strcpy(data, this->c_str());
 | 
					    std::strcpy(data, this->c_str());               // copy data of this
 | 
				
			||||||
    data[this->size()] = c;
 | 
					    data[this->size()] = c;                         // concats c
 | 
				
			||||||
    data[this->size()+1] = '\0';
 | 
					    data[this->size() + 1] = '\0';                  // null-terminator
 | 
				
			||||||
 | 
					    return data;
 | 
				
			||||||
    String ret;
 | 
					 | 
				
			||||||
    ret._str = new StringValue(data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return ret;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
String& String::operator+=(char c)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    auto data = new char[this->size() + 2];          // new char + null terminator
 | 
					 | 
				
			||||||
    std::strcpy(data, this->c_str());
 | 
					 | 
				
			||||||
    data[this->size()] = c;
 | 
					 | 
				
			||||||
    data[this->size()+1] = '\0';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _str->operator--();
 | 
					 | 
				
			||||||
    _str = new StringValue(data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return *this;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool String::operator==(const String& other) const
 | 
					bool String::operator==(const String& other) const
 | 
				
			||||||
@@ -112,14 +120,12 @@ const char& String::operator[](size_t index) const
 | 
				
			|||||||
    if (_str)
 | 
					    if (_str)
 | 
				
			||||||
        return (const_cast<const StringValue*>(_str))->operator[](index);   // cast to use const operator[]
 | 
					        return (const_cast<const StringValue*>(_str))->operator[](index);   // cast to use const operator[]
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        throw std::runtime_error("You cannot index an uninitialized String!");
 | 
					        throw std::runtime_error("You cannot uninitialized Strings!");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// reuse const operator[]
 | 
					// reuse const operator[], just as Scott Meyers would
 | 
				
			||||||
Char String::operator[](size_t index)
 | 
					Char String::operator[](size_t index)
 | 
				
			||||||
{
 | 
					{ return Char(_str->index_of(&const_cast<char&>(const_cast<const String*>(this)->operator[](index))), *this); }
 | 
				
			||||||
    return Char(_str->index_of(&const_cast<char&>(const_cast<const String*>(this)->operator[](index))), *this);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
size_t String::size() const noexcept
 | 
					size_t String::size() const noexcept
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -134,7 +140,7 @@ const char* String::c_str() const
 | 
				
			|||||||
    if (_str)
 | 
					    if (_str)
 | 
				
			||||||
        return *_str;   // invokes StringValue::operator const char*()
 | 
					        return *_str;   // invokes StringValue::operator const char*()
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        throw std::runtime_error("You cannot get the content of an uninitialized string!");
 | 
					        throw std::runtime_error("You cannot get the content of uninitialized Strings!");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
std::istream& operator>>(std::istream& is, String& str)
 | 
					std::istream& operator>>(std::istream& is, String& str)
 | 
				
			||||||
@@ -157,7 +163,7 @@ std::istream& operator>>(std::istream& is, String& str)
 | 
				
			|||||||
    if (str._str)                                 // if there is some old data, release it
 | 
					    if (str._str)                                 // if there is some old data, release it
 | 
				
			||||||
        str._str->operator--();
 | 
					        str._str->operator--();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    str._str = new StringValue(data.release());   // release ownership of final data
 | 
					    str._str = new StringValue(data.release());   // get ownership of final data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return is;
 | 
					    return is;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								String.h
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								String.h
									
									
									
									
									
								
							@@ -1,5 +1,7 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <iostream>
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					#include <memory>
 | 
				
			||||||
#include "StringValue.h"
 | 
					#include "StringValue.h"
 | 
				
			||||||
#include "Char.h"
 | 
					#include "Char.h"
 | 
				
			||||||
class Char;
 | 
					class Char;
 | 
				
			||||||
@@ -16,6 +18,9 @@ private:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    StringValue* _str;
 | 
					    StringValue* _str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    char* copy_and_concat(const String& str) const;
 | 
				
			||||||
 | 
					    char* copy_and_concat(char c) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    String() noexcept;
 | 
					    String() noexcept;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,4 @@
 | 
				
			|||||||
#include "StringValue.h"
 | 
					#include "StringValue.h"
 | 
				
			||||||
#include <stdexcept>
 | 
					 | 
				
			||||||
#include <cstring>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -30,6 +28,7 @@ const char& StringValue::operator[](size_t index) const
 | 
				
			|||||||
    return _data[index];
 | 
					    return _data[index];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// reuse const operator[], just as Scott Meyers would
 | 
				
			||||||
char& StringValue::operator[](size_t index)
 | 
					char& StringValue::operator[](size_t index)
 | 
				
			||||||
{ return const_cast<char&>(const_cast<const StringValue*>(this)->operator[](index)); }
 | 
					{ return const_cast<char&>(const_cast<const StringValue*>(this)->operator[](index)); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -41,8 +40,8 @@ size_t StringValue::size() const noexcept
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
size_t StringValue::index_of(char* c) const
 | 
					size_t StringValue::index_of(char* c) const
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    size_t index = c - _data;   // this is totally safe pointer-arithmetic
 | 
					    size_t index = c - _data;   // this is totally safe as long as I don't do anything with it
 | 
				
			||||||
    if (index <= this->size())  // if it is within our data
 | 
					    if (index <= this->size())  // if it is within our data it is safe to use
 | 
				
			||||||
        return index;
 | 
					        return index;
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
        throw std::invalid_argument("char* not within held data!");
 | 
					        throw std::invalid_argument("char* not within held data!");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include <stddef.h>
 | 
					#include <stdexcept>
 | 
				
			||||||
 | 
					#include <cstring>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,21 +7,30 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This is a demonstration, that the String class and it's components work
 | 
					/* This is a demonstration, that the String class and it's components work
 | 
				
			||||||
 * correctly, basically a non-unit test. */
 | 
					 * correctly, basically a non-unit test. Perfect for usage with valgrind */
 | 
				
			||||||
int main()
 | 
					int main()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (std::is_default_constructible<String>::value)
 | 
					    if (std::is_default_constructible<String>::value)
 | 
				
			||||||
        std::cout << "class String is default constructible" << std::endl;
 | 
					        std::cout << "class String is default constructible" << std::endl;
 | 
				
			||||||
 | 
					    String defaultctor();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (std::is_constructible<String, const char*>::value)
 | 
					    if (std::is_constructible<String, const char*>::value)
 | 
				
			||||||
        std::cout << "class String is constructible from const char*" << std::endl;
 | 
					        std::cout << "class String is constructible from const char*" << std::endl;
 | 
				
			||||||
 | 
					    String constchar("yeeeey");
 | 
				
			||||||
    if (std::is_copy_constructible<String>::value)
 | 
					    if (std::is_copy_constructible<String>::value)
 | 
				
			||||||
        std::cout << "class String is copy constructible" << std::endl;
 | 
					        std::cout << "class String is copy constructible" << std::endl;
 | 
				
			||||||
 | 
					    String copy(constchar);
 | 
				
			||||||
    if (std::is_copy_assignable<String>::value)
 | 
					    if (std::is_copy_assignable<String>::value)
 | 
				
			||||||
        std::cout << "class String is copy assignable" << std::endl;
 | 
					        std::cout << "class String is copy assignable" << std::endl;
 | 
				
			||||||
 | 
					    String othercopy;
 | 
				
			||||||
 | 
					    othercopy = constchar;
 | 
				
			||||||
    if (std::is_move_constructible<String>::value)
 | 
					    if (std::is_move_constructible<String>::value)
 | 
				
			||||||
        std::cout << "class String is move constructible" << std::endl;
 | 
					        std::cout << "class String is move constructible" << std::endl;
 | 
				
			||||||
 | 
					    String moved(std::move(othercopy));
 | 
				
			||||||
    if (std::is_move_assignable<String>::value)
 | 
					    if (std::is_move_assignable<String>::value)
 | 
				
			||||||
        std::cout << "class String is move assignable" << std::endl;
 | 
					        std::cout << "class String is move assignable" << std::endl;
 | 
				
			||||||
 | 
					    String moveassigned;
 | 
				
			||||||
 | 
					    moveassigned = std::move(moved);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    std::cout << std::endl;
 | 
					    std::cout << std::endl;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										3
									
								
								test.cpp
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								test.cpp
									
									
									
									
									
								
							@@ -204,7 +204,8 @@ TEST_P(ResourceSharingStringTest, resourceSharingWorks)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    EXPECT_EQ(str1.c_str(), str2.c_str());
 | 
					    EXPECT_EQ(str1.c_str(), str2.c_str());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
INSTANTIATE_TEST_CASE_P(tests, ResourceSharingStringTest, ::testing::ValuesIn(testvalues3));
 | 
					// this feature is not implemented yet, therefore needs no testing
 | 
				
			||||||
 | 
					//INSTANTIATE_TEST_CASE_P(tests, ResourceSharingStringTest, ::testing::ValuesIn(testvalues3));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Stream tests
 | 
					// Stream tests
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user