File: vtkMemoryResourceStream.h

package info (click to toggle)
paraview 5.13.2%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 544,220 kB
  • sloc: cpp: 3,374,605; ansic: 1,332,409; python: 150,381; xml: 122,166; sql: 65,887; sh: 7,317; javascript: 5,262; yacc: 4,417; java: 3,977; perl: 2,363; lex: 1,929; f90: 1,397; makefile: 170; objc: 153; tcl: 59; pascal: 50; fortran: 29
file content (203 lines) | stat: -rw-r--r-- 7,024 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
// SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
// SPDX-License-Identifier: BSD-3-Clause
#ifndef vtkMemoryResourceStream_h
#define vtkMemoryResourceStream_h

#include "vtkBuffer.h"       // vtkBuffer
#include "vtkIOCoreModule.h" // For export macro
#include "vtkResourceStream.h"

#include <memory>  // for std::unique_ptr
#include <string>  // for std::basic_string
#include <utility> // for std::forward
#include <vector>  // for std::vector

VTK_ABI_NAMESPACE_BEGIN

/**
 * @brief `vtkResourceStream` implementation for memory input.
 *
 * `vtkMemoryResourceStream` can be a view on existing data.
 * Or it can copy specified data into an internal buffer.
 * Or it can take ownership of a `vtkBuffer`, a `std::vector` or a `std::string`.
 */
class VTKIOCORE_EXPORT vtkMemoryResourceStream : public vtkResourceStream
{
  /**
   * @brief Base class of DataHolder, used to manage type erased data destruction.
   */
  struct BasicHolder
  {
    BasicHolder() = default;
    virtual ~BasicHolder() = default;
    BasicHolder(const BasicHolder&) = delete;
    BasicHolder& operator=(const BasicHolder&) = delete;
    BasicHolder(BasicHolder&&) noexcept = delete;
    BasicHolder& operator=(BasicHolder&&) noexcept = delete;
  };

  /**
   * @brief Simple single value container
   *
   * This struct is used to manage stream owned buffer lifetime.
   * Its only purpose is to be destroyer through its base class destructor.
   */
  template <typename T>
  struct DataHolder : public BasicHolder
  {
    template <typename... Args>
    DataHolder(Args&&... args)
      : Data{ std::forward<Args>(args)... }
    {
    }

    ~DataHolder() override = default;
    DataHolder(const DataHolder&) = delete;
    DataHolder& operator=(const DataHolder&) = delete;
    DataHolder(DataHolder&&) noexcept = delete;
    DataHolder& operator=(DataHolder&&) noexcept = delete;

    T Data;
  };

  // Small utility function to easily create a DataHolder with type deduction
  template <typename T>
  static std::unique_ptr<DataHolder<T>> MakeHolder(T&& value)
  {
    return std::unique_ptr<DataHolder<T>>{ new DataHolder<T>{ std::forward<T>(value) } };
  }

public:
  vtkTypeMacro(vtkMemoryResourceStream, vtkResourceStream);
  static vtkMemoryResourceStream* New();
  void PrintSelf(ostream& os, vtkIndent indent) override;

  ///@{
  /**
   * @brief Override vtkResourceStream functions
   */
  std::size_t Read(void* buffer, std::size_t bytes) override;
  bool EndOfStream() override;
  vtkTypeInt64 Seek(vtkTypeInt64 pos, SeekDirection dir) override;
  vtkTypeInt64 Tell() override;
  ///@}

  /**
   * @brief Set buffer to stream
   *
   * If `copy` is `false`, the source buffer must stay valid as it may be used.
   *
   * Otherwise, if `copy` is `true`, given buffer will be copied into an internally managed buffer.
   * If `size` is 0, this call won't allocate anything. If `size > 0`,
   * `buffer` must not be `nullptr` and must point to a contiguous buffer of at least `size` bytes.
   *
   * Regardless of `copy` value, this function also has the following effects:
   * - Reset stream position to `0`.
   * - EndOfStream will return `true` if `size` is `0`, `false` otherwise.
   * - Release currently owned buffer, if any.
   * - Increase modified time.
   *
   * @param buffer the buffer address, may be nullptr if `size` is 0.
   * @param size the buffer size in bytes, may be 0.
   * @param copy if `true` this function copies given buffer to an internally managed buffer.
   */
  void SetBuffer(const void* buffer, std::size_t size, bool copy = false);

