1 /*
2    Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #ifndef PROPERTIES_HPP
26 #define PROPERTIES_HPP
27 
28 #include <ndb_global.h>
29 #include <BaseString.hpp>
30 #include <UtilBuffer.hpp>
31 #include <unordered_map>
32 
33 enum PropertiesType {
34   PropertiesType_Undefined = -1,
35   PropertiesType_Uint32 = 0,
36   PropertiesType_char = 1,
37   PropertiesType_Properties = 2,
38   PropertiesType_Uint64 = 3
39 };
40 
41 /**
42  * @struct  Property
43  * @brief   Stores one (name, value)-pair
44  *
45  * Value can be of type Properties, i.e. a Property may contain
46  * a Properties object.
47  */
48 struct Property {
49   Property(const char* name, Uint32 val);
50   Property(const char* name, Uint64 val);
51   Property(const char* name, const char * value);
52   Property(const char* name, const class Properties * value);
53   // We have no copy or move constructors so delete also assignment operator.
54   Property& operator=(const Property&) = delete;
55   Property& operator=(Property&&) = delete;
56   ~Property();
57 private:
58   friend class Properties;
59   struct PropertyImpl * impl;
60 };
61 
62 /**
63  * @class  Properties
64  * @brief  Stores information in (name, value)-pairs
65  */
66 class Properties {
67 public:
68   static const char delimiter;
69   static const char version[];
70 
71   Properties(bool case_insensitive= false);
72   Properties(const Properties &);
73   Properties(const Property *, int len);
74   Properties& operator=(const Properties&);
75   virtual ~Properties();
76 
77   /**
78    * Set/Get wheather names in the Properties should be compared
79    * w/o case.
80    * NOTE: The property is automatically applied to all propoerties put
81    *       into this after a called to setCaseInsensitiveNames has been made
82    *       But properties already in when calling setCaseInsensitiveNames will
83    *       not be affected
84    */
85   void setCaseInsensitiveNames(bool value);
86   bool getCaseInsensitiveNames() const;
87 
88   /**
89    * Insert an array of value(s)
90    */
91   void put(const Property *, int len);
92 
93   bool put(const char * name, Uint32 value, bool replace = false);
94   bool put64(const char * name, Uint64 value, bool replace = false);
95   bool put(const char * name, const char * value, bool replace = false);
96   bool put(const char * name, const Properties * value, bool replace = false);
97   bool append(const char * name, const char * value);
98 
99   /**
100    * Same as put above,
101    *   except that _%d (where %d is a number) is added to the name
102    * Compare get(name, no)
103    */
104   bool put(const char *, Uint32 no, Uint32, bool replace = false);
105   bool put64(const char *, Uint32 no, Uint64, bool replace = false);
106   bool put(const char *, Uint32 no, const char *, bool replace = false);
107   bool put(const char *, Uint32 no, const Properties *, bool replace = false);
108 
109 
110   bool getTypeOf(const char * name, PropertiesType * type) const;
111 
112   /** @return true if Properties object contains name */
113   bool contains(const char * name) const;
114 
115   bool get(const char * name, Uint32 * value) const;
116   bool get(const char * name, Uint64 * value) const;
117   bool get(const char * name, const char ** value) const;
118   bool get(const char * name, BaseString & value) const;
119   bool get(const char * name, const Properties ** value) const;
120 
121   bool getCopy(const char * name, char ** value) const;
122   bool getCopy(const char * name, Properties ** value) const;
123 
124   /**
125    * Same as get above
126    *   except that _%d (where %d = no) is added to the name
127    */
128   bool getTypeOf(const char * name, Uint32 no, PropertiesType * type) const;
129   bool contains(const char * name, Uint32 no) const;
130 
131   bool get(const char * name, Uint32 no, Uint32 * value) const;
132   bool get(const char * name, Uint32 no, Uint64 * value) const;
133   bool get(const char * name, Uint32 no, const char ** value) const;
134   bool get(const char * name, Uint32 no, const Properties ** value) const;
135 
136   bool getCopy(const char * name, Uint32 no, char ** value) const;
137   bool getCopy(const char * name, Uint32 no, Properties ** value) const;
138 
139   void clear();
140 
141   void remove(const char * name);
142 
143   void print(FILE * file = stdout, const char * prefix = 0) const;
144   /**
145    *  Iterator over names
146    */
147   class Iterator
148   {
149   public:
150     Iterator(const Properties* prop);
151     ~Iterator();
152 
153     const char* first();
154     const char* next();
155   private:
156     const Properties*  m_prop;
157     class IteratorImpl *m_iterImpl;
158   };
159   friend class Properties::Iterator;
160 
161   Uint32 getPackedSize() const;
162   bool unpack(const Uint32 * buf, Uint32 bufLen);
163   bool unpack(UtilBuffer &buf);
164 
getPropertiesErrno() const165   Uint32 getPropertiesErrno() const { return propErrno; }
getOSErrno() const166   Uint32 getOSErrno() const { return osErrno; }
167 
168 private:
169   Uint32 propErrno;
170   Uint32 osErrno;
171 
172   friend class PropertiesImpl;
173   class PropertiesImpl * impl;
174   class Properties * parent;
175 
176   void setErrno(Uint32 pErr, Uint32 osErr = 0) const ;
177 };
178 
179 /**
180  * Error code for properties
181  */
182 
183 /**
184  * No error
185  */
186 extern const Uint32 E_PROPERTIES_OK;
187 
188 /**
189  * Invalid name in put, names can not contain Properties::delimiter
190  */
191 extern const Uint32 E_PROPERTIES_INVALID_NAME;
192 
193 /**
194  * Element did not exist when using get
195  */
196 extern const Uint32 E_PROPERTIES_NO_SUCH_ELEMENT;
197 
198 /**
199  * Element had wrong type when using get
200  */
201 extern const Uint32 E_PROPERTIES_INVALID_TYPE;
202 
203 /**
204  * Element already existed when using put, and replace was not specified
205  */
206 extern const Uint32 E_PROPERTIES_ELEMENT_ALREADY_EXISTS;
207 
208 /**
209  * Invalid version on properties file you are trying to read
210  */
211 extern const Uint32 E_PROPERTIES_INVALID_VERSION_WHILE_UNPACKING;
212 
213 /**
214  * When unpacking an buffer
215  *  found that buffer is to short
216  *
217  * Probably an invlaid buffer
218  */
219 extern const Uint32 E_PROPERTIES_INVALID_BUFFER_TO_SHORT;
220 
221 /**
222  * Error when packing, can not allocate working buffer
223  *
224  * Note: OS error is set
225  */
226 extern const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_PACKING;
227 
228 /**
229  * Error when unpacking, can not allocate working buffer
230  *
231  * Note: OS error is set
232  */
233 extern const Uint32 E_PROPERTIES_ERROR_MALLOC_WHILE_UNPACKING;
234 
235 /**
236  * Error when unpacking, invalid checksum
237  *
238  */
239 extern const Uint32 E_PROPERTIES_INVALID_CHECKSUM;
240 
241 /**
242  * Error when unpacking
243  *   No of items > 0 while size of buffer (left) <= 0
244  */
245 extern const Uint32 E_PROPERTIES_BUFFER_TO_SMALL_WHILE_UNPACKING;
246 
247 inline bool
unpack(UtilBuffer & buf)248 Properties::unpack(UtilBuffer &buf) {
249   return unpack((const Uint32 *)buf.get_data(), buf.length());
250 }
251 
252 #endif
253