GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/options/managed_streams.h Lines: 17 24 70.8 %
Date: 2021-11-07 Branches: 3 8 37.5 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Gereon Kremer
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * Wrappers to handle memory management of streams.
14
 *
15
 * This file contains wrappers to handle special cases of managing memory
16
 * related to streams stored in options.
17
 */
18
19
#include "cvc5_public.h"
20
21
#ifndef CVC5__OPTIONS__MANAGED_STREAMS_H
22
#define CVC5__OPTIONS__MANAGED_STREAMS_H
23
24
#include <memory>
25
#include <ostream>
26
27
namespace cvc5 {
28
29
namespace detail {
30
/*
31
 * Open a file as an output stream and return it as a pointer. The caller
32
 * assumes the ownership of the returned pointer.
33
 */
34
std::ostream* openOStream(const std::string& filename);
35
/*
36
 * Open a file as an input stream and return it as a pointer. The caller
37
 * assumes the ownership of the returned pointer.
38
 */
39
std::istream* openIStream(const std::string& filename);
40
}  // namespace detail
41
42
/**
43
 * Implements memory management for streams, both input and output. It is
44
 * intended to be subclassed, where a subclass can provide a default value and
45
 * special cases. Usually, users should use one of these subclasses.
46
 * The template argument type should be either std::istream or std::ostream,
47
 * indicating whether the type wraps an input or output stream.
48
 */
49
template <typename Stream>
50
78882
class ManagedStream
51
{
52
 public:
53
92247
  ManagedStream(Stream* nonowned, std::string description)
54
92247
  : d_nonowned(nonowned), d_description(std::move(description)) {}
55
75741
  virtual ~ManagedStream() {}
56
57
  /**
58
   * Open the stream from the given value. First check the special cases and
59
   * then fall back to using `std::ofstream` or `std::ifstream`.
60
   */
61
3
  void open(const std::string& value)
62
  {
63
3
    if (specialCases(value)) return;
64
    if constexpr (std::is_same<Stream, std::ostream>::value)
65
    {
66
      d_nonowned = nullptr;
67
      d_owned.reset(detail::openOStream(value));
68
      d_description = value;
69
    }
70
    else if constexpr (std::is_same<Stream, std::istream>::value)
71
    {
72
      d_nonowned = nullptr;
73
      d_owned.reset(detail::openIStream(value));
74
      d_description = value;
75
    }
76
  }
77
78
264190
  Stream& operator*() const { return *getPtr(); }
79
  Stream* operator->() const { return getPtr(); }
80
6604
  operator Stream&() const { return *getPtr(); }
81
10
  operator Stream*() const { return getPtr(); }
82
83
6
  const std::string& description() const { return d_description; }
84
85
 protected:
86
  Stream* d_nonowned;
87
  std::shared_ptr<Stream> d_owned;
88
  std::string d_description = "<null>";
89
90
 private:
91
  /**
92
   * Check if there is a special case for this value. If so, the implementation
93
   * should set d_stream appropriately and return true to skip the default
94
   * methods for opening a stream.
95
   */
96
  virtual bool specialCases(const std::string& value) = 0;
97
98
  /** Return the pointer, either from d_nonowned or d_owned. */
99
270804
  Stream* getPtr() const
100
  {
101
270804
    if (d_nonowned != nullptr) return d_nonowned;
102
    return d_owned.get();
103
  }
104
};
105
106
template <typename Stream>
107
6
std::ostream& operator<<(std::ostream& os, const ManagedStream<Stream>& ms)
108
{
109
6
  return os << ms.description();
110
}
111
112
/**
113
 * Managed error output. It recognizes "stderr" and "--" as special valued for
114
 * std::cerr.
115
 */
116
51541
class ManagedErr : public ManagedStream<std::ostream>
117
{
118
 public:
119
  ManagedErr();
120
121
 private:
122
  bool specialCases(const std::string& value) override final;
123
};
124
125
/**
126
 * Managed standard input. It recognizes "stdin" and "--" as special valued for
127
 * std::cin.
128
 */
129
51541
class ManagedIn : public ManagedStream<std::istream>
130
{
131
 public:
132
  ManagedIn();
133
134
 private:
135
  bool specialCases(const std::string& value) override final;
136
};
137
138
/**
139
 * Managed standard output. It recognizes "stdout" and "--" as special valued
140
 * for std::cout.
141
 */
142
51541
class ManagedOut : public ManagedStream<std::ostream>
143
{
144
 public:
145
  ManagedOut();
146
147
 private:
148
  bool specialCases(const std::string& value) override final;
149
};
150
151
}  // namespace cvc5
152
153
#endif /* CVC5__OPTIONS__MANAGED_STREAMS_H */