VTK  9.3.1
vtkResourceParser.h
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
2 // SPDX-License-Identifier: BSD-3-Clause
3 #ifndef vtkResourceParser_h
4 #define vtkResourceParser_h
5 
6 #include "vtkIOCoreModule.h" // For export macro
7 #include "vtkObject.h"
8 #include "vtkResourceStream.h" // For SeekDirection and vtkResourceStream
9 #include "vtkSmartPointer.h" // For vtkSmartPointer
10 
11 #include <array> // for std::array
12 #include <cstdint> // for std::int32_t
13 #include <cstdlib> // for std::size_t
14 #include <functional> // for std::function
15 #include <limits> // for std::numeric_limits
16 #include <memory> // for std::unique_ptr
17 #include <string> // for std::string
18 #include <type_traits> // for SFINAE helpers
19 
20 VTK_ABI_NAMESPACE_BEGIN
21 
22 #ifndef __VTK_WRAP__ // do not wrap
23 
32 enum class vtkParseResult : std::int32_t
33 {
34  Error = -1, // Value not parsed because of type or formatting error
35  Ok = 0, // Value parsed successfully, no special status
36  EndOfStream = 1, // No value parsed, stream reached its end
37  EndOfLine = 2, // No value parsed, this is an end of line
38  Limit = 3, // Value parsed successfully, limit has been reached
39 };
40 
57 class VTKIOCORE_EXPORT vtkResourceParser : public vtkObject
58 {
59 public:
63  using PredicateType = std::function<bool(char c)>;
64 
66 
74  static const PredicateType DiscardNone;
78 
82  using DataReceiverType = std::function<void(const char* data, std::size_t size)>;
83 
84  static constexpr std::size_t NoLimit = (std::numeric_limits<std::size_t>::max)();
85 
86 private:
90  class vtkInternals;
91 
95  class VTKIOCORE_EXPORT vtkParserContext
96  {
97  public:
98  vtkParserContext();
99  ~vtkParserContext();
100  vtkParserContext(const vtkParserContext&) = delete;
101  vtkParserContext& operator=(const vtkParserContext&) = delete;
102 
104  void SetStream(vtkResourceStream* stream);
106  vtkResourceStream* GetStream() const;
107 
109  bool GetStopOnNewLine() const;
111  void SetStopOnNewLine(bool on);
112 
114  vtkTypeInt64 Seek(vtkTypeInt64 pos, vtkResourceStream::SeekDirection dir);
116  vtkTypeInt64 Tell();
118  std::size_t Read(char* output, std::size_t size);
120  void Reset();
121 
123  template <typename T>
124  vtkParseResult Parse(T& output, const PredicateType& discardPred);
125 
127  vtkParseResult ReadUntil(
128  const PredicateType& discardPred, const DataReceiverType& receiver, std::size_t limit);
130  vtkParseResult DiscardUntil(const PredicateType& discardPred);
132  vtkParseResult ReadLine(const DataReceiverType& receiver, std::size_t limit);
133 
135  void PrintSelf(ostream& os, vtkIndent indent);
136 
137  private:
138  std::unique_ptr<vtkInternals> Impl;
139  };
140 
150  template <typename T>
151  static constexpr bool IsSupported()
152  {
153  // Only remove references to check const and volatile
154  using Type = typename std::remove_reference<T>::type;
155 
164  }
165 
166 public:
167  vtkTypeMacro(vtkResourceParser, vtkObject);
168  void PrintSelf(ostream& os, vtkIndent indent) override;
169  static vtkResourceParser* New();
170 
179  void SetStream(vtkResourceStream* stream) { this->Context.SetStream(stream); }
180 
186  vtkResourceStream* GetStream() const { return this->Context.GetStream(); }
187 
189 
197  bool GetStopOnNewLine() const { return this->Context.GetStopOnNewLine(); }
198  void SetStopOnNewLine(bool on) { this->Context.SetStopOnNewLine(on); }
199  vtkBooleanMacro(StopOnNewLine, bool);
201 
218  vtkTypeInt64 Seek(vtkTypeInt64 pos, vtkResourceStream::SeekDirection dir)
219  {
220  return this->Context.Seek(pos, dir);
221  }
222 
235  vtkTypeInt64 Tell() { return this->Context.Tell(); }
236 
247  std::size_t Read(char* output, std::size_t size) { return this->Context.Read(output, size); }
248 
258  void Reset() { this->Context.Reset(); }
259 
303  template <typename T, typename std::enable_if<IsSupported<T>(), bool>::type = true>
304  vtkParseResult Parse(T& output, const PredicateType& discardPred = DiscardWhitespace)
305  {
306  // Static check to prevent cryptic linker error
307  static_assert(IsSupported<T>(), "Unsupported type given to Parse function");
308  return this->Context.Parse(output, discardPred);
309  }
310 
326  const PredicateType& discardPred, const DataReceiverType& receiver, std::size_t limit = NoLimit)
327  {
328  return this->Context.ReadUntil(discardPred, receiver, limit);
329  }
330 
334  template <typename It>
336  {
343 
347  It Output;
348  };
349 
360  template <typename OutputIt>
362  const PredicateType& discardPred, OutputIt output, std::size_t limit = NoLimit)
363  {
364  const auto result = this->ReadUntil(
365  discardPred,
366  [&output](const char* data, std::size_t size) mutable {
367  for (std::size_t i{}; i < size; ++i)
368  {
369  *output++ = data[i];
370  }
371  },
372  limit);
373 
374  return ReadToResult<OutputIt>{ result, output };
375  }
376 
386  template <typename ForwardIt>
388  const PredicateType& discardPred, ForwardIt begin, ForwardIt end)
389  {
390  return this->ReadUntilTo(discardPred, begin, std::distance(begin, end));
391  }
392 
402  {
403  return this->Context.DiscardUntil(pred);
404  }
405 
432  vtkParseResult ReadLine(const DataReceiverType& receiver, std::size_t limit = NoLimit)
433  {
434  return this->Context.ReadLine(receiver, limit);
435  }
436 
452  template <typename Allocator>
454  std::basic_string<char, std::char_traits<char>, Allocator>& output, std::size_t limit = NoLimit)
455  {
456  output.clear();
457 
458  return this->ReadLine(
459  [&output](const char* data, std::size_t size) { output.append(data, size); }, limit);
460  }
461 
474  template <typename OutputIt>
475  ReadToResult<OutputIt> ReadLineTo(OutputIt output, std::size_t limit = NoLimit)
476  {
477  const auto result = this->ReadLine(
478  [&output](const char* data, std::size_t size) {
479  for (std::size_t i{}; i < size; ++i)
480  {
481  *output++ = data[i];
482  }
483  },
484  limit);
485 
486  return ReadToResult<OutputIt>{ result, output };
487  }
488 
501  template <typename ForwardIt>
502  ReadToResult<ForwardIt> ReadLineTo(ForwardIt begin, ForwardIt end)
503  {
504  return this->ReadLineTo(begin, std::distance(begin, end));
505  }
506 
517  vtkParseResult DiscardLine(std::size_t limit = NoLimit)
518  {
519  return this->ReadLine([](const char*, std::size_t) {}, limit);
520  }
521 
522 protected:
526  vtkResourceParser() = default;
527  ~vtkResourceParser() override = default;
528  vtkResourceParser(const vtkResourceParser&) = delete;
529  vtkResourceParser& operator=(const vtkResourceParser&) = delete;
530 
531 private:
532  vtkParserContext Context;
533 };
534 
535 #define DECLARE_PARSE_EXTERN_TEMPLATE(type) \
536  extern template VTKIOCORE_EXPORT vtkParseResult \
537  vtkResourceParser::vtkParserContext::Parse<type>(type&, const PredicateType& discardPred)
538 
539 // Declare explicit instantiation for all supported types
541 DECLARE_PARSE_EXTERN_TEMPLATE(signed char);
542 DECLARE_PARSE_EXTERN_TEMPLATE(unsigned char);
544 DECLARE_PARSE_EXTERN_TEMPLATE(unsigned short);
546 DECLARE_PARSE_EXTERN_TEMPLATE(unsigned int);
548 DECLARE_PARSE_EXTERN_TEMPLATE(unsigned long);
550 DECLARE_PARSE_EXTERN_TEMPLATE(unsigned long long);
555 
556 #undef DECLARE_PARSE_EXTERN_TEMPLATE
557 
558 #endif
559 
560 VTK_ABI_NAMESPACE_END
561 
562 #endif
abstract base class for most VTK objects
Definition: vtkObject.h:51
Abstract class used for custom streams.
std::size_t Read(char *output, std::size_t size)
Read data from the input stream.
Structure returned by Read*To functions.
static const PredicateType DiscardWhitespace
Prebuild predicates for common cases.
void SetStopOnNewLine(bool on)
Specifies if the parser should handle newlines as a special token to stop on.
vtkParseResult Parse(T &output, const PredicateType &discardPred=DiscardWhitespace)
Main parsing function.
ReadToResult< ForwardIt > ReadLineTo(ForwardIt begin, ForwardIt end)
Read an entire line from the input stream.
vtkResourceStream * GetStream() const
Get the parsed stream.
vtkTypeInt64 Seek(vtkTypeInt64 pos, vtkResourceStream::SeekDirection dir)
Move stream cursor.
ReadToResult< ForwardIt > ReadUntilTo(const PredicateType &discardPred, ForwardIt begin, ForwardIt end)
Read data from the input stream to any output range until the perdicate is met.
vtkParseResult DiscardUntil(const PredicateType &pred)
Discard data from the input stream until the perdicate is met.
Helper class to perform formatted input from vtkResourceStream.
void SetStream(vtkResourceStream *stream)
Set the stream to parse.
a simple class to control print indentation
Definition: vtkIndent.h:28
std::function< void(const char *data, std::size_t size)> DataReceiverType
receiver type used by ReadUntil function
#define DECLARE_PARSE_EXTERN_TEMPLATE(type)
vtkTypeInt64 Tell()
Get stream cursor position from parser context.
vtkParseResult
Result of a vtkResouceParser parsing operation.
vtkParseResult ReadLine(std::basic_string< char, std::char_traits< char >, Allocator > &output, std::size_t limit=NoLimit)
Read an entire line from the input stream.
ReadToResult< OutputIt > ReadLineTo(OutputIt output, std::size_t limit=NoLimit)
Read an entire line from the input stream.
std::function< bool(char c)> PredicateType
predicate type used by ReadUntil and DiscardUntil functions
static const PredicateType DiscardNone
Prebuild predicates for common cases.
void Reset()
Reset parser internal state.
vtkParseResult Result
vtkParseResult::EndOfStream if EOS is reached before pred is met or limit is reached.
vtkParseResult ReadUntil(const PredicateType &discardPred, const DataReceiverType &receiver, std::size_t limit=NoLimit)
Read data from the input stream until the perdicate is met.
ReadToResult< OutputIt > ReadUntilTo(const PredicateType &discardPred, OutputIt output, std::size_t limit=NoLimit)
Read data from the input stream to any output iterator until the perdicate is met.
static const PredicateType DiscardNonAlphaNumeric
Prebuild predicates for common cases.
vtkParseResult DiscardLine(std::size_t limit=NoLimit)
Discard a line from the input stream.
vtkParseResult ReadLine(const DataReceiverType &receiver, std::size_t limit=NoLimit)
Read an entire line from the input stream.
It Output
Iterator one past the last written value.
#define max(a, b)
bool GetStopOnNewLine() const
Specifies if the parser should handle newlines as a special token to stop on.