Remote Call Framework 3.4
string.hpp
1 
2 //******************************************************************************
3 // RCF - Remote Call Framework
4 //
5 // Copyright (c) 2005 - 2023, Delta V Software. All rights reserved.
6 // https://www.deltavsoft.com
7 //
8 // RCF is distributed under dual licenses - closed source or GPL.
9 // Consult your particular license for conditions of use.
10 //
11 // If you have not purchased a commercial license, you are using RCF under GPL terms.
12 //
13 // Version: 3.4
14 // Contact: support <at> deltavsoft.com
15 //
16 //******************************************************************************
17 
18 #ifndef INCLUDE_SF_STRING_HPP
19 #define INCLUDE_SF_STRING_HPP
20 
21 #include <algorithm>
22 #include <string>
23 #include <type_traits>
24 
25 #include <RCF/Tools.hpp>
26 #include <SF/Archive.hpp>
27 #include <SF/Stream.hpp>
28 #include <RCF/Tchar.hpp>
29 
30 namespace SF {
31 
32  template<typename C, typename T, typename A>
33  inline void serializeString(SF::Archive & ar, std::basic_string<C,T,A> & s)
34  {
35  if (ar.isRead())
36  {
37  std::uint32_t count = 0;
38  ar & count;
39 
40  SF::IStream &is = *ar.getIstream();
41 
42  s.resize(0);
43 
44  std::size_t minSerializedLength = sizeof(C);
45  if (ar.verifyAgainstArchiveSize(count*minSerializedLength))
46  {
47  if (count > s.capacity())
48  {
49  s.reserve(count);
50  }
51  }
52 
53  std::uint32_t charsRemaining = count;
54  const std::uint32_t BufferSize = 512;
55  C buffer[BufferSize];
56  while (charsRemaining)
57  {
58  std::uint32_t charsToRead = RCF_MIN(BufferSize, charsRemaining);
59  std::uint32_t bytesToRead = charsToRead*sizeof(C);
60 
61  if ( is.read((char *)buffer, bytesToRead) != bytesToRead )
62  {
63  RCF::Exception e(RCF::RcfError_SfReadFailure);
64  RCF_THROW(e);
65  }
66 
67  s.append(buffer, charsToRead);
68  charsRemaining -= charsToRead;
69  }
70  }
71  else if (ar.isWrite())
72  {
73  std::uint32_t count = static_cast<std::uint32_t >(s.length());
74  ar & count;
75  ar.getOstream()->writeRaw(
76  (char *) s.c_str(),
77  count*sizeof(C));
78  }
79 
80  }
81 
82  RCF_EXPORT bool getCurrentNativeWstringSerialization();
83 
84  template<typename C, typename T, typename A>
85  inline void serializeEncodedString(SF::Archive & ar, std::basic_string<C,T,A> & ws)
86  {
87  if (ar.getRuntimeVersion() < 8)
88  {
89  serializeString(ar, ws);
90  return;
91  }
92 
93  RCF_ASSERT(ar.getRuntimeVersion() >= 8);
94 
95  if (ar.isRead())
96  {
97  int encodingType = 0;
98  ar & encodingType;
99  if (encodingType == 8)
100  {
101  // UTF-8 serialization.
102  std::string s;
103  ar & s;
104  ws = RCF::stringToWstring(s);
105  }
106  else
107  {
108  // Native wchar_t serialization.
109 
110  if ( encodingType != sizeof(wchar_t) )
111  {
112  RCF::Exception e(RCF::RcfError_WcharSizeMismatch, sizeof(wchar_t), encodingType);
113  RCF_THROW(e);
114  }
115 
116  serializeString(ar, ws);
117  }
118 
119  }
120  else if (ar.isWrite())
121  {
122  // Default behavior is to convert to UTF-8. However there is also a setting on ClientStub that allows
123  // user to instead select native wchar_t serialization.
124 
125  int encodingType = 8;
126  bool useNativeWstringSerialization = getCurrentNativeWstringSerialization();
127  if ( useNativeWstringSerialization )
128  {
129  encodingType = sizeof(wchar_t);
130  }
131 
132  ar & encodingType;
133 
134  if (encodingType == 8)
135  {
136  // UTF-8 serialization.
137  std::string s = RCF::wstringToString(ws);
138  ar & s;
139  }
140  else
141  {
142  // Native wchar_t serialization.
143 
144  if ( encodingType != sizeof(wchar_t) )
145  {
146  RCF::Exception e(RCF::RcfError_WcharSizeMismatch, sizeof(wchar_t), encodingType);
147  RCF_THROW(e);
148  }
149 
150  serializeString(ar, ws);
151  }
152  }
153  }
154 
155  template<typename C, typename T, typename A>
156  inline void serializeEncodedStringOrNot(SF::Archive & ar, std::basic_string<C, T, A> & t, std::true_type *)
157  {
158  serializeEncodedString(ar, t);
159  }
160 
161  template<typename C, typename T, typename A>
162  inline void serializeEncodedStringOrNot(SF::Archive & ar, std::basic_string<C, T, A> & t, std::false_type *)
163  {
164  serializeString(ar, t);
165  }
166 
167  // std::basic_string (with wstring support)
168  template<typename C, typename T, typename A>
169  inline void serialize_vc6(SF::Archive & ar, std::basic_string<C,T,A> & t, const unsigned int)
170  {
171  typedef typename std::is_same<C, wchar_t>::type type;
172  serializeEncodedStringOrNot(ar, t, (type *) NULL);
173  }
174 
175 } // namespace SF
176 
177 #endif // ! INCLUDE_SF_STRING_HPP
Represents an archive, in which serialized objects are stored.
Definition: Archive.hpp:31
int getRuntimeVersion()
Gets the RCF runtime version associated with this archive.
Base class for all RCF exceptions.
Definition: Exception.hpp:67
Definition: ByteBuffer.hpp:188
bool isWrite() const
Returns true if this archive is being written to.
bool isRead() const
Returns true if this archive is being read from.
Base class for input streams using SF serialization. Use operator >>() to deserialize objects from th...
Definition: Stream.hpp:137