stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
ios.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023 Amebis
4*/
5
6#pragma once
7
8#ifdef _WIN32
9#include <windows.h>
10#endif
11#include "endian.hpp"
12#include "internal.hpp"
13#include "string.hpp"
14#include "sal.hpp"
15#include <assert.h>
16#include <stdint.h>
17#include <stdio.h>
18#include <algorithm>
19#include <chrono>
20#include <fstream>
21#include <iterator>
22#include <istream>
23#include <ostream>
24#include <vector>
25
26namespace stdex
27{
31 template <class _Elem, class _Traits>
33 {
34 public:
35 std::basic_ostream<_Elem, _Traits> &sp; // Write stream
36
37 inline basic_ostreamfmt(_Inout_ std::basic_ostream<_Elem, _Traits> &stream) : sp(stream) {}
38
39 using pos_type = typename _Traits::pos_type;
40 using off_type = typename _Traits::off_type;
41 inline pos_type tellp() { return sp.tellp(); }
42 inline basic_ostreamfmt<_Elem, _Traits>& seekp(pos_type pos) { sp.seekp(pos); return *this; }
43 inline basic_ostreamfmt<_Elem, _Traits>& seekp(off_type off, std::ios_base::seekdir dir) { sp.seekp(off, dir); return *this; }
44 inline bool good() const noexcept { return sp.good(); }
45 inline bool eof() const noexcept { return sp.eof(); }
46 inline bool fail() const noexcept { return sp.fail(); }
47 inline bool bad() const noexcept { return sp.bad(); }
48
49 inline basic_ostreamfmt<_Elem, _Traits>& write(_In_reads_bytes_(size) const void* data, _In_ std::streamsize size)
50 {
51 sp.write(reinterpret_cast<const _Elem*>(data), size/sizeof(_Elem));
52 return *this;
53 }
54
55 template <class T>
56 inline basic_ostreamfmt<_Elem, _Traits>& write(_In_ T value)
57 {
58 HE2LE(&value);
59 sp.write(reinterpret_cast<const _Elem*>(&value), sizeof(T)/sizeof(_Elem));
60 return *this;
61 }
62
63 inline basic_ostreamfmt<_Elem, _Traits>& write(_In_z_ const char* value)
64 {
65 size_t count = strlen(value);
66 if (count > UINT32_MAX)
67 throw std::invalid_argument("string too big");
68 sp.write(static_cast<uint32_t>(count));
69 sp.write(reinterpret_cast<const _Elem*>(value), (std::streamsize)count * sizeof(char)/sizeof(_Elem));
70 return *this;
71 }
72
73 inline basic_ostreamfmt<_Elem, _Traits>& write(_In_z_ const wchar_t* value)
74 {
75 size_t count = strlen(value);
76 if (count > UINT32_MAX)
77 throw std::invalid_argument("string too big");
78 sp.write(static_cast<uint32_t>(count));
79#ifdef BIG_ENDIAN
80 for (size_t i = 0; i < count; ++i)
81 sp.write(value[i]);
82#else
83 sp.write(reinterpret_cast<const _Elem*>(value), (std::streamsize)count * sizeof(wchar_t)/sizeof(_Elem));
84#endif
85 return *this;
86 }
87
88 inline basic_ostreamfmt<_Elem, _Traits>& write_byte(_In_ uint8_t value)
89 {
90 return write(value);
91 }
92
100 template <class _Elem2>
101 void vprintf(_In_z_ _Printf_format_string_ const _Elem2 *format, _In_opt_ locale_t locale, _In_ va_list arg)
102 {
103 std::basic_string<_Elem2> str;
104 vappendf(str, format, locale, arg);
105 sp.write(reinterpret_cast<const _Elem*>(str.c_str()), str.size() * sizeof(_Elem2)/sizeof(_Elem));
106 }
107
114 template <class _Elem2>
115 void printf(_In_z_ _Printf_format_string_ const _Elem2 *format, _In_opt_ locale_t locale, ...)
116 {
117 va_list arg;
118 va_start(arg, locale);
119 vprintf(format, locale, arg);
120 va_end(arg);
121 }
122
123 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ int8_t value) { return write(value); }
124 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ int16_t value) { return write(value); }
125 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ int32_t value) { return write(value); }
126 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ int64_t value) { return write(value); }
127 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ uint8_t value) { return write(value); }
128 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ uint16_t value) { return write(value); }
129 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ uint32_t value) { return write(value); }
130 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ uint64_t value) { return write(value); }
131#if defined(_NATIVE_SIZE_T_DEFINED) && defined(_WIN64)
132 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ size_t value) { return write(value); }
133#endif
134 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ float value) { return write(value); }
135 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ double value) { return write(value); }
136 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ char value) { return write(value); }
137#ifdef _NATIVE_WCHAR_T_DEFINED
138 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_ wchar_t value) { return write(value); }
139#endif
140 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_z_ const char* value) { return write(value); }
141 inline basic_ostreamfmt<_Elem, _Traits>& operator <<(_In_z_ const wchar_t* value) { return write(value); }
142 };
143
144 using ostreamfmt = basic_ostreamfmt<char, std::char_traits<char>>;
145 using wostreamfmt = basic_ostreamfmt<wchar_t, std::char_traits<wchar_t>>;
146
150 template <class _Elem, class _Traits>
152 {
153 public:
154 std::basic_istream<_Elem, _Traits> &sg; // Read stream
155
156 inline basic_istreamfmt(_Inout_ std::basic_istream<_Elem, _Traits> &stream) : sg(stream) {}
157
158 using pos_type = typename _Traits::pos_type;
159 using off_type = typename _Traits::off_type;
160 inline pos_type tellg() { return sg.tellg(); }
161 inline basic_istreamfmt<_Elem, _Traits>& seekg(pos_type pos) { sg.seekg(pos); return *this; }
162 inline basic_istreamfmt<_Elem, _Traits>& seekg(off_type off, std::ios_base::seekdir dir) { sg.seekg(off, dir); return *this; }
163 inline bool good() const noexcept { return sg.good(); }
164 inline bool eof() const noexcept { return sg.eof(); }
165 inline bool fail() const noexcept { return sg.fail(); }
166 inline bool bad() const noexcept { return sg.bad(); }
167 inline std::streamsize gcount() const noexcept { return sg.gcount(); }
168
169 inline basic_istreamfmt<_Elem, _Traits>& read(_Out_writes_bytes_(size) void* data, std::streamsize size)
170 {
171 sg.read(reinterpret_cast<_Elem*>(data), size/sizeof(_Elem));
172 return *this;
173 }
174
175 template <class T>
176 inline basic_istreamfmt<_Elem, _Traits>& read(_Out_ T& value)
177 {
178 sg.read(reinterpret_cast<_Elem*>(&value), sizeof(T)/sizeof(_Elem));
179 if (sg.good())
180 LE2HE(&value);
181 return *this;
182 }
183
184 template <class _Traits = std::char_traits<char>, class _Alloc = std::allocator<char>>
185 inline basic_istreamfmt<_Elem, _Traits>& read(_Inout_ std::basic_string<char, _Traits, _Alloc>& value)
186 {
187 uint32_t count;
188 sg.read(count);
189 if (sg.good()) {
190 value.resize(count);
191 sg.read(reinterpret_cast<_Elem*>(&value[0]), (std::streamsize)count * sizeof(char)/sizeof(_Elem));
192 }
193 return *this;
194 }
195
196 template <class _Traits = std::char_traits<wchar_t>, class _Alloc = std::allocator<wchar_t>>
197 inline basic_istreamfmt<_Elem, _Traits>& read(_Inout_ std::basic_string<wchar_t, _Traits, _Alloc>& value)
198 {
199 uint32_t count;
200 sg.read(count);
201 if (sg.good()) {
202 value.resize(count);
203#ifdef BIG_ENDIAN
204 for (size_t i = 0; i < count; ++i)
205 sg.read(value[i]);
206#else
207 sg.read(reinterpret_cast<_Elem*>(&value[0]), (std::streamsize)count * sizeof(wchar_t)/sizeof(_Elem));
208#endif
209 }
210 return *this;
211 }
212
213 inline uint8_t read_byte()
214 {
215 uint8_t value;
216 read(value);
217 return value;
218 }
219
220 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ int8_t& value) { return read(value); }
221 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ int16_t& value) { return read(value); }
222 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ int32_t& value) { return read(value); }
223 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ int64_t& value) { return read(value); }
224 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ uint8_t& value) { return read(value); }
225 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ uint16_t& value) { return read(value); }
226 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ uint32_t& value) { return read(value); }
227 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ uint64_t& value) { return read(value); }
228#if defined(_NATIVE_SIZE_T_DEFINED) && defined(_WIN64)
229 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ size_t& value) { return read(value); }
230#endif
231 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ float& value) { return read(value); }
232 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ double& value) { return read(value); }
233 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ char& value) { return read(value); }
234#ifdef _NATIVE_WCHAR_T_DEFINED
235 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Out_ wchar_t& value) { return read(value); }
236#endif
237 template <class _Traits = std::char_traits<char>, class _Alloc = std::allocator<char>>
238 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Inout_ std::basic_string<char, _Traits, _Alloc>& value) { return read(value); }
239 template <class _Traits = std::char_traits<wchar_t>, class _Alloc = std::allocator<wchar_t>>
240 inline basic_istreamfmt<_Elem, _Traits>& operator >>(_Inout_ std::basic_string<wchar_t, _Traits, _Alloc>& value) { return read(value); }
241 };
242
245
249 template <class _Elem, class _Traits>
250 class basic_iostreamfmt : public basic_ostreamfmt<_Elem, _Traits>, public basic_istreamfmt<_Elem, _Traits>
251 {
252 public:
253 inline basic_iostreamfmt(_Inout_ std::basic_iostream<_Elem, _Traits> &stream) :
256 {}
257 };
258
261
265 template <class _Elem, class _Traits>
266 class basic_sharedstrbuf : public std::basic_streambuf<_Elem, _Traits>
267 {
268 public:
269 basic_sharedstrbuf(_In_reads_(size) const _Elem* data, _In_ size_t size)
270 {
271 setg(const_cast<_Elem*>(data), const_cast<_Elem*>(data), const_cast<_Elem*>(data + size));
272 }
273
275 {
276 setg(other.eback(), other.gptr(), other.egptr());
277 }
278
280 {
281 if (this != std::addressof(other))
282 std::basic_streambuf<_Elem, _Traits>::operator =(other);
283 return *this;
284 }
285
286 private:
289
290 protected:
291 virtual pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
292 {
293 if (which & std::ios_base::in) {
294 _Elem* target;
295 switch (way) {
296 case std::ios_base::beg: target = eback() + static_cast<ptrdiff_t>(off); break;
297 case std::ios_base::cur: target = gptr() + static_cast<ptrdiff_t>(off); break;
298 case std::ios_base::end: target = egptr() + static_cast<ptrdiff_t>(off); break;
299 default: throw std::invalid_argument("invalid seek reference");
300 }
301 if (eback() <= target && target <= egptr()) {
302 gbump(static_cast<int>(target - gptr()));
303 return pos_type{ off_type{ target - eback() } };
304 }
305 }
306 return pos_type{ off_type{-1} };
307 }
308
309 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
310 {
311 if (which & std::ios_base::in) {
312 _Elem* target = eback() + static_cast<size_t>(pos);
313 if (eback() <= target && target <= egptr()) {
314 gbump(static_cast<int>(target - gptr()));
315 return pos_type{ off_type{ target - eback() } };
316 }
317 }
318 return pos_type{ off_type{-1} };
319 }
320 };
321
322 template <class _Elem, class _Traits>
323 class basic_isharedstrstream : public std::basic_istream<_Elem, _Traits>
324 {
325 public:
326 basic_isharedstrstream(_In_reads_(size) const _Elem* data, _In_ size_t size) :
327 m_buf(data, size),
328 std::basic_istream<_Elem, _Traits>(&m_buf)
329 {}
330
331 protected:
333 };
334
337
343 template <class _Elem, class _Traits>
344 class basic_diagstreambuf : public std::basic_streambuf<_Elem, _Traits>
345 {
346 public:
347 using guest_stream = std::basic_iostream<_Elem, _Traits>;
348
349 basic_diagstreambuf(_In_reads_(count) guest_stream* const* streams, _In_ size_t count) : m_streams(stream, count) {}
350
351 template<typename _Iter>
352 basic_diagstreambuf(_In_ const _Iter first, _In_ const _Iter last) : m_streams(first, last) {}
353
354 private:
359
360 protected:
361 virtual pos_type seekoff(off_type off, std::ios_base::seekdir way, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
362 {
363 if (m_streams.empty())
364 return pos_type{ off_type{-1} };
365 auto r = pos_type{ off_type{-1} };
366 if ((which & std::ios_base::in)) {
367 m_streams[0]->seekg(off, way);
368 r = m_streams[0]->bad() ? pos_type{ off_type{-1} } : m_streams[0]->tellg();
369 for (size_t i = 1, n = m_streams.size(); i < n; ++i) {
370 m_streams[i]->seekg(off, way);
371 if (m_streams[i]->bad())
372 r = pos_type{ off_type{-1} };
373 }
374 }
375 if ((which & std::ios_base::out)) {
376 m_streams[0]->seekp(off, way);
377 r = m_streams[0]->bad() ? pos_type{ off_type{-1} } : m_streams[0]->tellp();
378 for (size_t i = 1, n = m_streams.size(); i < n; ++i) {
379 m_streams[i]->seekp(off, way);
380 if (m_streams[i]->bad())
381 r = pos_type{ off_type{-1} };
382 }
383 }
384 return r;
385 }
386
387 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
388 {
389 return seekoff(pos, std::ios_base::beg, which);
390 }
391
392 virtual int_type underflow()
393 {
394 int_type eof = _Traits::eof();
395 if (m_streams.empty())
396 eof;
397 _Elem data;
398 m_streams[0]->read(&data, 1);
399 int_type r = m_streams[0]->gcount() == 1 ? _Traits::to_int_type(data) : eof;
400 for (size_t i = 1, n = m_streams.size(); i < n; ++i) {
401 m_streams[i]->read(&data, 1);
402 int_type temp_r = m_streams[i]->gcount() == 1 ? _Traits::to_int_type(data) : eof;
403 if (r != temp_r)
404 r = eof;
405 }
406 return r;
407 }
408
409 virtual int_type overflow(int_type ch = _Traits::eof())
410 {
411 if (_Traits::not_eof(ch)) {
412 _Elem data = _Traits::to_char_type(ch);
413 bool good = true;
414 for (size_t i = 0, n = m_streams.size(); i < n; ++i) {
415 m_streams[i]->write(&data, 1);
416 good &= m_streams[i]->good();
417 }
418 return good ? 0 : _Traits::eof();
419 }
420 return 0;
421 }
422
423 virtual int sync()
424 {
425 int r = 0;
426 for (size_t i = 0, n = m_streams.size(); i < n; ++i)
427 if (m_streams[i]->sync() < 0)
428 r = -1;
429 return r;
430 }
431
432 protected:
433 std::vector<guest_stream*> m_streams;
434 };
435
442 template <class _Elem, class _Traits>
443 class basic_diagstream : public std::basic_iostream<_Elem, _Traits>
444 {
445 public:
446 using guest_stream = std::basic_iostream<_Elem, _Traits>;
447
448 basic_diagstream(_In_reads_(count) guest_stream* const* streams, _In_ size_t count) :
449 m_buf(streams, count),
450 std::basic_iostream<_Elem, _Traits>(&m_buf)
451 {}
452
453 template<typename _Iter>
454 basic_diagstream(_In_ const _Iter first, _In_ const _Iter last) :
455 m_buf(first, last),
456 std::basic_iostream<_Elem, _Traits>(&m_buf)
457 {}
458
459 protected:
461 };
462
465
466#ifdef _WIN32
468 template struct robber<getter<FILE*, std::filebuf>, &std::filebuf::_Myfile>;
469 template struct robber<getter<FILE*, std::wfilebuf>, &std::wfilebuf::_Myfile>;
470
471 inline FILE* filebuf_fhandle(_In_ std::filebuf* rb)
472 {
473 return (*rb).*get(getter<FILE*, std::filebuf>());
474 }
475
476 inline FILE* filebuf_fhandle(_In_ std::wfilebuf* rb)
477 {
478 return (*rb).*get(getter<FILE*, std::wfilebuf>());
479 }
481#endif
482
486 template <class _Elem, class _Traits>
487 class basic_fstream : public std::basic_fstream<_Elem, _Traits>
488 {
489 public:
490 using _Mybase = std::basic_fstream<_Elem, _Traits>;
491#if _HAS_CXX20
492 using time_point = std::chrono::time_point<std::chrono::file_clock>;
493#else
494 using time_point = std::chrono::time_point<std::chrono::system_clock>;
495#endif
496
497 basic_fstream() {}
498
499 explicit basic_fstream(
500 _In_z_ const char* file_name,
501 _In_ ios_base::openmode mode = ios_base::in | ios_base::out,
502 _In_ int prot = ios_base::_Default_open_prot) : _Mybase(file_name, mode, prot) {}
503
504 explicit basic_fstream(
505 _In_z_ const wchar_t* file_name,
506 _In_ ios_base::openmode mode = ios_base::in | ios_base::out,
507 _In_ int prot = ios_base::_Default_open_prot) : _Mybase(file_name, mode, prot) {}
508
509 template<class _Elem2, class _Traits2, class _Ax>
510 explicit basic_fstream(
511 _In_ const std::basic_string<_Elem2, _Traits2, _Ax>& str,
512 _In_ ios_base::openmode mode = ios_base::in | ios_base::out,
513 _In_ int prot = ios_base::_Default_open_prot) : basic_fstream(str.c_str(), mode, prot) {}
514
515 explicit basic_fstream(_In_ FILE* file) : _Mybase(file) {}
516
517 basic_fstream(_Inout_ basic_fstream&& other) : _Mybase(std::move(other)) {}
518
522 void truncate()
523 {
524 flush();
525 auto h = os_fhandle();
526#ifdef _WIN32
527 if (h == INVALID_HANDLE_VALUE)
528 throw std::runtime_error("invalid handle");
529 auto pos = tellp();
530 LONG
531 pos_lo = static_cast<LONG>(pos & 0xffffffff),
532 pos_hi = static_cast<LONG>((pos >> 32) & 0xffffffff);
533 if (SetFilePointer(h, pos_lo, &pos_hi, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
534 throw std::runtime_error("failed to seek");
535 if (!SetEndOfFile(h))
536 throw std::runtime_error("failed to truncate");
537#else
538#error Implement!
539#endif
540 }
541
547 time_point mtime() const
548 {
549 auto h = os_fhandle();
550#ifdef _WIN32
551 if (h == INVALID_HANDLE_VALUE)
552 throw std::runtime_error("invalid handle");
553 FILETIME ft;
554 if (!GetFileTime(h, NULL, NULL, &ft))
555 throw std::runtime_error("failed to get mtime");
556#if _HAS_CXX20
557 return time_point(time_point::duration(((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime)));
558#else
559 // Adjust epoch to std::chrono::time_point<std::chrono::system_clock>/time_t.
560 return time_point(time_point::duration(((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll));
561#endif
562#else
563#error Implement!
564#endif
565 }
566
567 protected:
568#ifdef _WIN32
569 HANDLE os_fhandle() const
570 {
571 FILE* f = filebuf_fhandle(rdbuf());
572 if (f == NULL)
573 return INVALID_HANDLE_VALUE;
574
575 int fd = _fileno(f);
576 if (fd == -1)
577 return INVALID_HANDLE_VALUE;
578
579 return (HANDLE)_get_osfhandle(fd);
580 }
581#else
582#error Implement!
583#endif
584 };
585
586 using fstream = basic_fstream<char, std::char_traits<char>>;
587 using wfstream = basic_fstream<wchar_t, std::char_traits<wchar_t>>;
588
592 template <class _Elem, class _Traits, class _Alloc>
593 class basic_stringstream : public std::basic_stringstream<_Elem, _Traits, _Alloc> {
594 public:
595 using _Mybase = std::basic_stringstream<_Elem, _Traits, _Alloc>;
596 using _Mystr = std::basic_string<_Elem, _Traits, _Alloc>;
597
599 explicit basic_stringstream(_In_ std::ios_base::openmode mode) : _Mybase(mode) {}
600 explicit basic_stringstream(_In_ const _Mystr& str, _In_ std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : _Mybase(str, mode) {}
601 basic_stringstream(_Inout_ basic_stringstream&& other) : _Mybase(std::move(other)) {}
602
610 template <class T>
611 explicit basic_stringstream(_In_z_ const T* filename, _In_ std::ios_base::openmode mode = std::ios_base::in, _In_ int prot = std::ios_base::_Default_open_prot) :
612 _Mybase(std::ios_base::in | std::ios_base::out | (mode & std::ios_base::binary | std::ios_base::app))
613 {
614 std::basic_ifstream<_Elem, _Traits> input(filename, mode & ~(std::ios_base::ate | std::ios_base::app), prot);
615 input.seekg(0, input.end);
616 auto size = input.tellg();
617 if (size > SIZE_MAX)
618 throw std::runtime_error("file too big to fit into memory");
619 str().reserve(static_cast<size_t>(size));
620 input.seekg(0);
621 do {
622 _Elem buf[0x1000];
623 input.read(buf, _countof(buf));
624 write(buf, input.gcount());
625 } while (!input.eof());
626 if (!(mode & (std::ios_base::ate | std::ios_base::app)))
627 seekp(0);
628 }
629
637 template <class _Elem2, class _Traits2 = std::char_traits<_Elem2>, class _Alloc2 = std::allocator<_Elem2>>
638 explicit basic_stringstream(_In_ const std::basic_string<_Elem2, _Traits2, _Alloc2>& filename, _In_ std::ios_base::openmode mode = std::ios_base::in, _In_ int prot = std::ios_base::_Default_open_prot) :
639 basic_stringstream(filename.c_str(), mode, prot)
640 {}
641
649 template <class T>
650 void save(_In_z_ const T* filename, _In_ std::ios_base::openmode mode = std::ios_base::out, _In_ int prot = std::ios_base::_Default_open_prot)
651 {
652 std::basic_ofstream<_Elem, _Traits> output(filename, mode, prot);
653 auto origin = tellg();
654 seekg(0, end);
655 auto size = tellg();
656 do {
657 _Elem buf[0x1000];
658 read(buf, _countof(buf));
659 output.write(buf, gcount());
660 } while (!eof());
661 seekg(origin);
662 }
663
664 template <class _Elem2, class _Traits2 = std::char_traits<T>, class _Alloc2 = std::allocator<T>>
665 void save(_In_ const std::basic_string<_Elem2, _Traits2, _Alloc2>& filename, _In_ std::ios_base::openmode mode = std::ios_base::out, _In_ int prot = std::ios_base::_Default_open_prot)
666 {
667 save(filename.data(), mode, prot);
668 }
669 };
670
671 using stringstream = basic_stringstream<char, std::char_traits<char>, std::allocator<char>>;
672 using wstringstream = basic_stringstream<wchar_t, std::char_traits<wchar_t>, std::allocator<char>>;
673}
Diagnostic input/output stream.
Definition ios.hpp:444
Diagnostic input stream buffer.
Definition ios.hpp:345
File stream with additional std::filesystem features.
Definition ios.hpp:488
time_point mtime() const
Returns file modification time.
Definition ios.hpp:547
void truncate()
Sets end of file at current put position.
Definition ios.hpp:522
Binary stream reader/writer.
Definition ios.hpp:251
Definition ios.hpp:324
Binary stream reader.
Definition ios.hpp:152
Binary stream writer.
Definition ios.hpp:33
void vprintf(const _Elem2 *format, locale_t locale, va_list arg)
Formats string using printf() and write it to stream.
Definition ios.hpp:101
void printf(const _Elem2 *format, locale_t locale,...)
Formats string using printf() and write it to stream.
Definition ios.hpp:115
Shared-memory string stream buffer.
Definition ios.hpp:267
String stream.
Definition ios.hpp:593
basic_stringstream(const T *filename, std::ios_base::openmode mode=std::ios_base::in, int prot=std::ios_base::_Default_open_prot)
Initializes stream with content from file.
Definition ios.hpp:611
void save(const T *filename, std::ios_base::openmode mode=std::ios_base::out, int prot=std::ios_base::_Default_open_prot)
Saves stream content to a file.
Definition ios.hpp:650
basic_stringstream(const std::basic_string< _Elem2, _Traits2, _Alloc2 > &filename, std::ios_base::openmode mode=std::ios_base::in, int prot=std::ios_base::_Default_open_prot)
Initializes stream with content from file.
Definition ios.hpp:638
Helper template to allow access to internal std C++ private members.
Definition internal.hpp:30
Helper template to allow access to internal std C++ private members.
Definition internal.hpp:18