LibraryLink Utilities  3.0.1
Modern C++ wrapper over LibraryLink and WSTP
Strings.h
Go to the documentation of this file.
1 
7 #ifndef LLU_WSTP_STRINGS_H_
8 #define LLU_WSTP_STRINGS_H_
9 
10 #include <algorithm>
11 #include <functional>
12 #include <memory>
13 
14 #include "wstp.h"
15 
16 #include "LLU/ErrorLog/Errors.h"
17 #include "LLU/Utilities.hpp"
19 #include "LLU/WSTP/Utilities.h"
20 
21 namespace LLU::WS {
22 
26  namespace EncodingConfig {
30 
34  extern bool useFastUTF8;
35  } // namespace EncodingConfig
36 
37  template<Encoding E>
38  struct ReleaseString;
39 
42  template<Encoding E>
43  using StringData = std::unique_ptr<const CharType<E>[], ReleaseString<E>>;
44 
46  template<typename T>
47  using GetStringFuncT = std::function<int(WSLINK, const T**, int*, int*)>;
48 
50  template<typename T>
51  using PutStringFuncT = std::function<int(WSLINK, const T*, int)>;
52 
54  template<typename T>
55  using ReleaseStringFuncT = std::function<void(WSLINK, const T*, int)>;
56 
57  template<Encoding E>
58  struct String {
59 
60  using CharT = CharType<E>;
61 
62  static GetStringFuncT<CharT> Get;
63  static PutStringFuncT<CharT> Put;
64  static ReleaseStringFuncT<CharT> Release;
65 
66  static const std::string GetFName;
67  static const std::string PutFName;
68 
69  template<typename T>
70  static void put(WSLINK m, const T* string, int len) {
71  static_assert(CharacterTypesCompatible<E, T>, "Character type does not match the encoding in WS::String<E>::put");
72  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): sorry :(
73  auto* expectedStr = reinterpret_cast<const CharT*>(string);
74  Detail::checkError(m, Put(m, expectedStr, len), ErrorName::WSPutStringError, PutFName);
75  }
76 
77  static StringData<E> get(WSLINK m) {
78  const CharT* rawResult {};
79  int bytes {};
80  int characters {};
81  Detail::checkError(m, Get(m, &rawResult, &bytes, &characters), ErrorName::WSGetStringError, GetFName);
82  return {rawResult, ReleaseString<E> {m, bytes, characters}};
83  }
84 
85  template<typename T>
86  static std::basic_string<T> getString(WSLINK m) {
87  static_assert(CharacterTypesCompatible<E, T>, "Character type does not match the encoding in WS::String<E>::getString");
88  using StringType = std::basic_string<T>;
89 
90  auto strData {get(m)};
91 
92  auto bytes = strData.get_deleter().getLength();
93  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast): sorry :(
94  auto* expectedData = reinterpret_cast<const T*>(strData.get());
95  auto strlen = static_cast<typename StringType::size_type>(bytes);
96 
97  return (bytes < 0 ? StringType {expectedData} : StringType {expectedData, strlen});
98  }
99  };
100 
106  template<>
107  struct String<Encoding::Undefined> {
108 
109  template<typename T>
110  static void put(WSLINK /*link*/, const T* /*stringData*/, int /*length*/) {
111  static_assert(dependent_false_v<T>, "Trying to use WS::String<Encoding::Undefined>::put");
112  }
113 
114  template<typename T = char>
115  static T* get(WSLINK /*link*/) {
116  static_assert(dependent_false_v<T>, "Trying to use WS::String<Encoding::Undefined>::get");
117  return nullptr;
118  }
119 
120  template<typename T>
121  static std::basic_string<T> getString(WSLINK /*link*/) {
122  static_assert(dependent_false_v<T>, "Trying to use WS::String<Encoding::Undefined>::getString");
123  return {};
124  }
125  };
127 
128  template<Encoding E>
129  struct ReleaseString {
130  ReleaseString() = default;
131  ReleaseString(WSLINK m, int l, int c) : m(m), length(l), chars(c) {}
132 
133  void operator()(const CharType<E>* data) {
134  String<E>::Release(m, data, length);
135  }
136 
137  int getLength() const {
138  return length;
139  }
140 
141  int getCharacters() const {
142  return chars;
143  }
144 
145  private:
146  WSLINK m = nullptr;
147  int length = 0;
148  int chars = 0;
149  };
150 
152 #ifndef _WIN32
153 
156 #define WS_STRING_DECLARE_SPECIALIZATIONS_OF_STATIC_MEMBERS(E) \
157  template<> \
158  GetStringFuncT<CharType<Encoding::E>> String<Encoding::E>::Get; \
159  template<> \
160  PutStringFuncT<CharType<Encoding::E>> String<Encoding::E>::Put; \
161  template<> \
162  ReleaseStringFuncT<CharType<Encoding::E>> String<Encoding::E>::Release; \
163  template<> \
164  const std::string String<Encoding::E>::GetFName; \
165  template<> \
166  const std::string String<Encoding::E>::PutFName;
167 
168  WS_STRING_DECLARE_SPECIALIZATIONS_OF_STATIC_MEMBERS(Native)
169  WS_STRING_DECLARE_SPECIALIZATIONS_OF_STATIC_MEMBERS(Byte)
170  WS_STRING_DECLARE_SPECIALIZATIONS_OF_STATIC_MEMBERS(UTF8)
171  WS_STRING_DECLARE_SPECIALIZATIONS_OF_STATIC_MEMBERS(UTF16)
172  WS_STRING_DECLARE_SPECIALIZATIONS_OF_STATIC_MEMBERS(UCS2)
173  WS_STRING_DECLARE_SPECIALIZATIONS_OF_STATIC_MEMBERS(UTF32)
174 
175 #else
176 
177  template<>
178  GetStringFuncT<CharType<Encoding::Native>> String<Encoding::Native>::Get = [](WSLINK m, const char** strData, int* len, int* charCnt) {
179  *len = *charCnt = -1;
180  return WSGetString(m, strData);
181  };
182  template<>
183  PutStringFuncT<CharType<Encoding::Native>> String<Encoding::Native>::Put = [](WSLINK m, const char* strData, int) { return WSPutString(m, strData); };
184  template<>
185  ReleaseStringFuncT<CharType<Encoding::Native>> String<Encoding::Native>::Release = [](WSLINK m, const char* strData, int) { WSReleaseString(m, strData); };
186  template<>
187  const std::string String<Encoding::Native>::GetFName = "WSGetString";
188  template<>
189  const std::string String<Encoding::Native>::PutFName = "WSPutString";
190 
191  template<>
192  GetStringFuncT<CharType<Encoding::Byte>> String<Encoding::Byte>::Get = [](WSLINK m, const unsigned char** strData, int* len, int* charCnt) {
193  *charCnt = -1;
194  return WSGetByteString(m, strData, len, EncodingConfig::substituteCodeForByteEncoding);
195  };
196  template<>
197  PutStringFuncT<CharType<Encoding::Byte>> String<Encoding::Byte>::Put = WSPutByteString;
198  template<>
199  ReleaseStringFuncT<CharType<Encoding::Byte>> String<Encoding::Byte>::Release = WSReleaseByteString;
200  template<>
201  const std::string String<Encoding::Byte>::GetFName = "WSGetByteString";
202  template<>
203  const std::string String<Encoding::Byte>::PutFName = "WSPutByteString";
204 
205  namespace {
206  // Nested lambdas are too much for MSVC, so we define this helper function separately
207  bool allASCIIQ(const unsigned char* strData, int len) {
208  return std::all_of(strData, strData + len, [](unsigned char c) -> bool { return c <= 127; });
209  }
210  }
211 
212  template<>
213  GetStringFuncT<CharType<Encoding::UTF8>> String<Encoding::UTF8>::Get = WSGetUTF8String;
214  template<>
215  PutStringFuncT<CharType<Encoding::UTF8>> String<Encoding::UTF8>::Put = [](WSLINK m, const unsigned char* strData, int len) -> int {
216  if (EncodingConfig::useFastUTF8 && allASCIIQ(strData, len)) {
217  return WSPutByteString(m, strData, len);
218  } else {
219  return WSPutUTF8String(m, strData, len);
220  }
221  };
222  template<>
223  ReleaseStringFuncT<CharType<Encoding::UTF8>> String<Encoding::UTF8>::Release = WSReleaseUTF8String;
224  template<>
225  const std::string String<Encoding::UTF8>::GetFName = "WSGetUTF8String";
226  template<>
227  const std::string String<Encoding::UTF8>::PutFName = "WSPut(UTF8/Byte)String";
228 
229  template<>
230  GetStringFuncT<CharType<Encoding::UTF16>> String<Encoding::UTF16>::Get = WSGetUTF16String;
231  template<>
232  PutStringFuncT<CharType<Encoding::UTF16>> String<Encoding::UTF16>::Put = WSPutUTF16String;
233  template<>
234  ReleaseStringFuncT<CharType<Encoding::UTF16>> String<Encoding::UTF16>::Release = WSReleaseUTF16String;
235  template<>
236  const std::string String<Encoding::UTF16>::GetFName = "WSGetUTF16String";
237  template<>
238  const std::string String<Encoding::UTF16>::PutFName = "WSPutUTF16String";
239 
240  template<>
241  GetStringFuncT<CharType<Encoding::UCS2>> String<Encoding::UCS2>::Get = [](WSLINK m, const unsigned short** strData, int* len, int* charCnt) {
242  *charCnt = -1;
243  return WSGetUCS2String(m, strData, len);
244  };
245  template<>
246  PutStringFuncT<CharType<Encoding::UCS2>> String<Encoding::UCS2>::Put = WSPutUCS2String;
247  template<>
248  ReleaseStringFuncT<CharType<Encoding::UCS2>> String<Encoding::UCS2>::Release = WSReleaseUCS2String;
249  template<>
250  const std::string String<Encoding::UCS2>::GetFName = "WSGetUCS2String";
251  template<>
252  const std::string String<Encoding::UCS2>::PutFName = "WSPutUCS2String";
253 
254  template<>
255  GetStringFuncT<CharType<Encoding::UTF32>> String<Encoding::UTF32>::Get = [](WSLINK m, const unsigned int** strData, int* len, int* charCnt) {
256  *charCnt = -1;
257  return WSGetUTF32String(m, strData, len);
258  };
259  template<>
260  PutStringFuncT<CharType<Encoding::UTF32>> String<Encoding::UTF32>::Put = WSPutUTF32String;
261  template<>
262  ReleaseStringFuncT<CharType<Encoding::UTF32>> String<Encoding::UTF32>::Release = WSReleaseUTF32String;
263  template<>
264  const std::string String<Encoding::UTF32>::GetFName = "WSGetUTF32String";
265  template<>
266  const std::string String<Encoding::UTF32>::PutFName = "WSPutUTF32String";
267 
268 #endif
269 } /* namespace LLU::WS */
271 
272 #endif /* LLU_WSTP_STRINGS_H_ */
LLU::WS::CharType
typename CharTypeStruct< E >::type CharType
Specializations of CharTypeStruct, encoding E has assigned type T iff WSPutEString takes const T* as ...
Definition: EncodingTraits.hpp:81
LLU::WS::EncodingConfig::substituteCodeForByteEncoding
long substituteCodeForByteEncoding
Global configuration parameter defining a substitute character required in WSGetByteString.
Definition: Strings.cpp:19
LLU::ErrorName::WSPutStringError
const std::string WSPutStringError
Could not send string via WSTP.
LLU::WS::GetStringFuncT
std::function< int(WSLINK, const T **, int *, int *)> GetStringFuncT
GetStringFuncT is a type of WSTP function that reads string from a link, e.g. WSGetByteString.
Definition: Strings.h:47
LLU::WS::Encoding
Encoding
Definition: EncodingTraits.hpp:21
LLU::WS::StringData
std::unique_ptr< const CharType< E >[], ReleaseString< E > > StringData
StringData with Encoding E is a unique_ptr to an array of E-encoded characters It allows you to take ...
Definition: Strings.h:43
EncodingTraits.hpp
Defines possible encodings together with their properties and related types.
LLU::WS::StringType
typename StringTypeStruct< E >::type StringType
Definition: EncodingTraits.hpp:113
LLU::WS::EncodingConfig::useFastUTF8
bool useFastUTF8
Global configuration parameter specifying whether to use a faster version of sending UTF8 strings.
Definition: Strings.cpp:20
Errors.h
Definitions of error names and error codes used across LLU.
LLU::WS
Contains definitions related to WSTP functionality in LLU.
Definition: EncodingTraits.hpp:15
LLU::WS::PutStringFuncT
std::function< int(WSLINK, const T *, int)> PutStringFuncT
PutStringFuncT is a type of WSTP function that sends string data to a link, e.g. WSPutByteString.
Definition: Strings.h:51
Utilities.h
Header file with miscellaneous utilities used throughout the WSTP-related part of LibraryLinkUtilitie...
LLU::WS::ReleaseStringFuncT
std::function< void(WSLINK, const T *, int)> ReleaseStringFuncT
ReleaseStringFuncT is a type of WSTP function to release string data allocated by WSTP,...
Definition: Strings.h:55
LLU::ErrorName::WSGetStringError
const std::string WSGetStringError
Could not get string from WSTP.
Utilities.hpp
Short but generally useful functions.