Repository: nasa/fprime (language: python)

Issue:
Format cpp and hpp files in Fw/Types
Reformatting improves the readability of the code. If we do it module by module, the impact should be minimal. `Fw/Types` seems like a logical place to start. 

If someone is developing `Fw/Types` with the old formatting, that person just needs to reformat the code being developed before diffing or making a PR against the new formatting. The catch is that because of the idiosyncratic use of the preprocessor symbols `PRIVATE` and `PROTECTED` in F Prime, you can't just run clang-format. Here is the script that I use to work around this issue:
```bash
#!/bin/sh -e

# ----------------------------------------------------------------------
# fprime-format-cpp
# Use clang-format to format C++ files for F Prime
# ----------------------------------------------------------------------

format()
{
  sed -e 's;^[ \t]*PROTECTED[ \t]*:;protected: // fprime-format-cpp;' -e 's;^[ \t]*PRIVATE[ \t]*:;private: // fprime-format-cpp;' | \
  clang-format --style=file | \
  sed -e 's;protected: *// fprime-format-cpp;PROTECTED:;' -e 's;private: *// fprime-format-cpp;PRIVATE:;'
}

if test $# -eq 0
then
  format
else
  for file in "$@"
  do
    cp "$file" "$file.bak"
    format < "$file.bak" > "$file"
  done
fi
```
I call this tool `fprime-format-cpp`. When run anywhere in the F Prime repo, it picks up the formatting configuration stored in `[fprime-root]/.clang-format`, so the formatting should be consistent for all users. It's designed so that you can run it inside a text editor (e.g., vi or VS Code) or in batch mode on the command line.

Here is how you can reformat all the files in a build module:
```bash
% fprime-format-cpp `find . -name '*.hpp' -or -name '*.cpp'`
```

I recommend that we put `fprime-format-cpp`, or something like it, into the repo so users can use it to format their code.
Format cpp and hpp files in Fw/Types
Reformatting improves the readability of the code. If we do it module by module, the impact should be minimal. `Fw/Types` seems like a logical place to start. 

If someone is developing `Fw/Types` with the old formatting, that person just needs to reformat the code being developed before diffing or making a PR against the new formatting. The catch is that because of the idiosyncratic use of the preprocessor symbols `PRIVATE` and `PROTECTED` in F Prime, you can't just run clang-format. Here is the script that I use to work around this issue:
```bash
#!/bin/sh -e

# ----------------------------------------------------------------------
# fprime-format-cpp
# Use clang-format to format C++ files for F Prime
# ----------------------------------------------------------------------

format()
{
  sed -e 's;^[ \t]*PROTECTED[ \t]*:;protected: // fprime-format-cpp;' -e 's;^[ \t]*PRIVATE[ \t]*:;private: // fprime-format-cpp;' | \
  clang-format --style=file | \
  sed -e 's;protected: *// fprime-format-cpp;PROTECTED:;' -e 's;private: *// fprime-format-cpp;PRIVATE:;'
}

if test $# -eq 0
then
  format
else
  for file in "$@"
  do
    cp "$file" "$file.bak"
    format < "$file.bak" > "$file"
  done
fi
```
I call this tool `fprime-format-cpp`. When run anywhere in the F Prime repo, it picks up the formatting configuration stored in `[fprime-root]/.clang-format`, so the formatting should be consistent for all users. It's designed so that you can run it inside a text editor (e.g., vi or VS Code) or in batch mode on the command line.

Here is how you can reformat all the files in a build module:
```bash
% fprime-format-cpp `find . -name '*.hpp' -or -name '*.cpp'`
```

I recommend that we put `fprime-format-cpp`, or something like it, into the repo so users can use it to format their code.


Discussion / hints:

Fix patch:
diff --git a/Fw/Cmd/CMakeLists.txt b/Fw/Cmd/CMakeLists.txt
index f87144d8cb..b4bfeda815 100644
--- a/Fw/Cmd/CMakeLists.txt
+++ b/Fw/Cmd/CMakeLists.txt
@@ -12,6 +12,5 @@ set(SOURCE_FILES
   "${CMAKE_CURRENT_LIST_DIR}/CmdArgBuffer.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/CmdPacket.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/Cmd.fpp"
-  "${CMAKE_CURRENT_LIST_DIR}/CmdString.cpp"
 )
 register_fprime_module()
