TurtleBrains  0.3.5
High quality, portable, C++ framework for rapid 2D game development.
tb_fixed_string.hpp
1 
15 #ifndef TurtleBrains_FixedString_hpp
16 #define TurtleBrains_FixedString_hpp
17 
18 #include <turtle_brains/core/tb_configuration.hpp>
19 #include <turtle_brains/core/tb_string.hpp>
20 #include <turtle_brains/core/tb_error.hpp>
21 
22 #include <cstring>
23 
24 // 2024-07-30: I believe I'm getting this warning as a compiler bug, and yet Ubuntu 22.04 isn't letting me update GCC.
25 // Bug Reported here: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88780 and you can see it was closed for GCC 11 on
26 // 2024-07-19, which is definitely after I got rhino started; as of today no GCC update avaiable.
27 //
28 // This was caused in TrackBuilder where NodeName is FixedString<24> and the error is complaining about:
29 // "output may be truncated copying 23 bytes from a string of length 23" where size = 24, and I expected error is
30 // 24-1 for the null-terminator. Previously used strncpy(mData, value, Size - 1); and now strncpy with full size and
31 // manually setting the last char to null-terminator.
32 //
33 // 2024-11-02: Today the null-terminator was removed from the FixedString and .c_str() was removed as well since it
34 // required that null-terminator. Using data() returns the raw (possibly no null-terminator) character array; also
35 // could use String() to return a copy where .c_str() can work.
36 #if (defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER))
37  #pragma GCC diagnostic ignored "-Wstringop-truncation"
38 #endif
39 
40 namespace TurtleBrains
41 {
42  namespace Core
43  {
44 
45  template <size_t Size> class FixedString
46  {
47  tb_static_error_if(Size < 1, "Expected FixedString size to contain at least 1 character.");
48 
49  public:
50  FixedString(void) :
51  mData{ '\0', }
52  {
53  }
54 
55  FixedString(const char* value) :
56  mData{ '\0', }
57  {
58  strncpy(mData, value, Size);
59  }
60 
61  FixedString(const String& value) :
62  mData{ '\0', }
63  {
64  strncpy(mData, value.c_str(), Size);
65  }
66 
67  FixedString(const FixedString& value) :
68  mData{ '\0', }
69  {
70  strncpy(mData, value.mData, Size);
71  }
72 
73  FixedString& operator=(const FixedString& other)
74  {
75  strncpy(mData, other.mData, Size);
76  return *this;
77  }
78 
79  FixedString& operator=(const String& other)
80  {
81  strncpy(mData, other.c_str(), Size);
82  return *this;
83  }
84 
85  FixedString& operator=(const char* other)
86  {
87  strncpy(mData, other, Size);
88  return *this;
89  }
90 
91  bool operator==(const FixedString& other) const { return 0 == std::strncmp(mData, other.String().c_str(), Size); }
92  bool operator==(const char* other) const { return 0 == std::strncmp(mData, other, Size); }
93  bool operator==(const String& other) const { return 0 == std::strncmp(mData, other.c_str(), Size); }
94  bool operator!=(const FixedString& other) const { return 0 != std::strncmp(mData, other.mData, Size); }
95  bool operator!=(const char* other) const { return 0 != std::strncmp(mData, other, Size); }
96  bool operator!=(const String& other) const { return 0 != std::strncmp(mData, other.c_str(), Size); }
97 
98  inline operator tbCore::String(void) const
99  {
100  return String();
101  }
102 
103  bool empty(void) const { return mData[0] == '\0'; }
104  size_t size(void) const
105  {
106  // memchr is somewhat like strlen with max count, strlen_s (and any _s) are seemingly bad standards because
107  // MSVC had some of them defined that don't act like the standard states; so many compilers didn't
108  // support the _s functions. https://stackoverflow.com/questions/66346502/which-is-most-standard-strnlen-or-strnlen-s
109  const char* nullTerm = static_cast<const char*>(memchr(mData, '\0', Size));
110  const char* start = &mData[0];
111  return (nullptr == nullTerm) ? Size : (nullTerm - start);
112  }
113 
114  size_t FixedSize(void) const { return Size; }
115 
118  const char* data(void) const { return mData; }
119  char* data(void) { return mData; }
120 
121  tbCore::String String(void) const
122  {
123  return tbCore::String(mData, size());
124  }
125 
126  private:
127  char mData[Size];
128  };
129 
130  template <size_t Size> std::ostream& operator<<(std::ostream& outputStream, const FixedString<Size>& fixed)
131  {
132  outputStream << fixed.data();
133  return outputStream;
134  }
135 
136  template <size_t Size> std::istream& operator<<(std::istream& inputStream, FixedString<Size>& fixed)
137  {
138  String buffer;
139  inputStream >> buffer;
140  fixed = buffer;
141  return inputStream;
142  }
143 
144  template <size_t Size> bool operator==(const char* left, const FixedString<Size>& right) { return 0 == std::strncmp(right.data(), left, Size); }
145  template <size_t Size> bool operator==(const String& left, const FixedString<Size>& right) { return 0 == std::strncmp(right.data(), left.c_str(), Size); }
146  template <size_t Size> bool operator!=(const char* left, const FixedString<Size>& right) { return 0 != std::strncmp(right.data(), left, Size); }
147  template <size_t Size> bool operator!=(const String& left, const FixedString<Size>& right) { return 0 != std::strncmp(right.data(), left.c_str(), Size); }
148 
149  }; /* namespace Core */
150 }; /* namespace TurtleBrains */
151 
152 namespace tbCore = TurtleBrains::Core;
153 
154 #if (defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER))
155  #pragma GCC diagnostic warning "-Wstringop-truncation"
156 #endif
157 
158 #endif /* TurtleBrains_FixedString_hpp */
Definition: tb_fixed_string.hpp:46
const char * data(void) const
Definition: tb_fixed_string.hpp:118
Definition: tb_types.hpp:32
Contains core functionality for each component of the API.
Definition: tb_debug_logger.hpp:125
std::string String
Definition: tb_string.hpp:302
Here is some information about the primary namespace.
Definition: tb_application_dialog.hpp:22