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