PageRenderTime 72ms CodeModel.GetById 27ms app.highlight 37ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llcommon/llsdutil.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 422 lines | 161 code | 44 blank | 217 comment | 3 complexity | 450801a6835e487e4c3e457e21daaf91 MD5 | raw file
  1/** 
  2 * @file llsdutil.h
  3 * @author Phoenix
  4 * @date 2006-05-24
  5 * @brief Utility classes, functions, etc, for using structured data.
  6 *
  7 * $LicenseInfo:firstyear=2006&license=viewerlgpl$
  8 * Second Life Viewer Source Code
  9 * Copyright (C) 2010, Linden Research, Inc.
 10 * 
 11 * This library is free software; you can redistribute it and/or
 12 * modify it under the terms of the GNU Lesser General Public
 13 * License as published by the Free Software Foundation;
 14 * version 2.1 of the License only.
 15 * 
 16 * This library is distributed in the hope that it will be useful,
 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 19 * Lesser General Public License for more details.
 20 * 
 21 * You should have received a copy of the GNU Lesser General Public
 22 * License along with this library; if not, write to the Free Software
 23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 24 * 
 25 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 26 * $/LicenseInfo$
 27 */
 28
 29#ifndef LL_LLSDUTIL_H
 30#define LL_LLSDUTIL_H
 31
 32class LLSD;
 33
 34// U32
 35LL_COMMON_API LLSD ll_sd_from_U32(const U32);
 36LL_COMMON_API U32 ll_U32_from_sd(const LLSD& sd);
 37
 38// U64
 39LL_COMMON_API LLSD ll_sd_from_U64(const U64);
 40LL_COMMON_API U64 ll_U64_from_sd(const LLSD& sd);
 41
 42// IP Address
 43LL_COMMON_API LLSD ll_sd_from_ipaddr(const U32);
 44LL_COMMON_API U32 ll_ipaddr_from_sd(const LLSD& sd);
 45
 46// Binary to string
 47LL_COMMON_API LLSD ll_string_from_binary(const LLSD& sd);
 48
 49//String to binary
 50LL_COMMON_API LLSD ll_binary_from_string(const LLSD& sd);
 51
 52// Serializes sd to static buffer and returns pointer, useful for gdb debugging.
 53LL_COMMON_API char* ll_print_sd(const LLSD& sd);
 54
 55// Serializes sd to static buffer and returns pointer, using "pretty printing" mode.
 56LL_COMMON_API char* ll_pretty_print_sd_ptr(const LLSD* sd);
 57LL_COMMON_API char* ll_pretty_print_sd(const LLSD& sd);
 58
 59//compares the structure of an LLSD to a template LLSD and stores the
 60//"valid" values in a 3rd LLSD. Default values
 61//are pulled from the template.  Extra keys/values in the test
 62//are ignored in the resultant LLSD.  Ordering of arrays matters
 63//Returns false if the test is of same type but values differ in type
 64//Otherwise, returns true
 65
 66LL_COMMON_API BOOL compare_llsd_with_template(
 67	const LLSD& llsd_to_test,
 68	const LLSD& template_llsd,
 69	LLSD& resultant_llsd);
 70
 71/**
 72 * Recursively determine whether a given LLSD data block "matches" another
 73 * LLSD prototype. The returned string is empty() on success, non-empty() on
 74 * mismatch.
 75 *
 76 * This function tests structure (types) rather than data values. It is
 77 * intended for when a consumer expects an LLSD block with a particular
 78 * structure, and must succinctly detect whether the arriving block is
 79 * well-formed. For instance, a test of the form:
 80 * @code
 81 * if (! (data.has("request") && data.has("target") && data.has("modifier") ...))
 82 * @endcode
 83 * could instead be expressed by initializing a prototype LLSD map with the
 84 * required keys and writing:
 85 * @code
 86 * if (! llsd_matches(prototype, data).empty())
 87 * @endcode
 88 *
 89 * A non-empty return value is an error-message fragment intended to indicate
 90 * to (English-speaking) developers where in the prototype structure the
 91 * mismatch occurred.
 92 *
 93 * * If a slot in the prototype isUndefined(), then anything is valid at that
 94 *   place in the real object. (Passing prototype == LLSD() matches anything
 95 *   at all.)
 96 * * An array in the prototype must match a data array at least that large.
 97 *   (Additional entries in the data array are ignored.) Every isDefined()
 98 *   entry in the prototype array must match the corresponding entry in the
 99 *   data array.
100 * * A map in the prototype must match a map in the data. Every key in the
101 *   prototype map must match a corresponding key in the data map. (Additional
102 *   keys in the data map are ignored.) Every isDefined() value in the
103 *   prototype map must match the corresponding key's value in the data map.
104 * * Scalar values in the prototype are tested for @em type rather than value.
105 *   For instance, a String in the prototype matches any String at all. In
106 *   effect, storing an Integer at a particular place in the prototype asserts
107 *   that the caller intends to apply asInteger() to the corresponding slot in
108 *   the data.
109 * * A String in the prototype matches String, Boolean, Integer, Real, UUID,
110 *   Date and URI, because asString() applied to any of these produces a
111 *   meaningful result.
112 * * Similarly, a Boolean, Integer or Real in the prototype can match any of
113 *   Boolean, Integer or Real in the data -- or even String.
114 * * UUID matches UUID or String.
115 * * Date matches Date or String.
116 * * URI matches URI or String.
117 * * Binary in the prototype matches only Binary in the data.
118 *
119 * @TODO: when a Boolean, Integer or Real in the prototype matches a String in
120 * the data, we should examine the String @em value to ensure it can be
121 * meaningfully converted to the requested type. The same goes for UUID, Date
122 * and URI.
123 */
124LL_COMMON_API std::string llsd_matches(const LLSD& prototype, const LLSD& data, const std::string& pfx="");
125
126/// Deep equality. If you want to compare LLSD::Real values for approximate
127/// equality rather than bitwise equality, pass @a bits as for
128/// is_approx_equal_fraction().
129LL_COMMON_API bool llsd_equals(const LLSD& lhs, const LLSD& rhs, unsigned bits=-1);
130
131// Simple function to copy data out of input & output iterators if
132// there is no need for casting.
133template<typename Input> LLSD llsd_copy_array(Input iter, Input end)
134{
135	LLSD dest;
136	for (; iter != end; ++iter)
137	{
138		dest.append(*iter);
139	}
140	return dest;
141}
142
143/*****************************************************************************
144*   LLSDArray
145*****************************************************************************/
146/**
147 * Construct an LLSD::Array inline, with implicit conversion to LLSD. Usage:
148 *
149 * @code
150 * void somefunc(const LLSD&);
151 * ...
152 * somefunc(LLSDArray("text")(17)(3.14));
153 * @endcode
154 *
155 * For completeness, LLSDArray() with no args constructs an empty array, so
156 * <tt>LLSDArray()("text")(17)(3.14)</tt> produces an array equivalent to the
157 * above. But for most purposes, LLSD() is already equivalent to an empty
158 * array, and if you explicitly want an empty isArray(), there's
159 * LLSD::emptyArray(). However, supporting a no-args LLSDArray() constructor
160 * follows the principle of least astonishment.
161 */
162class LLSDArray
163{
164public:
165    LLSDArray():
166        _data(LLSD::emptyArray())
167    {}
168
169    /**
170     * Need an explicit copy constructor. Consider the following:
171     *
172     * @code
173     * LLSD array_of_arrays(LLSDArray(LLSDArray(17)(34))
174     *                               (LLSDArray("x")("y")));
175     * @endcode
176     *
177     * The coder intends to construct [[17, 34], ["x", "y"]].
178     *
179     * With the compiler's implicit copy constructor, s/he gets instead
180     * [17, 34, ["x", "y"]].
181     *
182     * The expression LLSDArray(17)(34) constructs an LLSDArray with those two
183     * values. The reader assumes it should be converted to LLSD, as we always
184     * want with LLSDArray, before passing it to the @em outer LLSDArray
185     * constructor! This copy constructor makes that happen.
186     */
187    LLSDArray(const LLSDArray& inner):
188        _data(LLSD::emptyArray())
189    {
190        _data.append(inner);
191    }
192
193    LLSDArray(const LLSD& value):
194        _data(LLSD::emptyArray())
195    {
196        _data.append(value);
197    }
198
199    LLSDArray& operator()(const LLSD& value)
200    {
201        _data.append(value);
202        return *this;
203    }
204
205    operator LLSD() const { return _data; }
206    LLSD get() const { return _data; }
207
208private:
209    LLSD _data;
210};
211
212/*****************************************************************************
213*   LLSDMap
214*****************************************************************************/
215/**
216 * Construct an LLSD::Map inline, with implicit conversion to LLSD. Usage:
217 *
218 * @code
219 * void somefunc(const LLSD&);
220 * ...
221 * somefunc(LLSDMap("alpha", "abc")("number", 17)("pi", 3.14));
222 * @endcode
223 *
224 * For completeness, LLSDMap() with no args constructs an empty map, so
225 * <tt>LLSDMap()("alpha", "abc")("number", 17)("pi", 3.14)</tt> produces a map
226 * equivalent to the above. But for most purposes, LLSD() is already
227 * equivalent to an empty map, and if you explicitly want an empty isMap(),
228 * there's LLSD::emptyMap(). However, supporting a no-args LLSDMap()
229 * constructor follows the principle of least astonishment.
230 */
231class LLSDMap
232{
233public:
234    LLSDMap():
235        _data(LLSD::emptyMap())
236    {}
237    LLSDMap(const LLSD::String& key, const LLSD& value):
238        _data(LLSD::emptyMap())
239    {
240        _data[key] = value;
241    }
242
243    LLSDMap& operator()(const LLSD::String& key, const LLSD& value)
244    {
245        _data[key] = value;
246        return *this;
247    }
248
249    operator LLSD() const { return _data; }
250    LLSD get() const { return _data; }
251
252private:
253    LLSD _data;
254};
255
256/*****************************************************************************
257*   LLSDParam
258*****************************************************************************/
259/**
260 * LLSDParam is a customization point for passing LLSD values to function
261 * parameters of more or less arbitrary type. LLSD provides a small set of
262 * native conversions; but if a generic algorithm explicitly constructs an
263 * LLSDParam object in the function's argument list, a consumer can provide
264 * LLSDParam specializations to support more different parameter types than
265 * LLSD's native conversions.
266 *
267 * Usage:
268 *
269 * @code
270 * void somefunc(const paramtype&);
271 * ...
272 * somefunc(..., LLSDParam<paramtype>(someLLSD), ...);
273 * @endcode
274 */
275template <typename T>
276class LLSDParam
277{
278public:
279    /**
280     * Default implementation converts to T on construction, saves converted
281     * value for later retrieval
282     */
283    LLSDParam(const LLSD& value):
284        _value(value)
285    {}
286
287    operator T() const { return _value; }
288
289private:
290    T _value;
291};
292
293/**
294 * Turns out that several target types could accept an LLSD param using any of
295 * a few different conversions, e.g. LLUUID's constructor can accept LLUUID or
296 * std::string. Therefore, the compiler can't decide which LLSD conversion
297 * operator to choose, even though to us it seems obvious. But that's okay, we
298 * can specialize LLSDParam for such target types, explicitly specifying the
299 * desired conversion -- that's part of what LLSDParam is all about. Turns out
300 * we have to do that enough to make it worthwhile generalizing. Use a macro
301 * because I need to specify one of the asReal, etc., explicit conversion
302 * methods as well as a type. If I'm overlooking a clever way to implement
303 * that using a template instead, feel free to reimplement.
304 */
305#define LLSDParam_for(T, AS)                    \
306template <>                                     \
307class LLSDParam<T>                              \
308{                                               \
309public:                                         \
310    LLSDParam(const LLSD& value):               \
311        _value(value.AS())                      \
312    {}                                          \
313                                                \
314    operator T() const { return _value; }       \
315                                                \
316private:                                        \
317    T _value;                                   \
318}
319
320LLSDParam_for(float,        asReal);
321LLSDParam_for(LLUUID,       asUUID);
322LLSDParam_for(LLDate,       asDate);
323LLSDParam_for(LLURI,        asURI);
324LLSDParam_for(LLSD::Binary, asBinary);
325
326/**
327 * LLSDParam<const char*> is an example of the kind of conversion you can
328 * support with LLSDParam beyond native LLSD conversions. Normally you can't
329 * pass an LLSD object to a function accepting const char* -- but you can
330 * safely pass an LLSDParam<const char*>(yourLLSD).
331 */
332template <>
333class LLSDParam<const char*>
334{
335private:
336    // The difference here is that we store a std::string rather than a const
337    // char*. It's important that the LLSDParam object own the std::string.
338    std::string _value;
339    // We don't bother storing the incoming LLSD object, but we do have to
340    // distinguish whether _value is an empty string because the LLSD object
341    // contains an empty string or because it's isUndefined().
342    bool _undefined;
343
344public:
345    LLSDParam(const LLSD& value):
346        _value(value),
347        _undefined(value.isUndefined())
348    {}
349
350    // The const char* we retrieve is for storage owned by our _value member.
351    // That's how we guarantee that the const char* is valid for the lifetime
352    // of this LLSDParam object. Constructing your LLSDParam in the argument
353    // list should ensure that the LLSDParam object will persist for the
354    // duration of the function call.
355    operator const char*() const
356    {
357        if (_undefined)
358        {
359            // By default, an isUndefined() LLSD object's asString() method
360            // will produce an empty string. But for a function accepting
361            // const char*, it's often important to be able to pass NULL, and
362            // isUndefined() seems like the best way. If you want to pass an
363            // empty string, you can still pass LLSD(""). Without this special
364            // case, though, no LLSD value could pass NULL.
365            return NULL;
366        }
367        return _value.c_str();
368    }
369};
370
371namespace llsd
372{
373
374/*****************************************************************************
375*   BOOST_FOREACH() helpers for LLSD
376*****************************************************************************/
377/// Usage: BOOST_FOREACH(LLSD item, inArray(someLLSDarray)) { ... }
378class inArray
379{
380public:
381    inArray(const LLSD& array):
382        _array(array)
383    {}
384
385    typedef LLSD::array_const_iterator const_iterator;
386    typedef LLSD::array_iterator iterator;
387
388    iterator begin() { return _array.beginArray(); }
389    iterator end()   { return _array.endArray(); }
390    const_iterator begin() const { return _array.beginArray(); }
391    const_iterator end()   const { return _array.endArray(); }
392
393private:
394    LLSD _array;
395};
396
397/// MapEntry is what you get from dereferencing an LLSD::map_[const_]iterator.
398typedef std::map<LLSD::String, LLSD>::value_type MapEntry;
399
400/// Usage: BOOST_FOREACH([const] MapEntry& e, inMap(someLLSDmap)) { ... }
401class inMap
402{
403public:
404    inMap(const LLSD& map):
405        _map(map)
406    {}
407
408    typedef LLSD::map_const_iterator const_iterator;
409    typedef LLSD::map_iterator iterator;
410
411    iterator begin() { return _map.beginMap(); }
412    iterator end()   { return _map.endMap(); }
413    const_iterator begin() const { return _map.beginMap(); }
414    const_iterator end()   const { return _map.endMap(); }
415
416private:
417    LLSD _map;
418};
419
420} // namespace llsd
421
422#endif // LL_LLSDUTIL_H