memoryStreamBuffer.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2016-2025 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 Class
27  Foam::memorybuf
28 
29 Description
30  A std::streambuf used for memory buffer streams such as
31  ispanstream, ocharstream, etc.
32 
33 \*---------------------------------------------------------------------------*/
34 
35 #ifndef Foam_memoryStreamBuffer_H
36 #define Foam_memoryStreamBuffer_H
37 
38 #include "stdFoam.H" // For span
39 #include "DynamicList.H"
40 
41 #include <memory>
42 #include <type_traits>
43 
44 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
45 
46 namespace Foam
47 {
48 
49 /*---------------------------------------------------------------------------*\
50  Class memorybuf Declaration
51 \*---------------------------------------------------------------------------*/
52 
53 //- A streambuf for memory similar to std::spanbuf (C++23)
54 class memorybuf
55 :
56  public std::streambuf
57 {
58 protected:
59 
60  //- Set position pointer to relative position
61  virtual std::streampos seekoff
62  (
63  std::streamoff off,
64  std::ios_base::seekdir way,
65  std::ios_base::openmode which = std::ios_base::in|std::ios_base::out
66  )
67  {
68  const bool testin = which & std::ios_base::in;
69  const bool testout = which & std::ios_base::out;
70 
71  if (way == std::ios_base::beg)
72  {
73  if (testin)
74  {
75  setg(eback(), eback(), egptr());
76  gbump(off);
77  }
78  if (testout)
79  {
80  setp(pbase(), epptr());
81  pbump(off);
82  }
83  }
84  else if (way == std::ios_base::cur)
85  {
86  if (testin)
87  {
88  gbump(off);
89  }
90  if (testout)
91  {
92  pbump(off);
93  }
94  }
95  else if (way == std::ios_base::end)
96  {
97  if (testin)
98  {
99  setg(eback(), eback(), egptr());
100  gbump(egptr() - eback() - off);
101  }
102  if (testout)
103  {
104  setp(pbase(), epptr());
105  pbump(epptr() - pbase() - off);
106  }
107  }
108 
109  if (testin)
110  {
111  return (gptr() - eback()); // span_tellg()
112  }
113  if (testout)
114  {
115  return (pptr() - pbase()); // span_tellp()
116  }
117 
118  return -1;
119  }
120 
121 
122  //- Set position pointer to absolute position
123  virtual std::streampos seekpos
124  (
125  std::streampos pos,
126  std::ios_base::openmode which = std::ios_base::in|std::ios_base::out
127  )
128  {
129  return seekoff(pos, std::ios_base::beg, which);
130  }
131 
132 public:
133 
134  // Forward Declarations
135  class in_base;
136  class in_dynamic;
137  class out_base;
138  class out_dynamic;
139 };
140 
141 
142 /*---------------------------------------------------------------------------*\
143  Class memorybuf::in_base Declaration
144 \*---------------------------------------------------------------------------*/
145 
146 //- The base input streambuf with memory access
147 class memorybuf::in_base
148 :
149  public memorybuf
150 {
151 protected:
152 
153  //- Get sequence of characters from a fixed region
154  virtual std::streamsize xsgetn(char* s, std::streamsize n)
155  {
156  std::streamsize count = 0;
157  while (count < n && gptr() < egptr())
158  {
159  *(s + count++) = *(gptr());
160  gbump(1);
161  }
162  return count;
163  }
164 
165 public:
166 
167  // Constructors
168 
169  //- Default construct
170  in_base() = default;
171 
172  //- Construct for character array (can be nullptr) and number of bytes
173  in_base(char* s, std::streamsize n)
174  {
175  resetg(s, n);
176  }
177 
178 
179  // Member Functions
181  // //- Reset get buffer pointer to the beginning of existing span
182  // void rewind() { setg(eback(), eback(), egptr()); }
183 
184  //- Reset get buffer with character data (can be nullptr) and count
185  // Sets get pointer to the begin.
186  void resetg(char* s, std::streamsize n)
187  {
188  if (s)
189  {
190  setg(s, s, s + n);
191  }
192  else
193  {
194  setg(nullptr, nullptr, nullptr);
195  }
196  }
197 
198  //- The current buffer get position
199  std::streamsize span_tellg() const { return (gptr() - eback()); }
200 
201  //- The get buffer capacity
202  std::streamsize span_capacity() const { return (egptr() - eback()); }
203 
204  //- The number of characters remaining in the get area
205  std::streamsize span_remaining() const
206  {
207  return (gptr() < egptr()) ? (egptr() - gptr()) : 0;
208  }
209 
210  //- The span data (start of input characters)
211  char* data_bytes() const { return eback(); }
212 
213  //- The span size (number of input characters)
214  std::streamsize size_bytes() const { return (egptr() - eback()); }
215 
216  std::string_view view() const
217  {
218  return std::string_view(data_bytes(), size_bytes());
219  }
220 
221  //- Some information about the input buffer position/capacity
222  void info(Ostream& os) const
223  {
224  os << "get=" << span_tellg() << '/' << span_capacity();
225  }
226 };
227 
228 
229 /*---------------------------------------------------------------------------*\
230  Class memorybuf::in_dynamic Declaration
231 \*---------------------------------------------------------------------------*/
232 
233 //- An output streambuf for memory access
235 :
237 {
238 private:
239 
240  //- Character storage
241  List<char> storage_;
242 
243 
244 public:
245 
246  // Constructors
247 
248  //- Default construct - empty
249  in_dynamic() = default;
250 
251  //- Copy construct from content
252  in_dynamic(const char* s, std::streamsize n)
253  {
254  if (s && n)
255  {
256  storage_.resize_nocopy(n);
257  std::copy(s, (s + n), storage_.data());
258  }
259  sync_gbuffer();
260  }
261 
262  //- Move construct from List
263  in_dynamic(::Foam::List<char>&& buffer)
264  :
265  storage_(std::move(buffer))
266  {
267  sync_gbuffer();
268  }
269 
270  //- Move construct from DynamicList (added length only)
271  template<int SizeMin>
273  {
274  storage_.transfer(buffer); // Implies shrink_to_fit
275  sync_gbuffer();
276  }
277 
278 
279  // Member Functions
280 
281  //- Sync get buffer pointers to agree with list dimensions
282  // Sets get pointer to the begin (rewind).
283  void sync_gbuffer()
284  {
285  resetg(storage_.data(), storage_.size());
286  }
287 
288  //- Reset content (copy)
289  void reset(const char* s, std::streamsize n)
290  {
291  if (s && n)
292  {
293  storage_.resize_nocopy(n);
294  std::copy(s, (s + n), storage_.data());
295  }
296  else
297  {
298  storage_.clear();
299  }
300  sync_gbuffer();
301  }
302 
303  //- Exchange buffer content and parameter contents, reset positions
304  void swap(List<char>& other)
305  {
306  other.swap(storage_); // Swap contents
307  sync_gbuffer();
308  }
309 
310  //- Exchange buffer content and parameter contents, reset positions
311  template<int SizeMin>
312  void swap(DynamicList<char,SizeMin>& other)
313  {
314  // NB: not storage_.swap(other)! - incorrect slicing
315  other.swap(storage_); // Swap contents: implies shrink_to_fit
316  sync_gbuffer();
317  }
318 
319  //- Reset buffer and return contents
321  {
322  DynamicList<char> chars(std::move(storage_));
323  sync_gbuffer();
324  return chars;
325  }
326 };
327 
329 /*---------------------------------------------------------------------------*\
330  Class memorybuf::out_base Declaration
331 \*---------------------------------------------------------------------------*/
332 
333 //- An output streambuf for memory access
335 :
336  public memorybuf
337 {
338 protected:
339 
340  //- Put sequence of characters to a fixed region
341  virtual std::streamsize xsputn(const char* s, std::streamsize n)
342  {
343  std::streamsize count = 0;
344  while (count < n && pptr() < epptr())
345  {
346  *(pptr()) = *(s + count++);
347  pbump(1);
348  }
349  return count;
350  }
351 
352 public:
353 
354  // Constructors
356  //- Default construct
357  out_base() = default;
358 
359  //- Construct for character array (can be nullptr) and number of bytes
360  out_base(char* s, std::streamsize n)
361  {
362  resetp(s, n);
363  }
364 
366  // Member Functions
367 
368  // //- Reset put buffer pointer to the beginning of existing span
369  // void rewind() { setp(pbase(), epptr()); }
370 
371  //- Reset put buffer with character data (can be nullptr) and count
372  // Sets put pointer to the begin.
373  inline void resetp(char* s, std::streamsize n)
374  {
375  if (s)
376  {
377  // As per (std::ios_base::out && !std::ios_base::ate)
378  setp(s, s + n);
379  // No treatment for (std::ios_base::out && std::ios_base::ate)
380  }
381  else
382  {
383  setp(nullptr, nullptr);
384  }
385  }
386 
387  //- The current buffer put position
388  std::streamsize span_tellp() const { return (pptr() - pbase()); }
389 
390  //- The put buffer capacity
391  std::streamsize span_capacity() const { return (epptr() - pbase()); }
392 
393  //- The span data (start of output characters)
394  char* data_bytes() const { return pbase(); }
395 
396  //- The span size (size of output buffer)
397  std::streamsize size_bytes() const { return (pptr() - pbase()); }
398 
399  std::string_view view() const
400  {
401  return std::string_view(data_bytes(), size_bytes());
402  }
403 
404  //- Some information about the output buffer position/capacity
405  void info(Ostream& os) const
406  {
407  os << "put=" << span_tellp() << '/' << span_capacity();
408  }
409 };
410 
411 
412 /*---------------------------------------------------------------------------*\
413  Class memorybuf::out_dynamic Declaration
414 \*---------------------------------------------------------------------------*/
415 
416 //- An output streambuf for memory access
418 :
419  public memorybuf::out_base
420 {
421 private:
422 
423  //- Character storage.
424  // Internally manage like a DynamicList, with its capacity known
425  // from the list size and the addressable size known through the
426  // stream pointers.
427  List<char> storage_;
428 
429 protected:
430 
431  //- Handle overflow
432  virtual int overflow(int_type c = traits_type::eof())
433  {
434  if (c != traits_type::eof())
435  {
436  // Need more space?
437  reserve(1 + span_tellp());
438 
439  *(pptr()) = c;
440  pbump(1);
441  }
442  return c;
443  }
444 
445  //- Put sequence of characters
446  virtual std::streamsize xsputn(const char* s, std::streamsize n)
447  {
448  // Enough space so that appends work without problem
449  reserve(n + span_tellp());
450 
451  std::streamsize count = 0;
452  while (count < n && pptr() < epptr())
453  {
454  *(pptr()) = *(s + count++);
455  pbump(1);
456  }
457 
458  return count;
459  }
460 
462 public:
464  // Constructors
465 
466  //- Default construct with initial reserved number of bytes.
467  // The value of 512 is a bit arbitrary, but consistent with
468  // std::stringstream
469  out_dynamic(size_t nbytes = 512)
470  :
471  storage_(label(nbytes))
472  {
473  sync_pbuffer();
474  }
475 
476  //- Move construct from List
477  out_dynamic(::Foam::List<char>&& buffer)
478  :
479  storage_(std::move(buffer))
480  {
481  sync_pbuffer();
482  }
483 
484  //- Move construct from DynamicList (uses entire capacity)
485  template<int SizeMin>
487  {
488  buffer.resize(buffer.capacity()); // Use entire space
489  storage_.transfer(buffer);
490  sync_pbuffer();
491  }
492 
493 
494  // Member Functions
495 
496  //- Increment capacity (if needed) and adjust buffer pointers
497  void reserve(const std::streamsize len)
498  {
499  if (storage_.size() < len)
500  {
501  const auto cur = span_tellp(); // Current location
502 
503  label newCapacity = 512;
504 
505  if (newCapacity < len)
506  {
507  // Increase capacity (doubling)
508  newCapacity =
509  Foam::max(label(len), label(2*storage_.size()));
510  // ratio=1.5:
511  // Foam::max(label(len), label((storage_.size()/2)*3));
512  }
513 
514  // Info<<"request:" << len
515  // << " cur cap:" << storage_.size()
516  // << " new cap:" << newCapacity
517  // << " pos:" << cur << endl;
518 
519  storage_.resize(newCapacity);
520  sync_pbuffer();
521  pbump(cur);
522  }
523  }
524 
525  //- Sync put buffer pointers to agree with list dimensions
526  // Sets put pointer to the begin (rewind).
527  void sync_pbuffer()
528  {
529  resetp(storage_.data(), storage_.size());
530  }
531 
532  //- Clear storage
533  void clearStorage()
534  {
535  storage_.clear();
536  sync_pbuffer();
537  }
538 
539  //- Shrink storage to addressed storage
540  void shrink()
541  {
542  const auto cur = span_tellp(); // Addressed length
543 
544  storage_.resize(cur);
545  sync_pbuffer();
546  pbump(cur);
547  }
548 
549  //- Exchange buffer content and parameter contents, reset positions
550  void swap(List<char>& other)
551  {
552  const auto cur = span_tellp(); // Output length
553  other.swap(storage_);
554  other.resize(cur); // Truncate to output length
555  sync_pbuffer();
556  }
558  //- Exchange buffer content and parameter contents, reset positions
559  template<int SizeMin>
560  void swap(DynamicList<char,SizeMin>& other)
561  {
562  const auto cur = span_tellp(); // Output length
563 
564  other.resize(other.capacity()); // Use entire space
565  other.swap(storage_); // NB: not storage_.swap(other)
566  other.resize(cur); // Restrict to output length
567  sync_pbuffer();
568  }
569 
570  //- Reset buffer and return contents as a DynamicList.
571  //- The list size corresponds to the region of output.
573  {
574  const auto cur = span_tellp(); // Output length
575  DynamicList<char> chars(std::move(storage_));
576  chars.resize(cur); // Restrict to output length
577 
578  if (chars.empty()) chars.clearStorage(); // Can destroy now
579  sync_pbuffer();
580  return chars;
581  }
582 };
583 
584 
585 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
586 
587 } // End namespace Foam
588 
589 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
590 
591 #endif
592 
593 // ************************************************************************* //
void swap(UList< T > &list) noexcept
Swap content with another UList of the same type in constant time.
Definition: UListI.H:499
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
void resetg(char *s, std::streamsize n)
Reset get buffer with character data (can be nullptr) and count.
std::string_view view() const
DynamicList< char > release()
Reset buffer and return contents.
std::streamsize span_capacity() const
The put buffer capacity.
virtual int overflow(int_type c=traits_type::eof())
Handle overflow.
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:150
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition: List.C:337
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
std::streamsize span_capacity() const
The get buffer capacity.
bool empty() const noexcept
True if List is empty (ie, size() is zero)
Definition: UList.H:697
T * data() noexcept
Return pointer to the underlying array serving as data storage.
Definition: UListI.H:265
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:366
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:168
char * data_bytes() const
The span data (start of output characters)
out_base()=default
Default construct.
virtual std::streamsize xsgetn(char *s, std::streamsize n)
Get sequence of characters from a fixed region.
void info(Ostream &os) const
Some information about the output buffer position/capacity.
label capacity() const noexcept
Size of the underlying storage.
Definition: DynamicList.H:236
void swap(List< char > &other)
Exchange buffer content and parameter contents, reset positions.
dimensionedScalar pos(const dimensionedScalar &ds)
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
void clear()
Clear the list, i.e. set size to zero.
Definition: ListI.H:130
void shrink()
Shrink storage to addressed storage.
The base input streambuf with memory access.
std::streamsize span_remaining() const
The number of characters remaining in the get area.
virtual std::streampos seekpos(std::streampos pos, std::ios_base::openmode which=std::ios_base::in|std::ios_base::out)
Set position pointer to absolute position.
virtual std::streampos seekoff(std::streamoff off, std::ios_base::seekdir way, std::ios_base::openmode which=std::ios_base::in|std::ios_base::out)
Set position pointer to relative position.
std::string_view view() const
An output streambuf for memory access.
void swap(List< char > &other)
Exchange buffer content and parameter contents, reset positions.
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
virtual std::streamsize xsputn(const char *s, std::streamsize n)
Put sequence of characters to a fixed region.
virtual std::streamsize xsputn(const char *s, std::streamsize n)
Put sequence of characters.
OBJstream os(runTime.globalPath()/outputName)
void reserve(const std::streamsize len)
Increment capacity (if needed) and adjust buffer pointers.
void swap(List< T > &list)
Swap with plain List content. Implies shrink_to_fit().
Definition: DynamicListI.H:459
DynamicList< char > release()
Reset buffer and return contents as a DynamicList. The list size corresponds to the region of output...
in_dynamic()=default
Default construct - empty.
void sync_pbuffer()
Sync put buffer pointers to agree with list dimensions.
std::streamsize span_tellp() const
The current buffer put position.
void resetp(char *s, std::streamsize n)
Reset put buffer with character data (can be nullptr) and count.
void sync_gbuffer()
Sync get buffer pointers to agree with list dimensions.
void reset(const char *s, std::streamsize n)
Reset content (copy)
out_dynamic(size_t nbytes=512)
Default construct with initial reserved number of bytes.
const dimensionedScalar c
Speed of light in a vacuum.
const char * end
Definition: SVGTools.H:223
A streambuf for memory similar to std::spanbuf (C++23)
void clearStorage()
Clear the list and delete storage.
Definition: DynamicListI.H:425
Includes some common C++ headers, defines global macros and templates used in multiple places by Open...
label n
std::streamsize size_bytes() const
The span size (number of input characters)
void info(Ostream &os) const
Some information about the input buffer position/capacity.
std::streamsize size_bytes() const
The span size (size of output buffer)
void clearStorage()
Clear storage.
An output streambuf for memory access.
gmvFile<< "tracers "<< particles.size()<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().x()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().y()<< " ";}gmvFile<< nl;for(const passiveParticle &p :particles){ gmvFile<< p.position().z()<< " ";}gmvFile<< nl;forAll(lagrangianScalarNames, i){ word name=lagrangianScalarNames[i];IOField< scalar > s(IOobject(name, runTime.timeName(), cloud::prefix, mesh, IOobject::MUST_READ, IOobject::NO_WRITE))
An output streambuf for memory access.
in_base()=default
Default construct.
char * data_bytes() const
The span data (start of input characters)
std::streamsize span_tellg() const
The current buffer get position.
Namespace for OpenFOAM.