  /**
   * @brief Set buffer to stream
   *
   * `this` will keep an owning reference to `buffer` (`buffer` reference count will be increased).
   * While `buffer` is streamed, it **must not** be invalidated (e.g. calling `vtkBuffer::Allocate`)
   * nor freed.
   * Also note that `buffer` content is still managed by the `vtkBuffer` instance, so it can be
   * modified externally.
   *
   * Streamed buffer is set as if by calling:
   * `SetBuffer(buffer->GetBuffer(), buffer->GetSize() * sizeof(T), false)`.
   * If `buffer` is nullptr, this function has the same effect as `SetBuffer(nullptr, 0)`.
   * When `buffer` is released, it only decrements the reference count.
   *
   * @param buffer `vtkBuffer` to stream, may be nullptr. `buffer` may also empty.
   */
  template <typename T>
  void SetBuffer(vtkSmartPointer<vtkBuffer<T>> buffer)
  {
    if (buffer)
    {
      this->SetBuffer(buffer->GetBuffer(), buffer->GetSize() * sizeof(T));
      this->Holder = MakeHolder(std::move(buffer));
    }
    else
    {
      this->SetBuffer(nullptr, 0);
    }
  }

  /**
   * @brief Set buffer to stream
   *
   * `this` will manage `vec` lifetime internally.
   *
   * Streamed buffer is set as if by calling:
   * `SetBuffer(vec.data(), vec.size() * sizeof(T), false)`.
   *
   * Note that this function takes `vec` by value:
   * - Call `SetBuffer(std::move(vec))` if you no longer need `vec` after the call.
   * This is the most efficient way, because it will not copy `vec` data at all,
   * it will only transfer ownership of `vec` to the stream.
   * - Call `SetBuffer(vec)` to copy vec. Useful if you need to keep `vec` on caller side.
   *
   * @param vec std::vector to stream, may be empty.
   */
  template <typename T, typename Allocator>
  void SetBuffer(std::vector<T, Allocator> vec)
  {
    this->SetBuffer(vec.data(), vec.size() * sizeof(T));
    this->Holder = MakeHolder(std::move(vec));
  }

  /**
   * @brief Set buffer to stream
   *
   * Same as `SetBuffer(std::vector<T, Allocator> vec)` but for `std::basic_string`.
   *
   * @param str std::string to stream, may be empty.
   */
  template <typename CharT, typename Traits, typename Allocator>
  void SetBuffer(std::basic_string<CharT, Traits, Allocator> str)
  {
    // unlike std::vector (and other containers), std::basic_string does not guarantee
    // iterators validity after a move (mainly for SSO).
    // So we have to move it prior to getting the pointer.
    auto holder = MakeHolder(std::move(str));
    this->SetBuffer(holder->Data.data(), holder->Data.size() * sizeof(CharT));
    this->Holder = std::move(holder);
  }

  /**
   * @brief Check if `this` has a internally managed buffer
   *
   * This is `true` after a call to `SetBuffer(vtkSmartPointer<vtkBuffer<T>>)`
   * even if only the reference count is managed by the stream.
   *
   * @return `true` if `this` manage streamed buffer, `false` otherwise.
   */
  bool OwnsBuffer() const { return this->Holder != nullptr; }

protected:
  vtkMemoryResourceStream();
  ~vtkMemoryResourceStream() override = default;
  vtkMemoryResourceStream(const vtkMemoryResourceStream&) = delete;
  vtkMemoryResourceStream& operator=(const vtkMemoryResourceStream&) = delete;

private:
  const unsigned char* Buffer = nullptr; // for pointer arithmetic
  std::size_t Size = 0;
  vtkTypeInt64 Pos = 0;
  bool Eos = false;
  std::unique_ptr<BasicHolder> Holder;
};

VTK_ABI_NAMESPACE_END

#endif