Explorar o código

Added String boxing class

- added String boxing class to wrap std::string datatype
- added tests for String boxing class
pcmattulat %!s(int64=4) %!d(string=hai) anos
pai
achega
5174e8eae3
Modificáronse 4 ficheiros con 408 adicións e 2 borrados
  1. 5 2
      CMakeLists.txt
  2. 132 0
      source/boxing/String.cpp
  3. 77 0
      source/boxing/String.hpp
  4. 194 0
      test/cases/boxing/StringTest.cpp

+ 5 - 2
CMakeLists.txt

@@ -45,13 +45,16 @@ set(SOURCE_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/source/boxing/Float.hpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/boxing/Float.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/source/boxing/Double.hpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/source/boxing/Double.cpp)
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/boxing/Double.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/boxing/String.hpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/source/boxing/String.cpp)
 
 set(TEST_FILES
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/boxing/IntegerTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/boxing/BooleanTest.cpp
         ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/boxing/FloatTest.cpp
-        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/boxing/DoubleTest.cpp)
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/boxing/DoubleTest.cpp
+        ${CMAKE_CURRENT_SOURCE_DIR}/test/cases/boxing/StringTest.cpp)
 
 ##########################################################
 # Build

+ 132 - 0
source/boxing/String.cpp

@@ -0,0 +1,132 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-08-14
+ * Changed:         2020-08-14
+ *
+ * */
+
+#include <algorithm>
+#include <utility>
+#include "String.hpp"
+
+ls_std::String::String() : Class("String")
+{}
+
+ls_std::String::String(std::string _value) : Class("String"),
+value(std::move(_value))
+{}
+
+ls_std::String::operator const char*() const {
+  return this->value.c_str();
+}
+
+ls_std::String::operator std::string() const {
+  return this->value;
+}
+
+ls_std::String & ls_std::String::operator=(std::string _value) {
+  this->value = std::move(_value);
+  return *this;
+}
+
+std::string ls_std::String::operator+(String _string) const {
+  return this->value + _string.toString();
+}
+
+std::string ls_std::String::operator+(const std::string& _string) const {
+  return this->value + _string;
+}
+
+std::string ls_std::String::operator+(const char *_string) const {
+  return this->value + _string;
+}
+
+std::string ls_std::String::operator-(int _number) {
+  std::string copy = this->value;
+  return copy.substr(0, copy.size() - _number);;
+}
+
+ls_std::String & ls_std::String::operator+=(String _string) {
+  this->value = this->value + _string.toString();
+  return *this;
+}
+
+ls_std::String & ls_std::String::operator+=(const std::string &_text) {
+  this->value = this->value + _text;
+  return *this;
+}
+
+bool ls_std::String::operator==(String _string) {
+  return this->value == _string.toString();
+}
+
+bool ls_std::String::operator==(const std::string& _value) {
+  return this->value == _value;
+}
+
+bool ls_std::String::operator==(const char *_value) {
+  return this->value == _value;
+}
+
+bool ls_std::String::operator!=(String _string) {
+  return this->value != _string.toString();
+}
+
+bool ls_std::String::operator!=(const std::string& _value) {
+  return this->value != _value;
+}
+
+bool ls_std::String::operator!=(const char *_value) {
+  return this->value != _value;
+}
+
+void ls_std::String::parse(std::string parseText) {
+  this->value = std::move(parseText);
+}
+
+std::string ls_std::String::toString() {
+  return this->value;
+}
+
+bool ls_std::String::contains(const std::string& _text) {
+  return this->value.find(_text) != std::string::npos;
+}
+
+bool ls_std::String::endsWith(const std::string &_text) {
+  return this->value.rfind(_text) == (this->value.size() - _text.size());
+}
+
+bool ls_std::String::equalsIgnoreCase(String _string) {
+  return this->toLowerCase() == _string.toLowerCase();
+}
+
+bool ls_std::String::equalsIgnoreCase(std::string _text) {
+  return this->toLowerCase() == ls_std::String{std::move(_text)}.toLowerCase();
+}
+
+std::string ls_std::String::reverse() {
+  std::string copy = this->value;
+  std::reverse(copy.begin(), copy.end());
+
+  return copy;
+}
+
+bool ls_std::String::startsWith(const std::string &_text) {
+  return this->value.rfind(_text, 0) == 0;
+}
+
+std::string ls_std::String::toLowerCase() {
+  std::string copy = this->value;
+  std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower);
+
+  return copy;
+}
+
+std::string ls_std::String::toUpperCase() {
+  std::string copy = this->value;
+  std::transform(copy.begin(), copy.end(), copy.begin(), ::toupper);
+
+  return copy;
+}

