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