mptStringBuffer.h 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. * mptStringBuffer.h
  3. * -----------------
  4. * Purpose: Various functions for "fixing" char array strings for writing to or
  5. * reading from module files, or for securing char arrays in general.
  6. * Notes : (currently none)
  7. * Authors: OpenMPT Devs
  8. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  9. */
  10. #pragma once
  11. #include "openmpt/all/BuildSettings.hpp"
  12. #include "mpt/string/buffer.hpp"
  13. #include "mptString.h"
  14. #include <algorithm>
  15. #include <string>
  16. #include <vector>
  17. OPENMPT_NAMESPACE_BEGIN
  18. namespace mpt
  19. {
  20. namespace String
  21. {
  22. enum ReadWriteMode : uint8
  23. {
  24. // Reading / Writing: Standard null-terminated string handling.
  25. nullTerminated = 1,
  26. // Reading: Source string is not guaranteed to be null-terminated (if it fills the whole char array).
  27. // Writing: Destination string is not guaranteed to be null-terminated (if it fills the whole char array).
  28. maybeNullTerminated = 2,
  29. // Reading: String may contain null characters anywhere. They should be treated as spaces.
  30. // Writing: A space-padded string is written.
  31. spacePadded = 3,
  32. // Reading: String may contain null characters anywhere. The last character is ignored (it is supposed to be 0).
  33. // Writing: A space-padded string with a trailing null is written.
  34. spacePaddedNull = 4,
  35. };
  36. namespace detail
  37. {
  38. std::string ReadStringBuffer(String::ReadWriteMode mode, const char *srcBuffer, std::size_t srcSize);
  39. void WriteStringBuffer(String::ReadWriteMode mode, char *destBuffer, const std::size_t destSize, const char *srcBuffer, const std::size_t srcSize);
  40. } // namespace detail
  41. } // namespace String
  42. namespace String {
  43. using mpt::ReadTypedBuf;
  44. using mpt::WriteTypedBuf;
  45. } // namespace String
  46. namespace String {
  47. using mpt::ReadAutoBuf;
  48. using mpt::WriteAutoBuf;
  49. } // namespace String
  50. template <typename Tchar>
  51. class StringModeBufRefImpl
  52. {
  53. private:
  54. Tchar * buf;
  55. std::size_t size;
  56. String::ReadWriteMode mode;
  57. public:
  58. // cppcheck false-positive
  59. // cppcheck-suppress uninitMemberVar
  60. StringModeBufRefImpl(Tchar * buf_, std::size_t size_, String::ReadWriteMode mode_)
  61. : buf(buf_)
  62. , size(size_)
  63. , mode(mode_)
  64. {
  65. static_assert(sizeof(Tchar) == 1);
  66. }
  67. StringModeBufRefImpl(const StringModeBufRefImpl &) = delete;
  68. StringModeBufRefImpl(StringModeBufRefImpl &&) = default;
  69. StringModeBufRefImpl & operator = (const StringModeBufRefImpl &) = delete;
  70. StringModeBufRefImpl & operator = (StringModeBufRefImpl &&) = delete;
  71. operator std::string () const
  72. {
  73. return String::detail::ReadStringBuffer(mode, buf, size);
  74. }
  75. bool empty() const
  76. {
  77. return String::detail::ReadStringBuffer(mode, buf, size).empty();
  78. }
  79. StringModeBufRefImpl & operator = (const std::string & str)
  80. {
  81. String::detail::WriteStringBuffer(mode, buf, size, str.data(), str.size());
  82. return *this;
  83. }
  84. };
  85. template <typename Tchar>
  86. class StringModeBufRefImpl<const Tchar>
  87. {
  88. private:
  89. const Tchar * buf;
  90. std::size_t size;
  91. String::ReadWriteMode mode;
  92. public:
  93. // cppcheck false-positive
  94. // cppcheck-suppress uninitMemberVar
  95. StringModeBufRefImpl(const Tchar * buf_, std::size_t size_, String::ReadWriteMode mode_)
  96. : buf(buf_)
  97. , size(size_)
  98. , mode(mode_)
  99. {
  100. static_assert(sizeof(Tchar) == 1);
  101. }
  102. StringModeBufRefImpl(const StringModeBufRefImpl &) = delete;
  103. StringModeBufRefImpl(StringModeBufRefImpl &&) = default;
  104. StringModeBufRefImpl & operator = (const StringModeBufRefImpl &) = delete;
  105. StringModeBufRefImpl & operator = (StringModeBufRefImpl &&) = delete;
  106. operator std::string () const
  107. {
  108. return String::detail::ReadStringBuffer(mode, buf, size);
  109. }
  110. bool empty() const
  111. {
  112. return String::detail::ReadStringBuffer(mode, buf, size).empty();
  113. }
  114. };
  115. namespace String {
  116. template <typename Tchar, std::size_t size>
  117. inline StringModeBufRefImpl<typename std::add_const<Tchar>::type> ReadBuf(String::ReadWriteMode mode, const std::array<Tchar, size> &buf)
  118. {
  119. return StringModeBufRefImpl<typename std::add_const<Tchar>::type>(buf.data(), size, mode);
  120. }
  121. template <typename Tchar, std::size_t size>
  122. inline StringModeBufRefImpl<typename std::add_const<Tchar>::type> ReadBuf(String::ReadWriteMode mode, const Tchar (&buf)[size])
  123. {
  124. return StringModeBufRefImpl<typename std::add_const<Tchar>::type>(buf, size, mode);
  125. }
  126. template <typename Tchar>
  127. inline StringModeBufRefImpl<typename std::add_const<Tchar>::type> ReadBuf(String::ReadWriteMode mode, const Tchar * buf, std::size_t size)
  128. {
  129. return StringModeBufRefImpl<typename std::add_const<Tchar>::type>(buf, size, mode);
  130. }
  131. template <typename Tchar, std::size_t size>
  132. inline StringModeBufRefImpl<Tchar> WriteBuf(String::ReadWriteMode mode, std::array<Tchar, size> &buf)
  133. {
  134. return StringModeBufRefImpl<Tchar>(buf.data(), size, mode);
  135. }
  136. template <typename Tchar, std::size_t size>
  137. inline StringModeBufRefImpl<Tchar> WriteBuf(String::ReadWriteMode mode, Tchar (&buf)[size])
  138. {
  139. return StringModeBufRefImpl<Tchar>(buf, size, mode);
  140. }
  141. template <typename Tchar>
  142. inline StringModeBufRefImpl<Tchar> WriteBuf(String::ReadWriteMode mode, Tchar * buf, std::size_t size)
  143. {
  144. return StringModeBufRefImpl<Tchar>(buf, size, mode);
  145. }
  146. } // namespace String
  147. template <std::size_t len, mpt::String::ReadWriteMode mode>
  148. struct modecharbuf
  149. {
  150. public:
  151. typedef char Tchar;
  152. using char_type = Tchar;
  153. using string_type = std::basic_string<Tchar>;
  154. public:
  155. Tchar buf[len];
  156. public:
  157. modecharbuf() = default;
  158. modecharbuf(const modecharbuf &) = default;
  159. modecharbuf(modecharbuf &&) = default;
  160. modecharbuf & operator = (const modecharbuf &) = default;
  161. modecharbuf & operator = (modecharbuf &&) = default;
  162. operator string_type () const
  163. {
  164. return mpt::String::ReadBuf(mode, buf);
  165. }
  166. bool empty() const
  167. {
  168. return mpt::String::ReadBuf(mode, buf).empty();
  169. }
  170. modecharbuf & operator = (const string_type & str)
  171. {
  172. mpt::String::WriteBuf(mode, buf) = str;
  173. return *this;
  174. }
  175. };
  176. // see MPT_BINARY_STRUCT
  177. template <std::size_t len, mpt::String::ReadWriteMode mode>
  178. constexpr bool declare_binary_safe(const typename mpt::modecharbuf<len, mode> &) { return true; }
  179. //struct is_binary_safe<typename mpt::modecharbuf<len, mode>> : public std::true_type { };
  180. static_assert(sizeof(mpt::modecharbuf<7, mpt::String::ReadWriteMode::nullTerminated>) == 7);
  181. static_assert(alignof(mpt::modecharbuf<7, mpt::String::ReadWriteMode::nullTerminated>) == 1);
  182. static_assert(std::is_standard_layout<mpt::modecharbuf<7, mpt::String::ReadWriteMode::nullTerminated>>::value);
  183. #ifdef MODPLUG_TRACKER
  184. #if MPT_OS_WINDOWS
  185. namespace String {
  186. using mpt::ReadWinBuf;
  187. using mpt::WriteWinBuf;
  188. } // namespace String
  189. #if defined(MPT_WITH_MFC)
  190. namespace String {
  191. using mpt::ReadCStringBuf;
  192. using mpt::WriteCStringBuf;
  193. } // namespace String
  194. #endif // MPT_WITH_MFC
  195. #endif // MPT_OS_WINDOWS
  196. #endif // MODPLUG_TRACKER
  197. namespace String
  198. {
  199. #if MPT_COMPILER_MSVC
  200. #pragma warning(push)
  201. #pragma warning(disable:4127) // conditional expression is constant
  202. #endif // MPT_COMPILER_MSVC
  203. // Sets last character to null in given char array.
  204. // Size of the array must be known at compile time.
  205. template <size_t size>
  206. void SetNullTerminator(char (&buffer)[size])
  207. {
  208. static_assert(size > 0);
  209. buffer[size - 1] = 0;
  210. }
  211. inline void SetNullTerminator(char *buffer, size_t size)
  212. {
  213. MPT_ASSERT(size > 0);
  214. buffer[size - 1] = 0;
  215. }
  216. #if !defined(MPT_COMPILER_QUIRK_NO_WCHAR)
  217. template <size_t size>
  218. void SetNullTerminator(wchar_t (&buffer)[size])
  219. {
  220. static_assert(size > 0);
  221. buffer[size - 1] = 0;
  222. }
  223. inline void SetNullTerminator(wchar_t *buffer, size_t size)
  224. {
  225. MPT_ASSERT(size > 0);
  226. buffer[size - 1] = 0;
  227. }
  228. #endif // !MPT_COMPILER_QUIRK_NO_WCHAR
  229. #if MPT_COMPILER_MSVC
  230. #pragma warning(pop)
  231. #endif // MPT_COMPILER_MSVC
  232. } // namespace String
  233. } // namespace mpt
  234. OPENMPT_NAMESPACE_END