+ 77 - 0
source/boxing/String.hpp

@@ -0,0 +1,77 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-08-14
+ * Changed:         2020-08-14
+ *
+ * */
+
+#ifndef STRING_HPP
+#define STRING_HPP
+
+#include "IBoxing.hpp"
+#include "../base/Class.hpp"
+#include <string>
+
+namespace ls_std {
+  class String : public Class, IBoxing {
+    public:
+
+      String();
+      explicit String(std::string _value);
+      ~String() = default;
+
+      // conversion operator
+
+      operator const char*() const; // do not make explicit!
+      operator std::string() const; // do not make explicit!
+
+      // assignment operators
+
+      String& operator=(std::string _value);
+
+      // arithmetic operators
+
+      std::string operator+(String _string) const;
+      std::string operator+(const std::string& _string) const;
+      std::string operator+(const char* _string) const;
+      std::string operator-(int _number);
+
+      // compound operators
+
+      String& operator+=(String _string);
+      String& operator+=(const std::string& _text);
+
+      // comparison operators
+
+      bool operator==(String _string);
+      bool operator==(const std::string& _value);
+      bool operator==(const char* _value);
+      bool operator!=(String _string);
+      bool operator!=(const std::string& _value);
+      bool operator!=(const char* _value);
+
+      // implementation
+
+      void parse(std::string parseText) override;
+      std::string toString() override;
+
+      // additional functionality
+
+      bool contains(const std::string& _text);
+      bool endsWith(const std::string& _text);
+      bool equalsIgnoreCase(String _string);
+      bool equalsIgnoreCase(std::string _text);
+      std::string reverse();
+      bool startsWith(const std::string& _text);
+      std::string toLowerCase();
+      std::string toUpperCase();
+
+    private:
+
+      std::string value {};
+  };
+}
+
+#endif

+ 194 - 0
test/cases/boxing/StringTest.cpp

