1 
2 /**
3  *    Copyright (C) 2018-present MongoDB, Inc.
4  *
5  *    This program is free software: you can redistribute it and/or modify
6  *    it under the terms of the Server Side Public License, version 1,
7  *    as published by MongoDB, Inc.
8  *
9  *    This program is distributed in the hope that it will be useful,
10  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *    Server Side Public License for more details.
13  *
14  *    You should have received a copy of the Server Side Public License
15  *    along with this program. If not, see
16  *    <http://www.mongodb.com/licensing/server-side-public-license>.
17  *
18  *    As a special exception, the copyright holders give permission to link the
19  *    code of portions of this program with the OpenSSL library under certain
20  *    conditions as described in each individual source file and distribute
21  *    linked combinations including the program with the OpenSSL library. You
22  *    must comply with the Server Side Public License in all respects for
23  *    all of the code used other than as permitted herein. If you modify file(s)
24  *    with this exception, you may extend this exception to your version of the
25  *    file(s), but you are not obligated to do so. If you do not wish to do so,
26  *    delete this exception statement from your version. If you delete this
27  *    exception statement from all source files in the program, then also delete
28  *    it in the license file.
29  */
30 
31 #pragma once
32 
33 #include <map>
34 #include <vector>
35 
36 #include "mongo/base/status.h"
37 #include "mongo/bson/util/builder.h"
38 
39 namespace mongo {
40 namespace optionenvironment {
41 
42 class Constraint;
43 class KeyConstraint;
44 
45 /**
46  * Helper typedefs for the more complex C++ types supported by this Value class
47  */
48 typedef std::map<std::string, std::string> StringMap_t;
49 typedef std::vector<std::string> StringVector_t;
50 
51 typedef std::string Key;
52 
53 /** A simple container interface for storing various C++ values.
54  *
55  *  Usage:
56  *
57  *  Value intVal(2);
58  *  Value stringVal("string");
59  *
60  *  int intContents = 1;
61  *  Status ret = stringVal.get(&intContents);
62  *  // ret != Status::OK()
63  *  // intContents is still 1
64  *
65  *  ret = intVal.get(&intContents);
66  *  // ret == Status::OK()
67  *  // intContents is now 2
68  */
69 class Value {
70 public:
71     // Constructors
72 
Value()73     explicit Value() : _type(None) {}
Value(StringVector_t val)74     explicit Value(StringVector_t val) : _stringVectorVal(val), _type(StringVector) {}
Value(StringMap_t val)75     explicit Value(StringMap_t val) : _stringMapVal(val), _type(StringMap) {}
Value(bool val)76     explicit Value(bool val) : _boolVal(val), _type(Bool) {}
Value(double val)77     explicit Value(double val) : _doubleVal(val), _type(Double) {}
Value(int val)78     explicit Value(int val) : _intVal(val), _type(Int) {}
Value(long val)79     explicit Value(long val) : _longVal(val), _type(Long) {}
Value(std::string val)80     explicit Value(std::string val) : _stringVal(val), _type(String) {}
Value(const char * val)81     explicit Value(const char* val) : _stringVal(val), _type(String) {}
Value(unsigned long long val)82     explicit Value(unsigned long long val) : _unsignedLongLongVal(val), _type(UnsignedLongLong) {}
Value(unsigned val)83     explicit Value(unsigned val) : _unsignedVal(val), _type(Unsigned) {}
84 
85     // Access interface
86 
87     Status get(StringVector_t* val) const;
88     Status get(StringMap_t* val) const;
89     Status get(bool* val) const;
90     Status get(double* val) const;
91     Status get(int* val) const;
92     Status get(long* val) const;
93     Status get(std::string* val) const;
94     Status get(unsigned long long* val) const;
95     Status get(unsigned* val) const;
96 
97     // Utility functions
98 
99     /**
100      *  Return the value's type as a string
101      */
102     std::string typeToString() const;
103 
104     /**
105      *  Return true if the value was created with the no argument constructor
106      */
107     bool isEmpty() const;
108 
109     /**
110      *  Return true if the other Value equals this value, both in type and in contents
111      *
112      *  Two empty values are equal
113      */
114     bool equal(const Value&) const;
115 
116     /**
117      *  Return the std::string representation of this Value.  This function is used only for
118      *  debugging purposes and does not output data in an easily parseable format.
119      */
120     std::string toString() const;
121 
122     /**
123      *  The functions below are the legacy interface to be consistent with boost::any during the
124      *  transition period
125      */
126 
127     /**
128      *  Returns the contents of this Value as type T.  Throws AssertionException if the type
129      *  does not match
130      */
131     template <typename T>
132     T as() const;
133 
134     /**
135      *  Return the type_info for this value
136      */
137     const std::type_info& type() const;
138 
139 private:
140     StringVector_t _stringVectorVal;
141     StringMap_t _stringMapVal;
142     std::string _stringVal;
143     union {
144         bool _boolVal;
145         double _doubleVal;
146         int _intVal;
147         long _longVal;
148         unsigned long long _unsignedLongLongVal;
149         unsigned _unsignedVal;
150     };
151 
152     // Types currently supported by Value
153     enum Type {
154         StringVector,      // std::vector<std::string>
155         StringMap,         // std::map<std::string, std::string>
156         Bool,              // bool
157         Double,            // double
158         Int,               // int
159         Long,              // long
160         String,            // std::string
161         UnsignedLongLong,  // unsigned long long
162         Unsigned,          // unsigned
163         None,              // (not set)
164     };
165 
166     Type _type;
167 };
168 
169 template <typename T>
as()170 T Value::as() const {
171     T valueType;
172 
173     Status ret = get(&valueType);
174     if (!ret.isOK()) {
175         StringBuilder message;
176         message << "failed to extract typed value from Value container: " << ret.toString();
177         uasserted(17114, message.str());
178     }
179 
180     return valueType;
181 }
182 
183 }  // namespace optionenvironment
184 }  // namespace mongo
185