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 template<typename _Iter>
350 basic_diagstreambuf(_In_ const _Iter first, _In_ const _Iter last) : m_streams(first, last) {}
351 basic_diagstreambuf(_In_reads_(count) guest_stream* const* streams, _In_ size_t count) : basic_diagstreambuf(streams, streams + count) {}
352
353 private:
358
359 protected:
360 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)
361 {
362 if (m_streams.empty())
363 return pos_type{ off_type{-1} };
364 auto r = pos_type{ off_type{-1} };
365 if ((which & std::ios_base::in)) {
366 m_streams[0]->seekg(off, way);
367 r = m_streams[0]->bad() ? pos_type{ off_type{-1} } : m_streams[0]->tellg();
368 for (size_t i = 1, n = m_streams.size(); i < n; ++i) {
369 m_streams[i]->seekg(off, way);
370 if (m_streams[i]->bad())
371 r = pos_type{ off_type{-1} };
372 }
373 }
374 if ((which & std::ios_base::out)) {
375 m_streams[0]->seekp(off, way);
376 r = m_streams[0]->bad() ? pos_type{ off_type{-1} } : m_streams[0]->tellp();
377 for (size_t i = 1, n = m_streams.size(); i < n; ++i) {
378 m_streams[i]->seekp(off, way);
379 if (m_streams[i]->bad())
380 r = pos_type{ off_type{-1} };
381 }
382 }
383 return r;
384 }
385
386 virtual pos_type seekpos(pos_type pos, std::ios_base::openmode which = std::ios_base::in | std::ios_base::out)
387 {
388 return seekoff(pos, std::ios_base::beg, which);
389 }
390
391 virtual int_type underflow()
392 {
393 int_type eof = _Traits::eof();
394 if (m_streams.empty())
395 eof;
396 _Elem data;
397 m_streams[0]->read(&data, 1);
398 int_type r = m_streams[0]->gcount() == 1 ? _Traits::to_int_type(data) : eof;
399 for (size_t i = 1, n = m_streams.size(); i < n; ++i) {
400 m_streams[i]->read(&data, 1);
401 int_type temp_r = m_streams[i]->gcount() == 1 ? _Traits::to_int_type(data) : eof;
402 if (r != temp_r)
403 r = eof;
404 }
405 return r;
406 }
407
408 virtual int_type overflow(int_type ch = _Traits::eof())
409 {
410 if (_Traits::not_eof(ch)) {
411 _Elem data = _Traits::to_char_type(ch);
412 bool good = true;
413 for (size_t i = 0, n = m_streams.size(); i < n; ++i) {
414 m_streams[i]->write(&data, 1);
415 good &= m_streams[i]->good();
416 }
417 return good ? 0 : _Traits::eof();
418 }
419 return 0;
420 }
421
422 virtual int sync()
423 {
424 int r = 0;
425 for (size_t i = 0, n = m_streams.size(); i < n; ++i)
426 if (m_streams[i]->sync() < 0)
427 r = -1;
428 return r;
429 }
430
431 protected:
432 std::vector<guest_stream*> m_streams;
433 };
434
441 template <class _Elem, class _Traits>
442 class basic_diagstream : public std::basic_iostream<_Elem, _Traits>
443 {
444 public:
445 using guest_stream = std::basic_iostream<_Elem, _Traits>;
446
447 template<typename _Iter>
448 basic_diagstream(_In_ const _Iter first, _In_ const _Iter last) :
449 m_buf(first, last),
450 std::basic_iostream<_Elem, _Traits>(&m_buf)
451 {}
452
453 basic_diagstream(_In_reads_(count) guest_stream* const* streams, _In_ size_t count) :
454 basic_diagstream(streams, streams + count)
455 {}
456
457 protected:
459 };
460
463
464#ifdef _WIN32
466 template struct robber<getter<FILE*, std::filebuf>, &std::filebuf::_Myfile>;
467 template struct robber<getter<FILE*, std::wfilebuf>, &std::wfilebuf::_Myfile>;
468
469 inline FILE* filebuf_fhandle(_In_ std::filebuf* rb)
470 {
471 return (*rb).*get(getter<FILE*, std::filebuf>());
472 }
473
474 inline FILE* filebuf_fhandle(_In_ std::wfilebuf* rb)
475 {
476 return (*rb).*get(getter<FILE*, std::wfilebuf>());
477 }
479#endif
480
484 template <class _Elem, class _Traits>
485 class basic_fstream : public std::basic_fstream<_Elem, _Traits>
486 {
487 public:
488 using _Mybase = std::basic_fstream<_Elem, _Traits>;
489#if _HAS_CXX20
490 using time_point = std::chrono::time_point<std::chrono::file_clock>;
491#else
492 using time_point = std::chrono::time_point<std::chrono::system_clock>;
493#endif
494
495 basic_fstream() {}
496
497 explicit basic_fstream(
498 _In_z_ const char* file_name,
499 _In_ ios_base::openmode mode = ios_base::in | ios_base::out,
500 _In_ int prot = ios_base::_Default_open_prot) : _Mybase(file_name, mode, prot) {}
501
502 explicit basic_fstream(
503 _In_z_ const wchar_t* file_name,
504 _In_ ios_base::openmode mode = ios_base::in | ios_base::out,
505 _In_ int prot = ios_base::_Default_open_prot) : _Mybase(file_name, mode, prot) {}
506
507 template<class _Elem2, class _Traits2, class _Ax>
508 explicit basic_fstream(
509 _In_ const std::basic_string<_Elem2, _Traits2, _Ax>& str,
510 _In_ ios_base::openmode mode = ios_base::in | ios_base::out,
511 _In_ int prot = ios_base::_Default_open_prot) : basic_fstream(str.c_str(), mode, prot) {}
512
513 explicit basic_fstream(_In_ FILE* file) : _Mybase(file) {}
514
515 basic_fstream(_Inout_ basic_fstream&& other) : _Mybase(std::move(other)) {}
516
520 void truncate()
521 {
522 flush();
523 auto h = os_fhandle();
524#ifdef _WIN32
525 if (h == INVALID_HANDLE_VALUE)
526 throw std::runtime_error("invalid handle");
527 auto pos = tellp();
528 LONG
529 pos_lo = static_cast<LONG>(pos & 0xffffffff),
530 pos_hi = static_cast<LONG>((pos >> 32) & 0xffffffff);
531 if (SetFilePointer(h, pos_lo, &pos_hi, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
532 throw std::runtime_error("failed to seek");
533 if (!SetEndOfFile(h))
534 throw std::runtime_error("failed to truncate");
535#else
536#error Implement!
537#endif
538 }
539
545 time_point mtime() const
546 {
547 auto h = os_fhandle();
548#ifdef _WIN32
549 if (h == INVALID_HANDLE_VALUE)
550 throw std::runtime_error("invalid handle");
551 FILETIME ft;
552 if (!GetFileTime(h, NULL, NULL, &ft))
553 throw std::runtime_error("failed to get mtime");
554#if _HAS_CXX20
555 return time_point(time_point::duration(((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime)));
556#else
557 // Adjust epoch to std::chrono::time_point<std::chrono::system_clock>/time_t.
558 return time_point(time_point::duration(((static_cast<int64_t>(ft.dwHighDateTime) << 32) | ft.dwLowDateTime) - 116444736000000000ll));
559#endif
560#else
561#error Implement!
562#endif
563 }
564
565 protected:
566#ifdef _WIN32
567 HANDLE os_fhandle() const
568 {
569 FILE* f = filebuf_fhandle(rdbuf());
570 if (f == NULL)
571 return INVALID_HANDLE_VALUE;
572
573 int fd = _fileno(f);
574 if (fd == -1)
575 return INVALID_HANDLE_VALUE;
576
577 return (HANDLE)_get_osfhandle(fd);
578 }
579#else
580#error Implement!
581#endif
582 };
583
584 using fstream = basic_fstream<char, std::char_traits<char>>;
585 using wfstream = basic_fstream<wchar_t, std::char_traits<wchar_t>>;
586
590 template <class _Elem, class _Traits, class _Alloc>
591 class basic_stringstream : public std::basic_stringstream<_Elem, _Traits, _Alloc> {
592 public:
593 using _Mybase = std::basic_stringstream<_Elem, _Traits, _Alloc>;
594 using _Mystr = std::basic_string<_Elem, _Traits, _Alloc>;
595
597 explicit basic_stringstream(_In_ std::ios_base::openmode mode) : _Mybase(mode) {}
598 explicit basic_stringstream(_In_ const _Mystr& str, _In_ std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) : _Mybase(str, mode) {}
599 basic_stringstream(_Inout_ basic_stringstream&& other) : _Mybase(std::move(other)) {}
600
608 template <class T>
609 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) :
610 _Mybase(std::ios_base::in | std::ios_base::out | (mode & std::ios_base::binary | std::ios_base::app))
611 {
612 std::basic_ifstream<_Elem, _Traits> input(filename, mode & ~(std::ios_base::ate | std::ios_base::app), prot);
613 input.seekg(0, input.end);
614 auto size = input.tellg();
615 if (size > SIZE_MAX)
616 throw std::runtime_error("file too big to fit into memory");
617 str().reserve(static_cast<size_t>(size));
618 input.seekg(0);
619 do {
620 _Elem buf[0x1000];
621 input.read(buf, _countof(buf));
622 write(buf, input.gcount());
623 } while (!input.eof());
624 if (!(mode & (std::ios_base::ate | std::ios_base::app)))
625 seekp(0);
626 }
627
635 template <class _Elem2, class _Traits2 = std::char_traits<_Elem2>, class _Alloc2 = std::allocator<_Elem2>>
636 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) :
637 basic_stringstream(filename.c_str(), mode, prot)
638 {}
639
647 template <class T>
648 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)
649 {
650 std::basic_ofstream<_Elem, _Traits> output(filename, mode, prot);
651 auto origin = tellg();
652 seekg(0, end);
653 auto size = tellg();
654 do {
655 _Elem buf[0x1000];
656 read(buf, _countof(buf));
657 output.write(buf, gcount());
658 } while (!eof());
659 seekg(origin);
660 }
661
662 template <class _Elem2, class _Traits2 = std::char_traits<T>, class _Alloc2 = std::allocator<T>>
663 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)
664 {
665 save(filename.data(), mode, prot);
666 }
667 };
668
669 using stringstream = basic_stringstream<char, std::char_traits<char>, std::allocator<char>>;
670 using wstringstream = basic_stringstream<wchar_t, std::char_traits<wchar_t>, std::allocator<char>>;
671}
Diagnostic input/output stream.
Definition ios.hpp:443
Diagnostic input stream buffer.
Definition ios.hpp:345
File stream with additional std::filesystem features.
Definition ios.hpp:486
time_point mtime() const
Returns file modification time.
Definition ios.hpp:545
void truncate()
Sets end of file at current put position.
Definition ios.hpp:520
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:591
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:609
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:648
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:636
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