@@ -0,0 +1,194 @@
+/*
+ * Author:          Patrick-Christopher Mattulat
+ * Company:         Lynar Studios
+ * E-Mail:          webmaster@lynarstudios.com
+ * Created:         2020-08-14
+ * Changed:         2020-08-14
+ *
+ * */
+
+#include <gtest/gtest.h>
+#include "../../../source/boxing/String.hpp"
+
+namespace {
+  class StringTest : public ::testing::Test {
+    protected:
+
+      StringTest() = default;
+      ~StringTest() override = default;
+
+      void SetUp() override {}
+      void TearDown() override {}
+  };
+
+  // assignment operators
+
+  TEST_F(StringTest, operatorAssignment)
+  {
+    ls_std::String text {};
+    text = "Hi!";
+
+    ASSERT_STREQ("Hi!", text.toString().c_str());
+  }
+
+  // arithmetic operators
+
+  TEST_F(StringTest, operatorAdd)
+  {
+    ls_std::String text {"Hello! "};
+    ls_std::String end {"How are you? "};
+    text = text + end + "I'm good by the way!";
+
+    ASSERT_STREQ("Hello! How are you? I'm good by the way!", text.toString().c_str());
+  }
+
+  TEST_F(StringTest, operatorHyphen)
+  {
+    ls_std::String text {"abcdefghij"};
+    text = text - 5;
+
+    ASSERT_STREQ("abcde", text.toString().c_str());
+  }
+
+  // compound operators
+
+  TEST_F(StringTest, operatorAddEqual)
+  {
+    ls_std::String text {};
+    ls_std::String hello {"Hi! "};
+    ASSERT_STREQ("", text.toString().c_str());
+
+    text += hello;
+    ASSERT_STREQ("Hi! ", text.toString().c_str());
+
+    text += "Bye!";
+    ASSERT_STREQ("Hi! Bye!", text.toString().c_str());
+  }
+
+  // comparison operators
+
+  TEST_F(StringTest, operatorEqual)
+  {
+    ls_std::String text {"Hi!"};
+    ls_std::String hello {"Hi!"};
+
+    ASSERT_TRUE(text == hello);
+    ASSERT_TRUE(hello == text);
+    ASSERT_TRUE(hello == std::string("Hi!"));
+    ASSERT_TRUE(hello == "Hi!");
+  }
+
+  TEST_F(StringTest, operatorNotEqual)
+  {
+    ls_std::String text {"Hi!"};
+    ls_std::String hello {"Hello!"};
+
+    ASSERT_TRUE(text != hello);
+    ASSERT_TRUE(hello != text);
+    ASSERT_TRUE(text != std::string("Hello!"));
+    ASSERT_TRUE(text != "Hello!");
+  }
+
+  // implementation
+
+  TEST_F(StringTest, parse)
+  {
+    ls_std::String text {};
+    text.parse("Hello!");
+
+    ASSERT_STREQ("Hello!", text.toString().c_str());
+  }
+
+  TEST_F(StringTest, toString)
+  {
+    ls_std::String text {"Hello!"};
+
+    ASSERT_STREQ("Hello!", text.toString().c_str());
+  }
+
+  // additional functionality
+
+  TEST_F(StringTest, contains)
+  {
+    ls_std::String text {};
+    text = "Hey, I'm searching for the keyword 'cake'!";
+
+    ASSERT_TRUE(text.contains("cake"));
+  }
+
+  TEST_F(StringTest, containsNegative)
+  {
+    ls_std::String text {};
+    text = "Hey, I'm searching for the keyword 'cake'!";
+
+    ASSERT_FALSE(text.contains("butter"));
+  }
+
+  TEST_F(StringTest, endsWith)
+  {
+    ls_std::String text {};
+    text = "abcdef";
+
+    ASSERT_TRUE(text.endsWith("ef"));
+  }
+
+  TEST_F(StringTest, equalsIgnoreCase)
+  {
+    ls_std::String text {"Hello!"};
+    ls_std::String hello {"HeLLo!"};
+
+    ASSERT_TRUE(text.equalsIgnoreCase(hello));
+    ASSERT_TRUE(text.equalsIgnoreCase("HeLLO!"));
+  }
+
+  TEST_F(StringTest, endsWithNegative)
+  {
+    ls_std::String text {};
+    text = "abcdef";
+
+    ASSERT_FALSE(text.endsWith("efg"));
+  }
+
+  TEST_F(StringTest, reverse)
+  {
+    ls_std::String text {};
+    text = "abcdef";
+
+    ASSERT_STREQ("fedcba", text.reverse().c_str());
+    ASSERT_STREQ("abcdef", text);
+  }
+
+  TEST_F(StringTest, startsWith)
+  {
+    ls_std::String text {};
+    text = "abcdef";
+
+    ASSERT_TRUE(text.startsWith("abc"));
+  }
+
+  TEST_F(StringTest, startsWithNegative)
+  {
+    ls_std::String text {};
+    text = "abcdef";
+
+    ASSERT_FALSE(text.startsWith("bc"));
+  }
+
+  TEST_F(StringTest, toLowerCase)
+  {
+    ls_std::String text {};
+    text = "aBCdeFgHIJKLmn";
+
+    ASSERT_STREQ("abcdefghijklmn", text.toLowerCase().c_str());
+    ASSERT_STREQ("aBCdeFgHIJKLmn", text);
+  }
+
+  TEST_F(StringTest, toUpperCase)
+  {
+    ls_std::String text {};
+    text = "aBCdeFgHIJKLmn";
+
+    ASSERT_STREQ("ABCDEFGHIJKLMN", text.toUpperCase().c_str());
+    ASSERT_STREQ("aBCdeFgHIJKLmn", text);
+  }
+}