1 /***************************************************************************
2  *                                                                         *
3  *   LinuxSampler - modular, streaming capable sampler                     *
4  *                                                                         *
5  *   Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck   *
6  *   Copyright (C) 2005 - 2019 Christian Schoenebeck                       *
7  *                                                                         *
8  *   This program is free software; you can redistribute it and/or modify  *
9  *   it under the terms of the GNU General Public License as published by  *
10  *   the Free Software Foundation; either version 2 of the License, or     *
11  *   (at your option) any later version.                                   *
12  *                                                                         *
13  *   This program is distributed in the hope that it will be useful,       *
14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
16  *   GNU General Public License for more details.                          *
17  *                                                                         *
18  *   You should have received a copy of the GNU General Public License     *
19  *   along with this program; if not, write to the Free Software           *
20  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston,                 *
21  *   MA  02111-1307  USA                                                   *
22  ***************************************************************************/
23 
24 #ifndef __LS_OPTIONAL_H__
25 #define __LS_OPTIONAL_H__
26 
27 #include "Exception.h"
28 
29 namespace LinuxSampler {
30 
31     /**
32      * Base class of template class optional, not meant to be instantiated
33      * directly. It just provides the optional<T>::nothing member.
34      */
35     class optional_base {
36         public:
nothing_t()37             class nothing_t { public: nothing_t() {} };
38 
39             static const nothing_t nothing;
40     };
41 
42     /**
43      * This class can be used for any variable that might not have a value
44      * set. E.g. as a return value type of a function, since in the case of
45      * return values of functions it's often difficult to return a pointer
46      * variable which might do the trick of an optional return value. It
47      * behaves pretty much like a pointer though. That is, it can be checked
48      * against NULL and the actual value can be dereferenced with the
49      * typical C pointer dereference operators.
50      */
51     template<class T>
52     class optional : public optional_base {
53         public:
optional()54             optional() {
55                 initialized = false;
56             }
57 
optional(T data)58             optional(T data) {
59                 this->data  = data;
60                 initialized = true;
61             }
62 
optional(nothing_t)63             optional(nothing_t) {
64                 initialized = false;
65             }
66 
67             template <class T_inner>
optional(T_inner data)68             optional(T_inner data) {
69                 this->data  = T(data);
70                 initialized = true;
71             }
72 
get()73             const T& get() const throw (Exception) {
74                 if (!initialized) throw Exception("optional variable not initialized");
75                 return data;
76             }
77 
get()78             T& get() throw (Exception) {
79                 if (!initialized) throw Exception("optional variable not initialized");
80                 return data;
81             }
82 
83             optional& operator =(const optional& arg) {
84                 this->data  = arg.data;
85                 initialized = arg.initialized;
86                 return *this;
87             }
88 
89             optional& operator =(const T& arg) {
90                 this->data  = arg;
91                 initialized = true;
92                 return *this;
93             }
94 
95             bool operator ==(const optional& o) const {
96                 if (!initialized || !o.initialized)
97                     return initialized == o.initialized;
98                 return data == o.data;
99             }
100 
101             bool operator !=(const optional& o) const {
102                 return !(*this == o);
103             }
104 
throw(Exception)105             const T& operator *() const throw (Exception) { return get(); }
throw(Exception)106             T&       operator *()       throw (Exception) { return get(); }
107 
108             const T* operator ->() const throw (Exception) {
109                 if (!initialized) throw Exception("optional variable not initialized");
110                 return &data;
111             }
112 
113             T* operator ->() throw (Exception) {
114                 if (!initialized) throw Exception("optional variable not initialized");
115                 return &data;
116             }
117 
118             operator bool()   const { return initialized; }
119             bool operator !() const { return !initialized; }
120 
121         protected:
122             T    data;
123             bool initialized;
124     };
125 
126 } // namespace LinuxSampler
127 
128 #endif // __LS_OPTIONAL_H__
129