1 // Copyright (c) 2017-2020 Thomas Fussell
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, WRISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 // THE SOFTWARE
20 //
21 // @license: http://www.opensource.org/licenses/mit-license.php
22 // @author: see AUTHORS file
23 
24 #pragma once
25 
26 #include <string>
27 #include <vector>
28 
29 #include <xlnt/xlnt_config.hpp>
30 
31 namespace xlnt {
32 
33 struct datetime;
34 
35 /// <summary>
36 /// Represents an object that can have variable type.
37 /// </summary>
38 class XLNT_API variant
39 {
40 public:
41     // TODO: implement remaining types?
42 
43     /// <summary>
44     /// The possible types a variant can hold.
45     /// </summary>
46     enum class type
47     {
48         vector,
49         //array,
50         //blob,
51         //oblob,
52         //empty,
53         null,
54         //i1,
55         //i2,
56         i4,
57         //i8,
58         //integer,
59         //ui1,
60         //ui2,
61         //ui4,
62         //ui8,
63         //uint,
64         //r4,
65         //r8,
66         //decimal,
67         lpstr, // TODO: how does this differ from lpwstr?
68         //lpwstr,
69         //bstr,
70         date,
71         //filetime,
72         boolean,
73         //cy,
74         //error,
75         //stream,
76         //ostream,
77         //storage,
78         //ostorage,
79         //vstream,
80         //clsid
81     };
82 
83     /// <summary>
84     /// Default constructor. Creates a null-type variant.
85     /// </summary>
86     variant();
87 
88     /// <summary>
89     /// Creates a string-type variant with the given value.
90     /// </summary>
91     variant(const std::string &value);
92 
93     /// <summary>
94     /// Creates a string-type variant with the given value.
95     /// </summary>
96     variant(const char *value);
97 
98     /// <summary>
99     /// Creates a i4-type variant with the given value.
100     /// </summary>
101     variant(std::int32_t value);
102 
103     /// <summary>
104     /// Creates a bool-type variant with the given value.
105     /// </summary>
106     variant(bool value);
107 
108     /// <summary>
109     /// Creates a date-type variant with the given value.
110     /// </summary>
111     variant(const datetime &value);
112 
113     /// <summary>
114     /// Creates a vector_i4-type variant with the given value.
115     /// </summary>
116     variant(const std::initializer_list<std::int32_t> &value);
117 
118     /// <summary>
119     /// Creates a vector_i4-type variant with the given value.
120     /// </summary>
121     variant(const std::vector<std::int32_t> &value);
122 
123     /// <summary>
124     /// Creates a vector_string-type variant with the given value.
125     /// </summary>
126     variant(const std::initializer_list<const char *> &value);
127 
128     /// <summary>
129     /// Creates a vector_string-type variant with the given value.
130     /// </summary>
131     variant(const std::vector<const char *> &value);
132 
133     /// <summary>
134     /// Creates a vector_string-type variant with the given value.
135     /// </summary>
136     variant(const std::initializer_list<std::string> &value);
137 
138     /// <summary>
139     /// Creates a vector_string-type variant with the given value.
140     /// </summary>
141     variant(const std::vector<std::string> &value);
142 
143     /// <summary>
144     /// Creates a vector_variant-type variant with the given value.
145     /// </summary>
146     variant(const std::vector<variant> &value);
147 
148     /// <summary>
149     /// Returns true if this variant is of type t.
150     /// </summary>
151     bool is(type t) const;
152 
153     /// <summary>
154     /// Returns the value of this variant as type T. An exception will
155     /// be thrown if the types are not convertible.
156     /// </summary>
157     template <typename T>
158     T get() const;
159 
160     /// <summary>
161     /// Returns the type of this variant.
162     /// </summary>
163     type value_type() const;
164 
165     bool operator==(const variant &rhs) const;
166 
167 private:
168     type type_;
169     std::vector<variant> vector_value_;
170     std::int32_t i4_value_;
171     std::string lpstr_value_;
172 };
173 
174 template <>
175 bool variant::get() const;
176 
177 template <>
178 std::int32_t variant::get() const;
179 
180 template <>
181 std::string variant::get() const;
182 
183 template <>
184 datetime variant::get() const;
185 
186 template <>
187 std::vector<std::int32_t> variant::get() const;
188 
189 template <>
190 std::vector<std::string> variant::get() const;
191 
192 template <>
193 std::vector<variant> variant::get() const;
194 
195 } // namespace xlnt
196