diff --git a/Fw/Cmd/CmdString.cpp b/Fw/Cmd/CmdString.cpp
deleted file mode 100644
index c090e30cf9..0000000000
--- a/Fw/Cmd/CmdString.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <Fw/Cmd/CmdString.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Fw {
-
-    CmdStringArg::CmdStringArg(const char* src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-    }
-
-    CmdStringArg::CmdStringArg(const StringBase& src) : StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    CmdStringArg::CmdStringArg(const CmdStringArg& src) : StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    CmdStringArg::CmdStringArg() : StringBase() {
-        this->m_buf[0] = 0;
-    }
-
-    CmdStringArg& CmdStringArg::operator=(const CmdStringArg& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    CmdStringArg& CmdStringArg::operator=(const StringBase& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    CmdStringArg& CmdStringArg::operator=(const char* other) {
-        (void) Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-        return *this;
-    }
-
-    CmdStringArg::~CmdStringArg() {
-    }
-
-    const char* CmdStringArg::toChar() const {
-        return this->m_buf;
-    }
-
-    NATIVE_UINT_TYPE CmdStringArg::getCapacity() const {
-        return FW_CMD_STRING_MAX_SIZE;
-    }
-}
diff --git a/Fw/Cmd/CmdString.hpp b/Fw/Cmd/CmdString.hpp
index 4e3a9dfe7d..8b8480c34b 100644
--- a/Fw/Cmd/CmdString.hpp
+++ b/Fw/Cmd/CmdString.hpp
@@ -1,37 +1,59 @@
-#ifndef FW_CMD_STRING_TYPE_HPP
-#define FW_CMD_STRING_TYPE_HPP
+// ======================================================================
+// @file   CmdString.hpp
+// @author F Prime
+// @brief  A string sized for a command argument
+// ======================================================================
+
+#ifndef FW_CMD_STRING_HPP
+#define FW_CMD_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Types/StringType.hpp>
-#include <Fw/Cfg/SerIds.hpp>
+
+#include "Fw/Cfg/SerIds.hpp"
+#include "Fw/Types/StringBase.hpp"
 
 namespace Fw {
 
-    class CmdStringArg : public Fw::StringBase {
-        public:
+class CmdStringArg final : public StringBase {
+  public:
+    enum {
+        SERIALIZED_TYPE_ID = FW_TYPEID_CMD_STR,
+        STRING_SIZE = FW_CMD_STRING_MAX_SIZE,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
+    };
 
-            enum {
-                SERIALIZED_TYPE_ID = FW_TYPEID_CMD_STR,
-                SERIALIZED_SIZE = FW_CMD_STRING_MAX_SIZE + sizeof(FwBuffSizeType)
-            };
+    CmdStringArg() : StringBase() { *this = ""; }
 
-            CmdStringArg(const char* src);
-            CmdStringArg(const StringBase& src);
-            CmdStringArg(const CmdStringArg& src);
-            CmdStringArg();
-            CmdStringArg& operator=(const CmdStringArg& other);
-            CmdStringArg& operator=(const StringBase& other);
-            CmdStringArg& operator=(const char* other);
-            ~CmdStringArg();
+    CmdStringArg(const CmdStringArg& src) : StringBase() { *this = src; }
 
-            const char* toChar() const;
-            NATIVE_UINT_TYPE getCapacity() const ; //!< return buffer size
+    CmdStringArg(const StringBase& src) : StringBase() { *this = src; }
 
-        private:
+    CmdStringArg(const char* src) : StringBase() { *this = src; }
 
-            char m_buf[FW_CMD_STRING_MAX_SIZE];
-    };
+    ~CmdStringArg() {}
+
+    CmdStringArg& operator=(const CmdStringArg& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    CmdStringArg& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    CmdStringArg& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
+
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
 
-}
+  private:
+    char m_buf[CmdStringArg::STRING_SIZE];
+};
+}  // namespace Fw
 
 #endif
diff --git a/Fw/Log/CMakeLists.txt b/Fw/Log/CMakeLists.txt
index dcd364dd95..a63d4ead3f 100644
--- a/Fw/Log/CMakeLists.txt
+++ b/Fw/Log/CMakeLists.txt
@@ -12,8 +12,6 @@ set(SOURCE_FILES
   "${CMAKE_CURRENT_LIST_DIR}/LogBuffer.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/LogPacket.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/Log.fpp"
-  "${CMAKE_CURRENT_LIST_DIR}/LogString.cpp"
-  "${CMAKE_CURRENT_LIST_DIR}/TextLogString.cpp"
 
 )
 register_fprime_module()
diff --git a/Fw/Log/LogString.cpp b/Fw/Log/LogString.cpp
deleted file mode 100644
index 67c44e8277..0000000000
--- a/Fw/Log/LogString.cpp
+++ /dev/null
@@ -1,101 +0,0 @@
-#include <Fw/Log/LogString.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Fw {
-
-    LogStringArg::LogStringArg(const char* src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-    }
-
-    LogStringArg::LogStringArg(const StringBase& src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    LogStringArg::LogStringArg(const LogStringArg& src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    LogStringArg::LogStringArg()
-            : StringBase() {
-        this->m_buf[0] = 0;
-    }
-
-    LogStringArg& LogStringArg::operator=(const LogStringArg& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    LogStringArg& LogStringArg::operator=(const StringBase& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    LogStringArg& LogStringArg::operator=(const char* other) {
-        (void) Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-        return *this;
-    }
-
-    LogStringArg::~LogStringArg() {
-    }
-
-    const char* LogStringArg::toChar() const {
-        return this->m_buf;
-    }
-
-    NATIVE_UINT_TYPE LogStringArg::getCapacity() const {
-        return FW_LOG_STRING_MAX_SIZE;
-    }
-
-    SerializeStatus LogStringArg::serialize(SerializeBufferBase& buffer) const {
-        return this->serialize(buffer, this->length());
-    }
-
-    SerializeStatus LogStringArg::serialize(SerializeBufferBase& buffer, NATIVE_UINT_TYPE maxLength) const {
-        NATIVE_INT_TYPE len = FW_MIN(maxLength,this->length());
-#if FW_AMPCS_COMPATIBLE
-        // serialize 8-bit size with null terminator removed
-        U8 strSize = len - 1;
-        SerializeStatus stat = buffer.serialize(strSize);
-        if (stat != FW_SERIALIZE_OK) {
-            return stat;
-        }
-        return buffer.serialize(reinterpret_cast<const U8*>(this->toChar()),strSize, true);
-#else
-        return buffer.serialize(reinterpret_cast<const U8*>(this->toChar()),len);
-#endif
-    }
-
-    SerializeStatus LogStringArg::deserialize(SerializeBufferBase& buffer) {
-        NATIVE_UINT_TYPE maxSize = this->getCapacity() - 1;
-        CHAR* raw = const_cast<CHAR*>(this->toChar());
-
-#if FW_AMPCS_COMPATIBLE
-        // AMPCS encodes 8-bit string size
-        U8 strSize;
-        SerializeStatus stat = buffer.deserialize(strSize);
-        if (stat != FW_SERIALIZE_OK) {
-            return stat;
-        }
-        strSize = FW_MIN(maxSize,strSize);
-        stat = buffer.deserialize(reinterpret_cast<U8*>(raw),strSize,true);
-        // AMPCS Strings not null terminated
-        if(strSize < maxSize) {
-            raw[strSize] = 0;
-        }
-#else
-        SerializeStatus stat = buffer.deserialize(reinterpret_cast<U8*>(raw),maxSize);
-#endif
-
-        // Null terminate deserialized string
-        raw[maxSize] = 0;
-        return stat;
-    }
-}
diff --git a/Fw/Log/LogString.hpp b/Fw/Log/LogString.hpp
index 533e2ddf24..c348c2fbc3 100644
--- a/Fw/Log/LogString.hpp
+++ b/Fw/Log/LogString.hpp
@@ -1,41 +1,59 @@
-#ifndef FW_LOG_STRING_TYPE_HPP
-#define FW_LOG_STRING_TYPE_HPP
+// ======================================================================
+// @file   LogString.hpp
+// @author F Prime
+// @brief  A string sized for an event log entry
+// ======================================================================
+
+#ifndef FW_LOG_STRING_HPP
+#define FW_LOG_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Types/StringType.hpp>
-#include <Fw/Cfg/SerIds.hpp>
+
+#include "Fw/Cfg/SerIds.hpp"
+#include "Fw/Types/StringBase.hpp"
 
 namespace Fw {
 
-    class LogStringArg : public Fw::StringBase {
-        public:
+class LogStringArg final : public StringBase {
+  public:
+    enum {
+        SERIALIZED_TYPE_ID = FW_TYPEID_LOG_STR,
+        STRING_SIZE = FW_LOG_STRING_MAX_SIZE,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
+    };
 
-            enum {
-                SERIALIZED_TYPE_ID = FW_TYPEID_LOG_STR,
-                SERIALIZED_SIZE = FW_LOG_STRING_MAX_SIZE + sizeof(FwBuffSizeType) // size of buffer + storage of two size words
-            };
+    LogStringArg() : StringBase() { *this = ""; }
 
-            LogStringArg();
-            LogStringArg(const LogStringArg& src); //!< LogStringArg string constructor
-            LogStringArg(const StringBase& src); //!< other string constructor
-            LogStringArg(const char* src); //!< char* source constructor
-            LogStringArg& operator=(const LogStringArg& other); //!< assignment operator
-            LogStringArg& operator=(const StringBase& other); //!< other string assignment operator
-            LogStringArg& operator=(const char* other); //!< char* assignment operator
-            ~LogStringArg();
+    LogStringArg(const LogStringArg& src) : StringBase() { *this = src; }
 
-            const char* toChar() const override;
-            NATIVE_UINT_TYPE getCapacity() const override;
+    LogStringArg(const StringBase& src) : StringBase() { *this = src; }
 
-            SerializeStatus serialize(SerializeBufferBase& buffer) const override; //!< serialization function
-            SerializeStatus serialize(SerializeBufferBase& buffer, NATIVE_UINT_TYPE maxLen) const override; //!< serialization function
-            SerializeStatus deserialize(SerializeBufferBase& buffer) override; //!< deserialization function
+    LogStringArg(const char* src) : StringBase() { *this = src; }
 
-        private:
+    ~LogStringArg() {}
 
-            char m_buf[FW_LOG_STRING_MAX_SIZE];
-    };
+    LogStringArg& operator=(const LogStringArg& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    LogStringArg& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    LogStringArg& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
+
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
 
-}
+  private:
+    char m_buf[LogStringArg::STRING_SIZE];
+};
+}  // namespace Fw
 
 #endif
diff --git a/Fw/Log/TextLogString.cpp b/Fw/Log/TextLogString.cpp
deleted file mode 100644
index fb2cd3faa8..0000000000
--- a/Fw/Log/TextLogString.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <Fw/Log/TextLogString.hpp>
-#include <Fw/Types/StringUtils.hpp>
-namespace Fw {
-
-    TextLogString::TextLogString(const char* src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-    }
-
-    TextLogString::TextLogString(const StringBase& src): StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    TextLogString::TextLogString(const TextLogString& src): StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    TextLogString::TextLogString(): StringBase()  {
-        this->m_buf[0] = 0;
-    }
-
-    TextLogString& TextLogString::operator=(const TextLogString& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    TextLogString& TextLogString::operator=(const StringBase& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    TextLogString& TextLogString::operator=(const char* other) {
-        (void) Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-        return *this;
-    }
-
-    TextLogString::~TextLogString() {
-    }
-
-    const char* TextLogString::toChar() const {
-        return this->m_buf;
-    }
-
-    NATIVE_UINT_TYPE TextLogString::getCapacity() const {
-        return FW_LOG_TEXT_BUFFER_SIZE;
-    }
-}
diff --git a/Fw/Log/TextLogString.hpp b/Fw/Log/TextLogString.hpp
index e25f7273f2..70b08281c8 100644
--- a/Fw/Log/TextLogString.hpp
+++ b/Fw/Log/TextLogString.hpp
@@ -1,37 +1,59 @@
-#ifndef FW_TEXT_LOG_STRING_TYPE_HPP
-#define FW_TEXT_LOG_STRING_TYPE_HPP
+// ======================================================================
+// @file   TextLogString.hpp
+// @author F Prime
+// @brief  A string sized for an event log entry
+// ======================================================================
+
+#ifndef FW_TEXT_LOG_STRING_HPP
+#define FW_TEXT_LOG_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Types/StringType.hpp>
-#include <Fw/Cfg/SerIds.hpp>
+
+#include "Fw/Cfg/SerIds.hpp"
+#include "Fw/Types/StringBase.hpp"
 
 namespace Fw {
 
-    class TextLogString : public Fw::StringBase {
-        public:
+class TextLogString final : public StringBase {
+  public:
+    enum {
+        SERIALIZED_TYPE_ID = FW_TYPEID_LOG_STR,
+        STRING_SIZE = FW_LOG_TEXT_BUFFER_SIZE,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
+    };
 
-            enum {
-                SERIALIZED_TYPE_ID = FW_TYPEID_LOG_STR,
-                SERIALIZED_SIZE = FW_LOG_TEXT_BUFFER_SIZE + sizeof(FwBuffSizeType) // size of buffer + storage of two size words
-            };
+    TextLogString() : StringBase() { *this = ""; }
 
-            TextLogString(const char* src);
-            TextLogString(const StringBase& src);
-            TextLogString(const TextLogString& src);
-            TextLogString();
-            TextLogString& operator=(const TextLogString& other);
-            TextLogString& operator=(const StringBase& other);
-            TextLogString& operator=(const char* other);
-            ~TextLogString();
+    TextLogString(const TextLogString& src) : StringBase() { *this = src; }
 
-            const char* toChar() const;
-            NATIVE_UINT_TYPE getCapacity() const ;
+    TextLogString(const StringBase& src) : StringBase() { *this = src; }
 
-        private:
+    TextLogString(const char* src) : StringBase() { *this = src; }
 
-            char m_buf[FW_LOG_TEXT_BUFFER_SIZE];
-    };
+    ~TextLogString() {}
+
+    TextLogString& operator=(const TextLogString& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    TextLogString& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    TextLogString& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
+
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
 
-}
+  private:
+    char m_buf[TextLogString::STRING_SIZE];
+};
+}  // namespace Fw
 
 #endif
diff --git a/Fw/Prm/CMakeLists.txt b/Fw/Prm/CMakeLists.txt
index a468b38f91..7b48e04755 100644
--- a/Fw/Prm/CMakeLists.txt
+++ b/Fw/Prm/CMakeLists.txt
@@ -8,7 +8,6 @@
 set(SOURCE_FILES
   "${CMAKE_CURRENT_LIST_DIR}/Prm.fpp"
   "${CMAKE_CURRENT_LIST_DIR}/PrmBuffer.cpp"
-  "${CMAKE_CURRENT_LIST_DIR}/PrmString.cpp"
 )
 
 register_fprime_module()
diff --git a/Fw/Prm/PrmString.cpp b/Fw/Prm/PrmString.cpp
deleted file mode 100644
index f7569fa15b..0000000000
--- a/Fw/Prm/PrmString.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <Fw/Prm/PrmString.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Fw {
-
-    ParamString::ParamString(const char* src) : StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-    }
-
-    ParamString::ParamString(const StringBase& src) : StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    ParamString::ParamString(const ParamString& src) : StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    ParamString::ParamString() : StringBase()  {
-        this->m_buf[0] = 0;
-    }
-
-    ParamString& ParamString::operator=(const ParamString& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    ParamString& ParamString::operator=(const StringBase& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    ParamString& ParamString::operator=(const char* other) {
-        (void) Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-        return *this;
-    }
-
-    ParamString::~ParamString() {
-    }
-
-    const char* ParamString::toChar() const {
-        return this->m_buf;
-    }
-
-    NATIVE_UINT_TYPE ParamString::getCapacity() const {
-        return FW_PARAM_STRING_MAX_SIZE;
-    }
-}
diff --git a/Fw/Prm/PrmString.hpp b/Fw/Prm/PrmString.hpp
index 8972c49a7a..3220500568 100644
--- a/Fw/Prm/PrmString.hpp
+++ b/Fw/Prm/PrmString.hpp
@@ -1,37 +1,59 @@
-#ifndef FW_PRM_STRING_TYPE_HPP
-#define FW_PRM_STRING_TYPE_HPP
+// ======================================================================
+// @file   PrmString.hpp
+// @author F Prime
+// @brief  A string sized for a parameter
+// ======================================================================
+
+#ifndef FW_PARAM_STRING_HPP
+#define FW_PARAM_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Types/StringType.hpp>
-#include <Fw/Cfg/SerIds.hpp>
+
+#include "Fw/Cfg/SerIds.hpp"
+#include "Fw/Types/StringBase.hpp"
 
 namespace Fw {
 
-    class ParamString : public Fw::StringBase {
-        public:
+class ParamString : public StringBase {
+  public:
+    enum {
+        SERIALIZED_TYPE_ID = FW_TYPEID_PRM_STR,
+        STRING_SIZE = FW_PARAM_STRING_MAX_SIZE,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
+    };
 
-            enum {
-                SERIALIZED_TYPE_ID = FW_TYPEID_PRM_STR,
-                SERIALIZED_SIZE = FW_PARAM_STRING_MAX_SIZE + sizeof(FwBuffSizeType) // size of buffer + storage of two size words
-            };
+    ParamString() : StringBase() { *this = ""; }
 
-            ParamString(const char* src);
-            ParamString(const StringBase& src);
-            ParamString(const ParamString& src);
-            ParamString();
-            ParamString& operator=(const ParamString& other);
-            ParamString& operator=(const StringBase& other);
-            ParamString& operator=(const char* other);
-            ~ParamString();
+    ParamString(const ParamString& src) : StringBase() { *this = src; }
 
-            const char* toChar() const;
-            NATIVE_UINT_TYPE getCapacity() const;
+    ParamString(const StringBase& src) : StringBase() { *this = src; }
 
-        private:
+    ParamString(const char* src) : StringBase() { *this = src; }
 
-            char m_buf[FW_PARAM_STRING_MAX_SIZE];
-    };
+    ~ParamString() {}
+
+    ParamString& operator=(const ParamString& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    ParamString& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    ParamString& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
+
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
 
-}
+  private:
+    char m_buf[ParamString::STRING_SIZE];
+};
+}  // namespace Fw
 
 #endif
diff --git a/Fw/Test/CMakeLists.txt b/Fw/Test/CMakeLists.txt
index dff1941472..29907b8841 100644
--- a/Fw/Test/CMakeLists.txt
+++ b/Fw/Test/CMakeLists.txt
@@ -6,7 +6,6 @@
 #
 ####
 set(SOURCE_FILES
-  "${CMAKE_CURRENT_LIST_DIR}/String.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/UnitTestAssert.cpp"
 )
 set(MOD_DEPS Fw_Types)
diff --git a/Fw/Test/String.cpp b/Fw/Test/String.cpp
deleted file mode 100644
index d4a7c5c21f..0000000000
--- a/Fw/Test/String.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <Fw/Test/String.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Test {
-
-    String::String(const char* src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-    }
-
-    String::String(const StringBase& src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    String::String(const String& src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    String::String() : StringBase() {
-        this->m_buf[0] = 0;
-    }
-
-    String& String::operator=(const String& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    String& String::operator=(const StringBase& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    String& String::operator=(const char* other) {
-        (void) Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-        return *this;
-    }
-
-    String::~String() {
-    }
-
-    const char* String::toChar() const {
-        return this->m_buf;
-    }
-
-    NATIVE_UINT_TYPE String::getCapacity() const {
-        return STRING_SIZE;
-    }
-}
diff --git a/Fw/Test/String.hpp b/Fw/Test/String.hpp
index ddc525bcd2..0b08c06d57 100644
--- a/Fw/Test/String.hpp
+++ b/Fw/Test/String.hpp
@@ -1,37 +1,56 @@
-#ifndef TEST_STRING_TYPE_HPP
-#define TEST_STRING_TYPE_HPP
+// ======================================================================
+// @file   Test/String.hpp
+// @author F Prime
+// @brief  A longer string for testing
+// ======================================================================
+
+#ifndef FW_TEST_STRING_HPP
+#define FW_TEST_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Types/StringType.hpp>
-#include <Fw/Cfg/SerIds.hpp>
+
+#include "Fw/Cfg/SerIds.hpp"
+#include "Fw/Types/StringBase.hpp"
 
 namespace Test {
 
-    //! A longer string for testing
-    class String : public Fw::StringBase {
-        public:
+class String : public Fw::StringBase {
+  public:
+    enum {
+        STRING_SIZE = 256,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
+    };
 
-            enum {
-                STRING_SIZE = 256, //!< Storage for string
-                SERIALIZED_SIZE = STRING_SIZE + sizeof(FwBuffSizeType) //!< Serialized size is size of buffer + size field
-            };
+    String() : StringBase() { *this = ""; }
 
-            String(const char* src); //!< char* source constructor
-            String(const StringBase& src); //!< other string constructor
-            String(const String& src); //!< String string constructor
-            String(); //!< default constructor
-            String& operator=(const String& other); //!< assignment operator
-            String& operator=(const StringBase& other); //!< other string assignment operator
-            String& operator=(const char* other); //!< char* assignment operator
-            ~String(); //!< destructor
+    String(const String& src) : StringBase() { *this = src; }
 
-            const char* toChar() const; //!< gets char buffer
-            NATIVE_UINT_TYPE getCapacity() const ; //!< return buffer size
+    String(const StringBase& src) : StringBase() { *this = src; }
 
-        private:
+    String(const char* src) : StringBase() { *this = src; }
 
-            char m_buf[STRING_SIZE]; //!< storage for string data
-    };
-}
+    String& operator=(const String& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    String& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    String& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
+
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
+
+  private:
+    char m_buf[String::STRING_SIZE];
+};
+}  // namespace Fw
 
 #endif
diff --git a/Fw/Tlm/CMakeLists.txt b/Fw/Tlm/CMakeLists.txt
index c05d3a179d..92947dcce7 100644
--- a/Fw/Tlm/CMakeLists.txt
+++ b/Fw/Tlm/CMakeLists.txt
@@ -12,7 +12,6 @@ set(SOURCE_FILES
   "${CMAKE_CURRENT_LIST_DIR}/Tlm.fpp"
   "${CMAKE_CURRENT_LIST_DIR}/TlmBuffer.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/TlmPacket.cpp"
-  "${CMAKE_CURRENT_LIST_DIR}/TlmString.cpp"
 )
 register_fprime_module()
 ### UTs ###
diff --git a/Fw/Tlm/TlmString.cpp b/Fw/Tlm/TlmString.cpp
deleted file mode 100644
index 7e3307c335..0000000000
--- a/Fw/Tlm/TlmString.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include <Fw/Tlm/TlmString.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Fw {
-
-    TlmString::TlmString(const char* src) :  StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-    }
-
-    TlmString::TlmString(const StringBase& src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    TlmString::TlmString(const TlmString& src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    TlmString::TlmString() : StringBase() {
-        this->m_buf[0] = 0;
-    }
-
-    TlmString& TlmString::operator=(const TlmString& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    TlmString& TlmString::operator=(const StringBase& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    TlmString& TlmString::operator=(const char* other) {
-        (void) Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-        return *this;
-    }
-
-    TlmString::~TlmString() {
-    }
-
-    const char* TlmString::toChar() const {
-        return this->m_buf;
-    }
-
-    NATIVE_UINT_TYPE TlmString::getCapacity() const {
-        return FW_TLM_STRING_MAX_SIZE;
-    }
-
-    SerializeStatus TlmString::serialize(SerializeBufferBase& buffer) const {
-        return this->serialize(buffer, this->length());
-    }
-
-    SerializeStatus TlmString::serialize(SerializeBufferBase& buffer, NATIVE_UINT_TYPE maxLength) const {
-        NATIVE_INT_TYPE len = FW_MIN(maxLength,this->length());
-#if FW_AMPCS_COMPATIBLE
-        // serialize 8-bit size with null terminator removed
-        U8 strSize = len - 1;
-        SerializeStatus stat = buffer.serialize(strSize);
-        if (stat != FW_SERIALIZE_OK) {
-            return stat;
-        }
-        return buffer.serialize(reinterpret_cast<const U8*>(this->toChar()),strSize, true);
-#else
-        return buffer.serialize(reinterpret_cast<const U8*>(this->toChar()),len);
-#endif
-    }
-
-    SerializeStatus TlmString::deserialize(SerializeBufferBase& buffer) {
-        NATIVE_UINT_TYPE maxSize = this->getCapacity() - 1;
-        CHAR* raw = const_cast<CHAR*>(this->toChar());
-
-#if FW_AMPCS_COMPATIBLE
-        // AMPCS encodes 8-bit string size
-        U8 strSize;
-        SerializeStatus stat = buffer.deserialize(strSize);
-        if (stat != FW_SERIALIZE_OK) {
-            return stat;
-        }
-        strSize = FW_MIN(maxSize,strSize);
-        stat = buffer.deserialize(reinterpret_cast<U8*>(raw),strSize,true);
-        // AMPCS Strings not null terminated
-        if(strSize < maxSize) {
-            raw[strSize] = 0;
-        }
-#else
-        SerializeStatus stat = buffer.deserialize(reinterpret_cast<U8*>(raw),maxSize);
-#endif
-
-        // Null terminate deserialized string
-        raw[maxSize] = 0;
-        return stat;
-    }
-}
diff --git a/Fw/Tlm/TlmString.hpp b/Fw/Tlm/TlmString.hpp
index e9a1a988b8..b5d791fc17 100644
--- a/Fw/Tlm/TlmString.hpp
+++ b/Fw/Tlm/TlmString.hpp
@@ -1,39 +1,59 @@
-#ifndef FW_TLM_STRING_TYPE_HPP
-#define FW_TLM_STRING_TYPE_HPP
+// ======================================================================
+// @file   TlmString.hpp
+// @author F Prime
+// @brief  A string sized for a telemetry channel
+// ======================================================================
+
+#ifndef FW_TLM_STRING_HPP
+#define FW_TLM_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Types/StringType.hpp>
-#include <Fw/Cfg/SerIds.hpp>
+
+#include "Fw/Cfg/SerIds.hpp"
+#include "Fw/Types/StringBase.hpp"
 
 namespace Fw {
 
-    class TlmString : public Fw::StringBase {
-        public:
+class TlmString final : public StringBase {
+  public:
+    enum {
+        SERIALIZED_TYPE_ID = FW_TYPEID_TLM_STR,
+        STRING_SIZE = FW_TLM_STRING_MAX_SIZE,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
+    };
 
-            enum {
-                SERIALIZED_TYPE_ID = FW_TYPEID_TLM_STR,
-                SERIALIZED_SIZE = FW_TLM_STRING_MAX_SIZE + sizeof(FwBuffSizeType) // size of buffer + storage of size word
-            };
+    TlmString() : StringBase() { *this = ""; }
 
-            TlmString();
-            TlmString(const TlmString& src); //!< TlmString string constructor
-            TlmString(const StringBase& src); //!< other string constructor
-            TlmString(const char* src); //!< char* source constructor
-            TlmString& operator=(const TlmString& other); //!< assignment operator
-            TlmString& operator=(const StringBase& other); //!< other string assignment operator
-            TlmString& operator=(const char* other); //!< char* assignment operator
-            ~TlmString();
+    TlmString(const TlmString& src) : StringBase() { *this = src; }
 
-            const char* toChar() const override;
-            NATIVE_UINT_TYPE getCapacity() const override;
+    TlmString(const StringBase& src) : StringBase() { *this = src; }
 
-            SerializeStatus serialize(SerializeBufferBase& buffer) const override; //!< serialization function
-            SerializeStatus serialize(SerializeBufferBase& buffer, NATIVE_UINT_TYPE maxLen) const override; //!< serialization function
-            SerializeStatus deserialize(SerializeBufferBase& buffer) override; //!< deserialization function
+    TlmString(const char* src) : StringBase() { *this = src; }
 
-        private:
-            char m_buf[FW_TLM_STRING_MAX_SIZE];
-    };
-}
+    ~TlmString() {}
+
+    TlmString& operator=(const TlmString& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    TlmString& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    TlmString& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
+
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
+
+  private:
+    char m_buf[TlmString::STRING_SIZE];
+};
+}  // namespace Fw
 
 #endif
diff --git a/Fw/Types/CMakeLists.txt b/Fw/Types/CMakeLists.txt
index 42fb9992ea..a187ffa660 100644
--- a/Fw/Types/CMakeLists.txt
+++ b/Fw/Types/CMakeLists.txt
@@ -9,16 +9,12 @@
 
 set(SOURCE_FILES
   "${CMAKE_CURRENT_LIST_DIR}/Assert.cpp"
-  "${CMAKE_CURRENT_LIST_DIR}/FileNameString.cpp"
-  "${CMAKE_CURRENT_LIST_DIR}/InternalInterfaceString.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/MallocAllocator.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/MemAllocator.cpp"
-  "${CMAKE_CURRENT_LIST_DIR}/ObjectName.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/PolyType.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/SerialBuffer.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/Serializable.cpp"
-  "${CMAKE_CURRENT_LIST_DIR}/String.cpp"
-  "${CMAKE_CURRENT_LIST_DIR}/StringType.cpp"
+  "${CMAKE_CURRENT_LIST_DIR}/StringBase.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/StringUtils.cpp"
   "${CMAKE_CURRENT_LIST_DIR}/Types.fpp"
 )
diff --git a/Fw/Types/EightyCharString.cpp b/Fw/Types/EightyCharString.cpp
deleted file mode 100644
index 7dcc998a39..0000000000
--- a/Fw/Types/EightyCharString.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <Fw/Types/EightyCharString.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Fw {
-
-EightyCharString::EightyCharString(const char* src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-}
-
-EightyCharString::EightyCharString(const StringBase& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-EightyCharString::EightyCharString(const EightyCharString& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-EightyCharString::EightyCharString() : StringBase() {
-    this->m_buf[0] = 0;
-}
-
-EightyCharString& EightyCharString::operator=(const EightyCharString& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-EightyCharString& EightyCharString::operator=(const StringBase& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-EightyCharString& EightyCharString::operator=(const char* other) {
-    (void)Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-    return *this;
-}
-
-EightyCharString::~EightyCharString() {}
-
-const char* EightyCharString::toChar() const {
-    return this->m_buf;
-}
-
-NATIVE_UINT_TYPE EightyCharString::getCapacity() const {
-    return STRING_SIZE;
-}
-}  // namespace Fw
diff --git a/Fw/Types/EightyCharString.hpp b/Fw/Types/EightyCharString.hpp
deleted file mode 100644
index 34c5b4670a..0000000000
--- a/Fw/Types/EightyCharString.hpp
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef FW_EIGHTY_CHAR_STRING_TYPE_HPP
-#define FW_EIGHTY_CHAR_STRING_TYPE_HPP
-
-#include <FpConfig.hpp>
-#include <Fw/Cfg/SerIds.hpp>
-#include <Fw/Types/StringType.hpp>
-
-namespace Fw {
-
-class EightyCharString : public Fw::StringBase {
-  public:
-    enum {
-        SERIALIZED_TYPE_ID = FW_TYPEID_EIGHTY_CHAR_STRING,      //!< typeid for string type
-        STRING_SIZE = 80,                                       //!< Storage for string
-        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwBuffSizeType)  //!< Serialized size is size of buffer + size field
-    };
-
-    EightyCharString(const char* src);                           //!< char* source constructor
-    EightyCharString(const StringBase& src);                     //!< other string constructor
-    EightyCharString(const EightyCharString& src);               //!< EightyCharString string constructor
-    EightyCharString();                                          //!< default constructor
-    EightyCharString& operator=(const EightyCharString& other);  //!< assignment operator
-    EightyCharString& operator=(const StringBase& other);        //!< other string assignment operator
-    EightyCharString& operator=(const char* other);              //!< char* assignment operator
-    ~EightyCharString();                                         //!< destructor
-
-    const char* toChar() const;            //!< gets char buffer
-    NATIVE_UINT_TYPE getCapacity() const;  //!< return buffer size
-
-  private:
-    char m_buf[STRING_SIZE];  //!< storage for string data
-};
-}  // namespace Fw
-
-#endif
diff --git a/Fw/Types/ExternalString.hpp b/Fw/Types/ExternalString.hpp
new file mode 100644
index 0000000000..ca237a677c
--- /dev/null
+++ b/Fw/Types/ExternalString.hpp
@@ -0,0 +1,120 @@
+// ======================================================================
+// @file   ExternalString.hpp
+// @author Robert Bocchino
+// @brief  A string backed by an external buffer
+// ======================================================================
+
+#ifndef FW_EXTERNAL_STRING_HPP
+#define FW_EXTERNAL_STRING_HPP
+
+#include <FpConfig.hpp>
+
+#include "Fw/Types/StringBase.hpp"
+
+namespace Fw {
+
+//! A string backed by an external buffer
+class ExternalString final : public Fw::StringBase {
+  public:
+    // ----------------------------------------------------------------------
+    // Construction and destruction
+    // ----------------------------------------------------------------------
+
+    //! Constructor (uninitialized buffer)
+    ExternalString() : StringBase(), m_bufferPtr(nullptr), m_bufferSize(0) {}
+
+    //! Constructor (bufferPtr and bufferSize)
+    ExternalString(char* bufferPtr,                 //!< The buffer pointer
+                   StringBase::SizeType bufferSize  //!< The buffer size
+                   )
+        : StringBase(), m_bufferPtr(bufferPtr), m_bufferSize(bufferSize) {
+        *this = "";
+    }
+
+    //! Constructor (bufferPtr, bufferSize, and StringBase)
+    ExternalString(char* bufferPtr,                  //!< The buffer pointer
+                   StringBase::SizeType bufferSize,  //!< The buffer size
+                   const StringBase& sb              //!< The source string
+                   )
+        : StringBase(), m_bufferPtr(bufferPtr), m_bufferSize(bufferSize) {
+        *this = sb;
+    }
+
+    //! Constructor (bufferPtr, bufferSize, and const char*)
+    ExternalString(char* bufferPtr,                  //!< The buffer pointer
+                   StringBase::SizeType bufferSize,  //!< The buffer size
+                   const char* str                   //!< The source string
+                   )
+        : StringBase(), m_bufferPtr(bufferPtr), m_bufferSize(bufferSize) {
+        *this = str;
+    }
+
+    //! Destructor
+    ~ExternalString() {}
+
+  public:
+    // ----------------------------------------------------------------------
+    // StringBase interface
+    // ----------------------------------------------------------------------
+
+    //! Gets the char buffer
+    //! @return The char buffer
+    const char* toChar() const { return this->m_bufferPtr; }
+
+    //! Returns the buffer size
+    //! @return The buffer size
+    StringBase::SizeType getCapacity() const { return this->m_bufferSize; }
+
+  public:
+    // ----------------------------------------------------------------------
+    // Public interface
+    // ----------------------------------------------------------------------
+
+    //! Set the buffer and initialize it to the empty string
+    void setBuffer(char* bufferPtr,       //!< The buffer pointer
+                   FwSizeType bufferSize  //!< The buffer size
+    ) {
+        this->m_bufferPtr = bufferPtr;
+        this->m_bufferSize = bufferSize;
+        *this = "";
+    }
+
+  public:
+    // ----------------------------------------------------------------------
+    // Operators
+    // ----------------------------------------------------------------------
+
+    // Operator= (const ExternalString&)
+    ExternalString& operator=(const ExternalString& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    // Operator= (const StringBase&)
+    ExternalString& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    // const char* assignment operator
+    ExternalString& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+  private:
+    // ----------------------------------------------------------------------
+    // Data members
+    // ----------------------------------------------------------------------
+
+    //! Pointer to string buffer
+    char* m_bufferPtr;
+
+    //! Size of string buffer
+    //! F Prime strings are null-terminated, so this is one more than
+    //! the length of the largest string that the buffer can hold
+    StringBase::SizeType m_bufferSize;
+};
+}  // namespace Fw
+
+#endif
diff --git a/Fw/Types/FileNameString.cpp b/Fw/Types/FileNameString.cpp
deleted file mode 100644
index ae189b5a42..0000000000
--- a/Fw/Types/FileNameString.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "Fw/Types/FileNameString.hpp"
-#include "Fw/Types/StringUtils.hpp"
-
-namespace Fw {
-
-FileNameString::FileNameString(const char* src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-}
-
-FileNameString::FileNameString(const StringBase& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-FileNameString::FileNameString(const FileNameString& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-FileNameString::FileNameString() : StringBase() {
-    this->m_buf[0] = 0;
-}
-
-FileNameString& FileNameString::operator=(const FileNameString& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-FileNameString& FileNameString::operator=(const StringBase& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-FileNameString& FileNameString::operator=(const char* other) {
-    Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-    return *this;
-}
-
-FileNameString::~FileNameString() {}
-
-const char* FileNameString::toChar() const {
-    return this->m_buf;
-}
-
-NATIVE_UINT_TYPE FileNameString::getCapacity() const {
-    return STRING_SIZE;
-}
-}  // namespace Fw
diff --git a/Fw/Types/FileNameString.hpp b/Fw/Types/FileNameString.hpp
index abec0a59c4..5234439480 100644
--- a/Fw/Types/FileNameString.hpp
+++ b/Fw/Types/FileNameString.hpp
@@ -1,36 +1,59 @@
-#ifndef FW_FILENAMESTRING_HPP
-#define FW_FILENAMESTRING_HPP
+// ======================================================================
+// @file   FileNameString.hpp
+// @author F Prime
+// @brief  A string sized to store a file name
+// ======================================================================
+
+#ifndef FW_FILE_NAME_STRING_HPP
+#define FW_FILE_NAME_STRING_HPP
 
 #include <FpConfig.hpp>
 
 #include "Fw/Cfg/SerIds.hpp"
-#include "Fw/Types/StringType.hpp"
+#include "Fw/Types/StringBase.hpp"
 #include "config/FppConstantsAc.hpp"
 
 namespace Fw {
 
-class FileNameString : public Fw::StringBase {
+class FileNameString final : public StringBase {
   public:
     enum {
-        SERIALIZED_TYPE_ID = FW_TYPEID_FILE_NAME_STRING,        //!< typeid for string type
-        STRING_SIZE = FileNameStringSize,                       //!< Storage for string
-        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwBuffSizeType)  //!< Serialized size is size of buffer + size field
+        SERIALIZED_TYPE_ID = FW_TYPEID_FILE_NAME_STRING,
+        STRING_SIZE = FileNameStringSize,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
     };
 
-    explicit FileNameString(const char* src);                //!< char* source constructor
-    explicit FileNameString(const StringBase& src);          //!< other string constructor
-    explicit FileNameString(const FileNameString& src);      //!< String string constructor
-    FileNameString();                                        //!< default constructor
-    FileNameString& operator=(const FileNameString& other);  //!< assignment operator
-    FileNameString& operator=(const StringBase& other);      //!< other string assignment operator
-    FileNameString& operator=(const char* other);            //!< char* assignment operator
-    ~FileNameString();                                       //!< destructor
+    FileNameString() : StringBase() { *this = ""; }
+
+    FileNameString(const FileNameString& src) : StringBase() { *this = src; }
+
+    FileNameString(const StringBase& src) : StringBase() { *this = src; }
+
+    FileNameString(const char* src) : StringBase() { *this = src; }
+
+    ~FileNameString() {}
+
+    FileNameString& operator=(const FileNameString& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    FileNameString& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    FileNameString& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
 
-    const char* toChar() const;            //!< gets char buffer
-    NATIVE_UINT_TYPE getCapacity() const;  //!< return buffer size
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
 
   private:
-    char m_buf[FileNameString::STRING_SIZE];  //!< storage for string data
+    char m_buf[FileNameString::STRING_SIZE];
 };
 }  // namespace Fw
 
diff --git a/Fw/Types/InternalInterfaceString.cpp b/Fw/Types/InternalInterfaceString.cpp
deleted file mode 100644
index ad326a3336..0000000000
--- a/Fw/Types/InternalInterfaceString.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <Fw/Types/InternalInterfaceString.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Fw {
-
-InternalInterfaceString::InternalInterfaceString(const char* src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-}
-
-InternalInterfaceString::InternalInterfaceString(const StringBase& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-InternalInterfaceString::InternalInterfaceString(const InternalInterfaceString& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-InternalInterfaceString::InternalInterfaceString() : StringBase() {
-    this->m_buf[0] = 0;
-}
-
-InternalInterfaceString& InternalInterfaceString::operator=(const InternalInterfaceString& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-InternalInterfaceString& InternalInterfaceString::operator=(const StringBase& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-InternalInterfaceString& InternalInterfaceString::operator=(const char* other) {
-    (void)Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-    return *this;
-}
-
-InternalInterfaceString::~InternalInterfaceString() {}
-
-const char* InternalInterfaceString::toChar() const {
-    return this->m_buf;
-}
-
-NATIVE_UINT_TYPE InternalInterfaceString::getCapacity() const {
-    return FW_INTERNAL_INTERFACE_STRING_MAX_SIZE;
-}
-}  // namespace Fw
diff --git a/Fw/Types/InternalInterfaceString.hpp b/Fw/Types/InternalInterfaceString.hpp
index d7541811a1..7caf3588dc 100644
--- a/Fw/Types/InternalInterfaceString.hpp
+++ b/Fw/Types/InternalInterfaceString.hpp
@@ -1,35 +1,60 @@
-#ifndef FW_INTERNAL_INTERFACE_STRING_TYPE_HPP
-#define FW_INTERNAL_INTERFACE_STRING_TYPE_HPP
+// ======================================================================
+// @file   InternalInterfaceString.hpp
+// @author F Prime
+// @brief  A string sized for an internal port argument
+// ======================================================================
+
+#ifndef FW_INTERNAL_INTERFACE_STRING_HPP
+#define FW_INTERNAL_INTERFACE_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Cfg/SerIds.hpp>
-#include <Fw/Types/StringType.hpp>
+
+#include "Fw/Cfg/SerIds.hpp"
+#include "Fw/Types/StringBase.hpp"
+#include "config/FppConstantsAc.hpp"
 
 namespace Fw {
 
-class InternalInterfaceString : public Fw::StringBase {
+class InternalInterfaceString final : public StringBase {
   public:
     enum {
-        SERIALIZED_TYPE_ID = FW_TYPEID_INTERNAL_INTERFACE_STRING,  //!< typeid for string type
-        SERIALIZED_SIZE = FW_INTERNAL_INTERFACE_STRING_MAX_SIZE +
-                          sizeof(FwBuffSizeType)  //!< Serialized size is size of buffer + size field
+        SERIALIZED_TYPE_ID = FW_TYPEID_INTERNAL_INTERFACE_STRING,
+        STRING_SIZE = FW_INTERNAL_INTERFACE_STRING_MAX_SIZE,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
     };
 
-    InternalInterfaceString(const char* src);                                  //!< char* source constructor
-    InternalInterfaceString(const StringBase& src);                            //!< other string constructor
-    InternalInterfaceString(const InternalInterfaceString& src);               //!< other string constructor
-    InternalInterfaceString();                                                 //!< default constructor
-    InternalInterfaceString& operator=(const InternalInterfaceString& other);  //!< assignment operator
-    InternalInterfaceString& operator=(const StringBase& other);               //!< other string assignment operator
-    InternalInterfaceString& operator=(const char* other);                     //!< char* assignment operator
-    ~InternalInterfaceString();                                                //!< destructor
+    InternalInterfaceString() : StringBase() { *this = ""; }
+
+    InternalInterfaceString(const InternalInterfaceString& src) : StringBase() { *this = src; }
+
+    InternalInterfaceString(const StringBase& src) : StringBase() { *this = src; }
+
+    InternalInterfaceString(const char* src) : StringBase() { *this = src; }
+
+    ~InternalInterfaceString() {}
+
+    InternalInterfaceString& operator=(const InternalInterfaceString& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    InternalInterfaceString& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    InternalInterfaceString& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
 
-    const char* toChar() const;            //!< gets char buffer
-    NATIVE_UINT_TYPE getCapacity() const;  //!< return buffer size
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
 
   private:
-    char m_buf[FW_INTERNAL_INTERFACE_STRING_MAX_SIZE];  //!< storage for string data
+    char m_buf[InternalInterfaceString::STRING_SIZE];
 };
 }  // namespace Fw
 
-#endif  // FW_INTERNAL_INTERFACE_STRING_TYPE_HPP
+#endif
diff --git a/Fw/Types/ObjectName.cpp b/Fw/Types/ObjectName.cpp
deleted file mode 100644
index 2e76ac835d..0000000000
--- a/Fw/Types/ObjectName.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <Fw/Types/ObjectName.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Fw {
-
-ObjectName::ObjectName(const CHAR* src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-}
-
-ObjectName::ObjectName(const StringBase& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-ObjectName::ObjectName(const ObjectName& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-ObjectName::ObjectName() : StringBase() {
-    this->m_buf[0] = 0;
-}
-
-ObjectName& ObjectName::operator=(const ObjectName& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-ObjectName& ObjectName::operator=(const StringBase& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-ObjectName& ObjectName::operator=(const CHAR* other) {
-    (void)Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-    return *this;
-}
-
-ObjectName::~ObjectName() {}
-
-const CHAR* ObjectName::toChar() const {
-    return this->m_buf;
-}
-
-NATIVE_UINT_TYPE ObjectName::getCapacity() const {
-    return STRING_SIZE;
-}
-}  // namespace Fw
diff --git a/Fw/Types/ObjectName.hpp b/Fw/Types/ObjectName.hpp
index 349328a7ed..1b51c471f7 100644
--- a/Fw/Types/ObjectName.hpp
+++ b/Fw/Types/ObjectName.hpp
@@ -1,34 +1,58 @@
-#ifndef FW_OBJECT_NAME_TYPE_HPP
-#define FW_OBJECT_NAME_TYPE_HPP
+// ======================================================================
+// @file   ObjectName.hpp
+// @author F Prime
+// @brief  A string sized to store an object name
+// ======================================================================
+
+#ifndef FW_OBJECT_NAME_HPP
+#define FW_OBJECT_NAME_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Cfg/SerIds.hpp>
-#include <Fw/Types/StringType.hpp>
+
+#include "Fw/Cfg/SerIds.hpp"
+#include "Fw/Types/StringBase.hpp"
 
 namespace Fw {
 
-class ObjectName : public Fw::StringBase {
+class ObjectName final : public StringBase {
   public:
     enum {
-        SERIALIZED_TYPE_ID = FW_TYPEID_OBJECT_NAME,             //!< typeid for string type
-        STRING_SIZE = FW_OBJ_NAME_MAX_SIZE,                     //!< Storage for string
-        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwBuffSizeType)  //!< Serialized size is size of buffer + size field
+        SERIALIZED_TYPE_ID = FW_TYPEID_OBJECT_NAME,
+        STRING_SIZE = FW_OBJ_NAME_MAX_SIZE,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
     };
 
-    explicit ObjectName(const CHAR* src);            //!< char* source constructor
-    explicit ObjectName(const StringBase& src);      //!< StringBase string constructor
-    ObjectName(const ObjectName& src);               //!< ObjectName string constructor
-    ObjectName();                                    //!< default constructor
-    ObjectName& operator=(const ObjectName& other);  //!< assignment operator
-    ObjectName& operator=(const StringBase& other);  //!< StringBase string assignment operator
-    ObjectName& operator=(const CHAR* other);        //!< char* assignment operator
-    ~ObjectName();                                   //!< destructor
+    ObjectName() : StringBase() { *this = ""; }
+
+    ObjectName(const ObjectName& src) : StringBase() { *this = src; }
+
+    ObjectName(const StringBase& src) : StringBase() { *this = src; }
+
+    ObjectName(const char* src) : StringBase() { *this = src; }
+
+    ~ObjectName() {}
+
+    ObjectName& operator=(const ObjectName& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    ObjectName& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    ObjectName& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
 
-    const CHAR* toChar() const;            //!< gets char buffer
-    NATIVE_UINT_TYPE getCapacity() const;  //!< return buffer size
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
 
   private:
-    CHAR m_buf[STRING_SIZE];  //!< storage for string data
+    char m_buf[ObjectName::STRING_SIZE];
 };
 }  // namespace Fw
 
diff --git a/Fw/Types/String.cpp b/Fw/Types/String.cpp
deleted file mode 100644
index 2c7e988b3d..0000000000
--- a/Fw/Types/String.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <Fw/Types/String.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Fw {
-
-String::String(const char* src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-}
-
-String::String(const StringBase& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-String::String(const String& src) : StringBase() {
-    (void)Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-}
-
-String::String() : StringBase() {
-    this->m_buf[0] = 0;
-}
-
-String& String::operator=(const String& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-String& String::operator=(const StringBase& other) {
-    if (this == &other) {
-        return *this;
-    }
-
-    (void)Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-    return *this;
-}
-
-String& String::operator=(const char* other) {
-    (void)Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-    return *this;
-}
-
-String::~String() {}
-
-const char* String::toChar() const {
-    return this->m_buf;
-}
-
-NATIVE_UINT_TYPE String::getCapacity() const {
-    return STRING_SIZE;
-}
-}  // namespace Fw
diff --git a/Fw/Types/String.hpp b/Fw/Types/String.hpp
index e8c4c2e9b2..428fe317f6 100644
--- a/Fw/Types/String.hpp
+++ b/Fw/Types/String.hpp
@@ -1,34 +1,58 @@
-#ifndef FW_FIXED_LENGTH_STRING_TYPE_HPP
-#define FW_FIXED_LENGTH_STRING_TYPE_HPP
+// ======================================================================
+// @file   String.hpp
+// @author F Prime
+// @brief  A general purpose string backed by a fixed-size buffer
+// ======================================================================
+
+#ifndef FW_STRING_HPP
+#define FW_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Cfg/SerIds.hpp>
-#include <Fw/Types/StringType.hpp>
+
+#include "Fw/Cfg/SerIds.hpp"
+#include "Fw/Types/StringBase.hpp"
 
 namespace Fw {
 
-class String : public Fw::StringBase {
+class String final : public StringBase {
   public:
     enum {
-        SERIALIZED_TYPE_ID = FW_TYPEID_FIXED_LENGTH_STRING,     //!< typeid for string type
-        STRING_SIZE = FW_FIXED_LENGTH_STRING_SIZE,              //!< Storage for string
-        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwBuffSizeType)  //!< Serialized size is size of buffer + size field
+        SERIALIZED_TYPE_ID = FW_TYPEID_FIXED_LENGTH_STRING,
+        STRING_SIZE = FW_FIXED_LENGTH_STRING_SIZE,
+        SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType)
     };
 
-    String(const char* src);                     //!< char* source constructor
-    String(const StringBase& src);               //!< other string constructor
-    String(const String& src);                   //!< String string constructor
-    String();                                    //!< default constructor
-    String& operator=(const String& other);      //!< assignment operator
-    String& operator=(const StringBase& other);  //!< other string assignment operator
-    String& operator=(const char* other);        //!< char* assignment operator
-    ~String();                                   //!< destructor
+    String() : StringBase() { *this = ""; }
+
+    String(const String& src) : StringBase() { *this = src; }
+
+    String(const StringBase& src) : StringBase() { *this = src; }
+
+    String(const char* src) : StringBase() { *this = src; }
+
+    ~String() {}
+
+    String& operator=(const String& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    String& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    String& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
 
-    const char* toChar() const;            //!< gets char buffer
-    NATIVE_UINT_TYPE getCapacity() const;  //!< return buffer size
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
 
   private:
-    char m_buf[STRING_SIZE];  //!< storage for string data
+    char m_buf[String::STRING_SIZE];
 };
 }  // namespace Fw
 
diff --git a/Fw/Types/StringType.cpp b/Fw/Types/StringBase.cpp
similarity index 94%
rename from Fw/Types/StringType.cpp
rename to Fw/Types/StringBase.cpp
index bef9c0ddbc..2a7cef41f8 100644
--- a/Fw/Types/StringType.cpp
+++ b/Fw/Types/StringBase.cpp
@@ -1,7 +1,7 @@
 /**
- * \file
+ * \file StringBase.cpp
  * \author T. Canham
- * \brief Implements ISF string base class
+ * \brief Implements F Prime string base class
  *
  * \copyright
  * Copyright 2009-2016, by the California Institute of Technology.
@@ -87,11 +87,9 @@ std::ostream& operator<<(std::ostream& os, const StringBase& str) {
 #endif
 
 StringBase& StringBase::operator=(const StringBase& other) {
-    if (this == &other) {
-        return *this;
+    if (this != &other) {
+        (void)Fw::StringUtils::string_copy(const_cast<char*>(this->toChar()), other.toChar(), this->getCapacity());
     }
-
-    (void)Fw::StringUtils::string_copy(const_cast<char*>(this->toChar()), other.toChar(), this->getCapacity());
     return *this;
 }
 
diff --git a/Fw/Types/StringBase.hpp b/Fw/Types/StringBase.hpp
new file mode 100644
index 0000000000..37ea190e48
--- /dev/null
+++ b/Fw/Types/StringBase.hpp
@@ -0,0 +1,67 @@
+/**
+ * \file StringBase.hpp
+ * \author T. Canham
+ * \brief Declares F Prime string base class
+ *
+ * \copyright
+ * Copyright 2009-2016, by the California Institute of Technology.
+ * ALL RIGHTS RESERVED.  United States Government Sponsorship
+ * acknowledged.
+ *
+ */
+
+#ifndef FW_STRING_BASE_HPP
+#define FW_STRING_BASE_HPP
+
+#include <FpConfig.hpp>
+#include <Fw/Types/Serializable.hpp>
+#ifdef BUILD_UT
+#include <iostream>
+#endif
+
+namespace Fw {
+class StringBase : public Serializable {
+  public:
+    using SizeType = NATIVE_UINT_TYPE;
+    virtual const CHAR* toChar() const = 0;    //<! Convert to a C-style char*
+    virtual SizeType getCapacity() const = 0;  //!< return size of buffer
+    SizeType length() const;                   //!< Get length of string
+
+    const CHAR* operator+=(const CHAR* src);              //!< Concatenate a CHAR*
+    const StringBase& operator+=(const StringBase& src);  //!< Concatenate a StringBase
+    bool operator==(const StringBase& other) const;       //!< Check for equality with StringBase
+    bool operator==(const CHAR* other) const;             //!< Check for equality with CHAR*
+    bool operator!=(const StringBase& other) const;       //!< Inequality with StringBase
+    bool operator!=(const CHAR* other) const;             //!< Inequality with CHAR*
+    StringBase& operator=(const CHAR* src);               //!< Assign CHAR*
+    StringBase& operator=(const StringBase& src);         //!< Assign another StringBase
+
+    void format(const CHAR* formatString, ...);  //!< write formatted string to buffer
+
+    virtual SerializeStatus serialize(SerializeBufferBase& buffer) const;                   //!< serialization function
+    virtual SerializeStatus serialize(SerializeBufferBase& buffer, SizeType maxLen) const;  //!< serialization function
+    virtual SerializeStatus deserialize(SerializeBufferBase& buffer);  //!< deserialization function
+
+#ifdef BUILD_UT
+    // to support GoogleTest framework in unit tests
+    friend std::ostream& operator<<(std::ostream& os, const StringBase& str);
+#endif
+#if FW_SERIALIZABLE_TO_STRING || BUILD_UT
+    void toString(StringBase& text) const;  //!< write string with contents
+#endif
+
+  protected:
+    StringBase();
+    virtual ~StringBase();
+
+    void appendBuff(const CHAR* buff, SizeType size);
+
+  private:
+    // A no-implementation copy constructor here will prevent the default copy constructor from being called
+    // accidentally, and without an implementation it will create an error for the developer instead.
+    StringBase(const StringBase& src);  //!< constructor with buffer as source
+};
+
+}  // namespace Fw
+
+#endif
diff --git a/Fw/Types/StringType.hpp b/Fw/Types/StringType.hpp
index ebf8257aa5..f83bb63e55 100644
--- a/Fw/Types/StringType.hpp
+++ b/Fw/Types/StringType.hpp
@@ -1,67 +1,2 @@
-/**
- * \file
- * \author T. Canham
- * \brief Declares ISF string base class
- *
- * \copyright
- * Copyright 2009-2016, by the California Institute of Technology.
- * ALL RIGHTS RESERVED.  United States Government Sponsorship
- * acknowledged.
- *
- */
-
-#ifndef FW_STRING_TYPE_HPP
-#define FW_STRING_TYPE_HPP
-
-#include <FpConfig.hpp>
-#include <Fw/Types/Serializable.hpp>
-#ifdef BUILD_UT
-#include <iostream>
-#endif
-
-namespace Fw {
-class StringBase : public Serializable {
-  public:
-    using SizeType = NATIVE_UINT_TYPE;
-    virtual const CHAR* toChar() const = 0;    //<! Convert to a C-style char*
-    virtual SizeType getCapacity() const = 0;  //!< return size of buffer
-    SizeType length() const;                   //!< Get length of string
-
-    const CHAR* operator+=(const CHAR* src);              //!< Concatenate a CHAR*
-    const StringBase& operator+=(const StringBase& src);  //!< Concatenate a StringBase
-    bool operator==(const StringBase& other) const;       //!< Check for equality with StringBase
-    bool operator==(const CHAR* other) const;             //!< Check for equality with CHAR*
-    bool operator!=(const StringBase& other) const;       //!< Inequality with StringBase
-    bool operator!=(const CHAR* other) const;             //!< Inequality with CHAR*
-    StringBase& operator=(const CHAR* src);               //!< Assign CHAR*
-    StringBase& operator=(const StringBase& src);         //!< Assign another StringBase
-
-    void format(const CHAR* formatString, ...);  //!< write formatted string to buffer
-
-    virtual SerializeStatus serialize(SerializeBufferBase& buffer) const;                   //!< serialization function
-    virtual SerializeStatus serialize(SerializeBufferBase& buffer, SizeType maxLen) const;  //!< serialization function
-    virtual SerializeStatus deserialize(SerializeBufferBase& buffer);  //!< deserialization function
-
-#ifdef BUILD_UT
-    // to support GoogleTest framework in unit tests
-    friend std::ostream& operator<<(std::ostream& os, const StringBase& str);
-#endif
-#if FW_SERIALIZABLE_TO_STRING || BUILD_UT
-    void toString(StringBase& text) const;  //!< write string with contents
-#endif
-
-  protected:
-    StringBase();
-    virtual ~StringBase();
-
-    void appendBuff(const CHAR* buff, SizeType size);
-
-  private:
-    // A no-implementation copy constructor here will prevent the default copy constructor from being called
-    // accidentally, and without an implementation it will create an error for the developer instead.
-    StringBase(const StringBase& src);  //!< constructor with buffer as source
-};
-
-}  // namespace Fw
-
-#endif
+// Compatibility header
+#include "Fw/Types/StringBase.hpp"
diff --git a/Os/CMakeLists.txt b/Os/CMakeLists.txt
index 7a8b462e8c..529e0e149e 100644
--- a/Os/CMakeLists.txt
+++ b/Os/CMakeLists.txt
@@ -26,10 +26,8 @@ set(MOD_DEPS
 # Basic source files used in every OSAL layer.  Contains common code and helpers.
 set(SOURCE_FILES
     "${CMAKE_CURRENT_LIST_DIR}/IntervalTimerCommon.cpp"
-    "${CMAKE_CURRENT_LIST_DIR}/TaskString.cpp"
     "${CMAKE_CURRENT_LIST_DIR}/TaskCommon.cpp"
     "${CMAKE_CURRENT_LIST_DIR}/QueueCommon.cpp"
-    "${CMAKE_CURRENT_LIST_DIR}/QueueString.cpp"
     "${CMAKE_CURRENT_LIST_DIR}/IPCQueueCommon.cpp"
     "${CMAKE_CURRENT_LIST_DIR}/SimpleQueueRegistry.cpp"
     "${CMAKE_CURRENT_LIST_DIR}/MemCommon.cpp"
diff --git a/Os/QueueString.cpp b/Os/QueueString.cpp
deleted file mode 100644
index 9e625b60e3..0000000000
--- a/Os/QueueString.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <Os/QueueString.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Os {
-
-    QueueString::QueueString(const char* src) : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-    }
-
-    QueueString::QueueString(const StringBase& src) : StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    QueueString::QueueString(const QueueString& src)  : StringBase() {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    QueueString::QueueString() : StringBase()  {
-        this->m_buf[0] = 0;
-    }
-
-    QueueString& QueueString::operator=(const QueueString& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    QueueString& QueueString::operator=(const StringBase& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    QueueString& QueueString::operator=(const char* other) {
-        (void) Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-        return *this;
-    }
-
-    QueueString::~QueueString() {
-    }
-
-    const char* QueueString::toChar() const {
-        return this->m_buf;
-    }
-
-    NATIVE_UINT_TYPE QueueString::getCapacity() const {
-        return FW_QUEUE_NAME_MAX_SIZE;
-    }
-}
diff --git a/Os/QueueString.hpp b/Os/QueueString.hpp
index 8b590f5ced..d7fda579f2 100644
--- a/Os/QueueString.hpp
+++ b/Os/QueueString.hpp
@@ -1,29 +1,54 @@
-#ifndef OS_QUEUE_STRING_TYPE_HPP
-#define OS_QUEUE_STRING_TYPE_HPP
+// ======================================================================
+// @file   QueueString.hpp
+// @author F Prime
+// @brief  A string sized for an OS queue name
+// ======================================================================
+
+#ifndef OS_QUEUE_STRING_HPP
+#define OS_QUEUE_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Types/StringType.hpp>
+
+#include "Fw/Types/StringBase.hpp"
 
 namespace Os {
 
-    class QueueString : public Fw::StringBase {
-        public:
-
-            QueueString(const char* src); //!< char buffer constructor
-            QueueString(const StringBase& src); //!< copy constructor
-            QueueString(const QueueString& src); //!< copy constructor
-            QueueString(); //!< default constructor
-            QueueString& operator=(const QueueString& other); //!< assignment operator
-            QueueString& operator=(const StringBase& other); //!< other string assignment operator
-            QueueString& operator=(const char* other); //!< char* assignment operator
-            ~QueueString(); //!< destructor
-
-            const char* toChar() const; //!< get pointer to char buffer
-            NATIVE_UINT_TYPE getCapacity() const ;
-
-        private:
-            char m_buf[FW_QUEUE_NAME_MAX_SIZE]; //!< buffer for string
-    };
-}
+class QueueString final : public Fw::StringBase {
+  public:
+    enum { STRING_SIZE = FW_QUEUE_NAME_MAX_SIZE, SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType) };
+
+    QueueString() : StringBase() { *this = ""; }
+
+    QueueString(const QueueString& src) : StringBase() { *this = src; }
+
+    QueueString(const StringBase& src) : StringBase() { *this = src; }
+
+    QueueString(const char* src) : StringBase() { *this = src; }
+
+    ~QueueString() {}
+
+    QueueString& operator=(const QueueString& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    QueueString& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    QueueString& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
+
+    const char* toChar() const { return this->m_buf; }
+
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
+
+  private:
+    char m_buf[QueueString::STRING_SIZE];
+};
+}  // namespace Os
 
 #endif
diff --git a/Os/TaskString.cpp b/Os/TaskString.cpp
deleted file mode 100644
index 07d02f756b..0000000000
--- a/Os/TaskString.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-#include <Os/TaskString.hpp>
-#include <Fw/Types/StringUtils.hpp>
-
-namespace Os {
-
-    TaskString::TaskString(const char* src) : StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src, sizeof(this->m_buf));
-    }
-
-    TaskString::TaskString(const StringBase& src) : StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    TaskString::TaskString(const TaskString& src) : StringBase()  {
-        (void) Fw::StringUtils::string_copy(this->m_buf, src.toChar(), sizeof(this->m_buf));
-    }
-
-    TaskString::TaskString() {
-        this->m_buf[0] = 0;
-    }
-
-    TaskString& TaskString::operator=(const TaskString& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    TaskString& TaskString::operator=(const StringBase& other) {
-        if(this == &other) {
-            return *this;
-        }
-
-        (void) Fw::StringUtils::string_copy(this->m_buf, other.toChar(), sizeof(this->m_buf));
-        return *this;
-    }
-
-    TaskString& TaskString::operator=(const char* other) {
-        (void) Fw::StringUtils::string_copy(this->m_buf, other, sizeof(this->m_buf));
-        return *this;
-    }
-
-    TaskString::~TaskString() {
-    }
-
-    const char* TaskString::toChar() const {
-        return this->m_buf;
-    }
-
-    NATIVE_UINT_TYPE TaskString::getCapacity() const {
-        return FW_TASK_NAME_MAX_SIZE;
-    }
-}
diff --git a/Os/TaskString.hpp b/Os/TaskString.hpp
index 1a100ed3ce..e22db533a0 100644
--- a/Os/TaskString.hpp
+++ b/Os/TaskString.hpp
@@ -1,32 +1,54 @@
-#ifndef OS_TASK_STRING_TYPE_HPP
-#define OS_TASK_STRING_TYPE_HPP
+// ======================================================================
+// @file   TaskString.hpp
+// @author F Prime
+// @brief  A string sized for an OS task name
+// ======================================================================
+
+#ifndef OS_TASK_STRING_HPP
+#define OS_TASK_STRING_HPP
 
 #include <FpConfig.hpp>
-#include <Fw/Types/StringType.hpp>
+
+#include "Fw/Types/StringBase.hpp"
 
 namespace Os {
 
-    class TaskString : public Fw::StringBase {
-        public:
+class TaskString final : public Fw::StringBase {
+  public:
+    enum { STRING_SIZE = FW_TASK_NAME_MAX_SIZE, SERIALIZED_SIZE = STRING_SIZE + sizeof(FwSizeStoreType) };
+
+    TaskString() : StringBase() { *this = ""; }
+
+    TaskString(const TaskString& src) : StringBase() { *this = src; }
+
+    TaskString(const StringBase& src) : StringBase() { *this = src; }
+
+    TaskString(const char* src) : StringBase() { *this = src; }
+
+    ~TaskString() {}
 
-            TaskString(const char* src); //!< char buffer constructor
-            TaskString(const StringBase& src); //!< Copy constructor
-            TaskString(const TaskString& src); //!< Copy constructor
-            TaskString(); //!< default constructor
-            TaskString& operator=(const TaskString& other); //!< assignment operator
-            TaskString& operator=(const StringBase& other); //!< other string assignment operator
-            TaskString& operator=(const char* other); //!< char* assignment operator
-            ~TaskString(); //!< destructor
+    TaskString& operator=(const TaskString& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
 
-            const char* toChar() const; //!< get pointer to internal char buffer
-            NATIVE_UINT_TYPE getCapacity() const; //!< return buffer size
+    TaskString& operator=(const StringBase& src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
 
-        private:
+    TaskString& operator=(const char* src) {
+        (void)StringBase::operator=(src);
+        return *this;
+    }
 
-            char m_buf[FW_TASK_NAME_MAX_SIZE]; //!< buffer for string
+    const char* toChar() const { return this->m_buf; }
 
-    };
+    StringBase::SizeType getCapacity() const { return sizeof this->m_buf; }
 
-}
+  private:
+    char m_buf[TaskString::STRING_SIZE];
+};
+}  // namespace Os
 
 #endif


Test patch:
diff --git a/Fw/Types/test/ut/TypesTest.cpp b/Fw/Types/test/ut/TypesTest.cpp
index d6ac79f6c3..20142cf758 100644
--- a/Fw/Types/test/ut/TypesTest.cpp
+++ b/Fw/Types/test/ut/TypesTest.cpp
@@ -1,5 +1,6 @@
 #include <FpConfig.hpp>
 #include <Fw/Types/Assert.hpp>
+#include <Fw/Types/ExternalString.hpp>
 #include <Fw/Types/InternalInterfaceString.hpp>
 #include <Fw/Types/MallocAllocator.hpp>
 #include <Fw/Types/ObjectName.hpp>
@@ -1116,7 +1117,7 @@ TEST(TypesTest, PolyTest) {
     ASSERT_EQ(outPtr, inPtr);
 }
 
-TEST(TypesTest, EightyCharTest) {
+TEST(TypesTest, StringTest) {
     Fw::String str;
     str = "foo";
     Fw::String str2;
@@ -1148,7 +1149,13 @@ TEST(TypesTest, EightyCharTest) {
 
     std::cout << "Stream: " << str2 << std::endl;
 
-    // Make our own short string
+    char buffer[Fw::String::STRING_SIZE];
+    Fw::ExternalString es(buffer, sizeof buffer, "ExternalString");
+    Fw::ObjectName es2(es);
+
+    ASSERT_EQ(es, es2);
+    ASSERT_EQ(es2, "ExternalString");
+
 }
 
 TEST(TypesTest, ObjectNameTest) {
@@ -1173,11 +1180,12 @@ TEST(TypesTest, ObjectNameTest) {
     Fw::ObjectName copyStr2(copyStr);
     ASSERT_EQ(copyStr2, "ASTRING");
 
-    Fw::InternalInterfaceString ifstr("IfString");
-    Fw::ObjectName if2(ifstr);
+    char buffer[Fw::ObjectName::STRING_SIZE];
+    Fw::ExternalString es(buffer, sizeof buffer, "ExternalString");
+    Fw::ObjectName es2(es);
 
-    ASSERT_EQ(ifstr, if2);
-    ASSERT_EQ(if2, "IfString");
+    ASSERT_EQ(es, es2);
+    ASSERT_EQ(es2, "ExternalString");
 }
 
 TEST(TypesTest, StringFormatTest) {