ALib C++ Library
Library Version: 2412 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
std_strings_iostream.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !DOXYGEN
11#endif // !DOXYGEN
12
13#include <algorithm>
14
15#if ALIB_STRINGS
16
17
18#if !DOXYGEN
19
21
22namespace {
23
24int adjustNewLines(const NString& src, NAString& dest ) {
25 constexpr bool isRN= NEW_LINE.Length() == 2;
26 int result= 0;
27 integer idx= 0;
28 const NString* search= &src;
29 while ((idx=search->IndexOf('\n', idx)) != -1 ) {
30 if constexpr (isRN ) {
31 if (idx == 0 || search->CharAt(idx - 1) != '\r') {
32 if (++result == 1) {
33 dest.Reset(search->Substring(0, idx))._('\r')._<NC>(search->Substring(idx));
34 search= &dest;
35 }
36 else
37 dest.InsertAt("\r", idx);
38 }
39 ++idx;
40 }
41 else { // not windows
42 if (idx > 0 && search->CharAt(idx - 1) == '\r' ) {
43 if (++result == 1) {
44 dest.Reset(search->Substring(0, idx-1))._(search->Substring(idx));
45 search= &dest;
46 }
47 else
48 dest.Delete(idx-1, 1);
49 }
50 else
51 ++idx;
52 }
53 }
54 return result;
55}
56
57int adjustNewLines(const WString& src, NAString& dest ) {
58 dest.Reset(src);
59 constexpr bool isRN= NEW_LINE.Length() == 2;
60 int result= 0;
61 integer idx= 0;
62 while ((idx=dest.IndexOf('\n', idx)) != -1 ) {
63 if constexpr (isRN)
64 if (idx == 0 || dest.CharAt(idx - 1) != '\r')
65 dest.InsertAt("\r", idx);
66
67 if constexpr (!isRN)
68 if (!isRN && idx > 0 && dest.CharAt(idx - 1) == '\r' )
69 dest.Delete(idx-1, 1);
70
71 ++idx;
72 }
73 return result;
74}
75} // anonymous namespace
76
78{
79 if( ostream == nullptr )
80 {
81 ALIB_WARNING( "STRINGS", "StringWriter::WriteAndGetWideLength: No output stream")
82 return 0;
83 }
84
85 if (adjustNewLines(src, converter) > 0)
86 ostream->write( converter.Buffer(), converter.Length() );
87 else
88 ostream->write( src.Buffer(), src.Length() );
89 return src.WStringLength();
90}
91
93{
94 if( ostream == nullptr )
95 {
96 ALIB_WARNING( "STRINGS", "StringWriter::WriteAndGetWideLength: No output stream")
97 return 0;
98 }
99
100 adjustNewLines( src, converter );
101 ostream->write( converter.Buffer(), converter.Length() );
102 return src.Length();
103}
104
105void StringWriter::Write( const NString& src )
106{
107 if( ostream == nullptr )
108 {
109 ALIB_WARNING( "STRINGS", "StringWriter::WriteAndGetWideLength: No output stream")
110 return;
111 }
112 if (adjustNewLines(src, converter) > 0)
113 ostream->write( converter.Buffer(), converter.Length() );
114 else
115 ostream->write( src.Buffer(), src.Length() );
116}
117
118void StringWriter::WriteChars( const nchar fillChar, integer count )
119{
120 if( ostream == nullptr ) {
121 ALIB_WARNING( "STRINGS", "StringWriter::WriteAndGetWideLength: No output stream")
122 return;
123 }
124
125 characters::AlignedCharArray<nchar, 8*sizeof(void*)> alc( fillChar );
126 while (count >= alc.Length() ) {
127 ostream->write(alc.Buffer(), alc.Length());
128 count-= alc.Length();
129 }
130
131 if (count > 0)
132 ostream->write(alc.Buffer(), count);
133}
134
135void StringWriter::Write( const WString& src )
136{
137 if( ostream == nullptr )
138 {
139 ALIB_WARNING( "STRINGS", "StringWriter::WriteAndGetWideLength: No output stream")
140 return;
141 }
142 adjustNewLines( src, converter );
143 ostream->write( converter.Buffer(), converter.Length() );
144}
145} // namespace [alib::strings::compatibility::std]
146
147std::ostream& operator<<( std::ostream& stream, const alib::WString& string )
148{
149 alib::NString1K conv;
150 alib::integer maxConv= 1024 / static_cast<alib::integer>(MB_CUR_MAX);
151
152 alib::integer startIdx= 0;
153 while( startIdx < string.Length() )
154 {
155 alib::integer length= (std::min)( alib::integer(maxConv), string.Length() - startIdx);
156 conv.Reset( string.Substring<alib::NC>(startIdx, length) );
157 stream.write( conv.Buffer(), conv.Length() );
158 startIdx+= length;
159 }
160
161 return stream;
162}
163
164std::wostream& operator<<( std::wostream& stream, const alib::NString& string )
165{
168 conv << string;
169 stream.write( conv.Buffer(), conv.Length() );
170 return stream;
171}
172
173template<typename TChar>
175 TAString<TChar, alib::lang::HeapAllocator>& target,
176 const compatibility::std::TISReadLine<TChar>& reader )
177{
178 // we are required to read from to the param object. So we cast to non-const. This is OK, as
179 // the const specifier came through TMP.
180 compatibility::std::TISReadLine<TChar>& param= const_cast<compatibility::std::TISReadLine<TChar>&>( reader );
181
182 if ( param.TargetData == lang::CurrentData::Clear )
183 target.Reset();
184 alib::integer origLength= target.Length();
185
186 // read loop
187 while( !param.IStream->eof() )
188 {
189 // calc buffer size (if we hit the overall line width)
190 // and check if we reached the limit per line
191 alib::integer actReadSize= (std::min)( param.BufferSize, param.MaxLineWidth - ( target.Length() - origLength) + 1 );
192 if ( actReadSize < 2 )
193 return;
194
195 target.EnsureRemainingCapacity( actReadSize );
196
197 // read
199 int64_t start= target.Length();
200 param.IStream->getline( target.VBuffer() + start, actReadSize );
201 std::streamsize gCount= param.IStream->gcount();
202 std::streamsize count= static_cast<std::streamsize>( characters::Length( target.Buffer() + start ) );
203
204 bool lineComplete= count + 1 == gCount;
205
206 // something read?
207 if ( count > 0 )
208 {
209 // be sure to not have a carriage return at the start
210 if( *(target.Buffer() + start) == '\r' )
211 {
212 target.template Delete<NC>( static_cast<alib::integer>(start), 1 );
213 --count;
214 }
215
216 // be sure to not have a carriage return at the end
217 start+= count;
218 if( *(target.Buffer() + start -1 ) == '\r' )
219 --start;
220
221 target.SetLength( static_cast<alib::integer>(start) );
222
223 // if we are at the end of the file (without delimiter) we stop now
224 if ( param.IStream->eof() )
225 {
226 param.IsEOF= true;
227 return;
228 }
229 }
231
232
233 // delim read
234 if ( lineComplete )
235 return;
236
237 // buffer was not big enough
238 if ( gCount == actReadSize -1)
239 {
240 if ( param.IStream->eof() )
241 return;
242
243
244 // otherwise, it should really have been the buffer size, so let's clear the bit
245 // and continue with more buffer space
246 ALIB_ASSERT( param.IStream->rdstate() == std::iostream::failbit )
247 param.IStream->clear();
248 continue;
249 }
250
251 // the eof just happened now
252 if ( param.IStream->eof() )
253 break;
254
255 if ( param.IStream->rdstate() == std::iostream::failbit )
256 {
257 ALIB_ERROR( "STRINGS", "Unknown Error Reading File. Maybe method implemented incomplete?" )
258 break;
259 }
260
261 // anything else to add here? I guess not! But you never know with this strange
262 // iostream classes!
263
264 //...
265
266 // This happens if \0 is in the file
267 ALIB_ERROR( "STRINGS", "Unknown Error Reading File. Probably not a text file." )
268 break;
269 }
270
271 param.IsEOF= true;
272}
273
274
275// instantiations of T_Append::operator() for char and wchar_t versions of stream reader class
276template void alib::strings::T_Append<alib::strings::compatibility::std::TISReadLine<char >, char , alib::lang::HeapAllocator>::operator()( TAString<char , alib::lang::HeapAllocator>& target, const compatibility::std::TISReadLine<char >& reader );
277template void alib::strings::T_Append<alib::strings::compatibility::std::TISReadLine<wchar_t>, wchar_t, alib::lang::HeapAllocator>::operator()( TAString<wchar_t, alib::lang::HeapAllocator>& target, const compatibility::std::TISReadLine<wchar_t>& reader );
278
279#endif // DOXYGEN
280
281#endif // ALIB_STRINGS
282
void DbgDisableBufferReplacementWarning()
Definition tastring.inl:363
constexpr integer Length() const
Definition string.hpp:326
constexpr const TChar * Buffer() const
Definition string.hpp:319
ALIB_API integer WriteAndGetWideLength(const NString &src)
ALIB_API void Write(const NString &src)
ALIB_API void WriteChars(const nchar fillChar, integer count)
NAString converter
The string buffer used for conversion.
#define ALIB_WARNING(...)
Definition alib.hpp:1268
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:849
#define ALIB_ERROR(...)
Definition alib.hpp:1267
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:760
#define ALIB_ASSERT(cond)
Definition alib.hpp:1270
integer Length(const TChar *cstring)
@ Clear
Chooses to clear existing data.
std::ostream & operator<<(std::ostream &stream, const alib::NString &string)
Definition alib.cpp:69
files::File File
Type alias in namespace alib.
Definition ftree.hpp:1046
characters::AlignedCharArray<> AlignedCharArray
strings::TString< nchar > NString
Type alias in namespace alib.
strings::TAString< nchar, lang::HeapAllocator > NAString
Type alias in namespace alib.
strings::TSubstring< character > Substring
Type alias in namespace alib.
strings::TString< wchar > WString
Type alias in namespace alib.
constexpr CString NEW_LINE
A zero-terminated string containing the new-line character sequence.
Definition cstring.hpp:580
lang::HeapAllocator HeapAllocator
Type alias in namespace alib.
characters::nchar nchar
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
Definition integers.hpp:273