PageRenderTime 42ms CodeModel.GetById 13ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llui/llsdparam.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 342 lines | 245 code | 53 blank | 44 comment | 25 complexity | 889ff9a1ec025ac350e85efc9384bf3a MD5 | raw file
  1/** 
  2 * @file llsdparam.cpp
  3 * @brief parameter block abstraction for creating complex objects and 
  4 * parsing construction parameters from xml and LLSD
  5 *
  6 * $LicenseInfo:firstyear=2008&license=viewerlgpl$
  7 * Second Life Viewer Source Code
  8 * Copyright (C) 2010, Linden Research, Inc.
  9 * 
 10 * This library is free software; you can redistribute it and/or
 11 * modify it under the terms of the GNU Lesser General Public
 12 * License as published by the Free Software Foundation;
 13 * version 2.1 of the License only.
 14 * 
 15 * This library 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 GNU
 18 * Lesser General Public License for more details.
 19 * 
 20 * You should have received a copy of the GNU Lesser General Public
 21 * License along with this library; if not, write to the Free Software
 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 23 * 
 24 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 25 * $/LicenseInfo$
 26 */
 27
 28#include "linden_common.h"
 29
 30// Project includes
 31#include "llsdparam.h"
 32#include "llsdutil.h"
 33
 34static 	LLInitParam::Parser::parser_read_func_map_t sReadFuncs;
 35static 	LLInitParam::Parser::parser_write_func_map_t sWriteFuncs;
 36static 	LLInitParam::Parser::parser_inspect_func_map_t sInspectFuncs;
 37static const LLSD NO_VALUE_MARKER;
 38
 39LLFastTimer::DeclareTimer FTM_SD_PARAM_ADAPTOR("LLSD to LLInitParam conversion");
 40
 41//
 42// LLParamSDParser
 43//
 44LLParamSDParser::LLParamSDParser()
 45: Parser(sReadFuncs, sWriteFuncs, sInspectFuncs)
 46{
 47	using boost::bind;
 48
 49	if (sReadFuncs.empty())
 50	{
 51		registerParserFuncs<LLInitParam::Flag>(readFlag, &LLParamSDParser::writeFlag);
 52		registerParserFuncs<S32>(readS32, &LLParamSDParser::writeTypedValue<S32>);
 53		registerParserFuncs<U32>(readU32, &LLParamSDParser::writeU32Param);
 54		registerParserFuncs<F32>(readF32, &LLParamSDParser::writeTypedValue<F32>);
 55		registerParserFuncs<F64>(readF64, &LLParamSDParser::writeTypedValue<F64>);
 56		registerParserFuncs<bool>(readBool, &LLParamSDParser::writeTypedValue<bool>);
 57		registerParserFuncs<std::string>(readString, &LLParamSDParser::writeTypedValue<std::string>);
 58		registerParserFuncs<LLUUID>(readUUID, &LLParamSDParser::writeTypedValue<LLUUID>);
 59		registerParserFuncs<LLDate>(readDate, &LLParamSDParser::writeTypedValue<LLDate>);
 60		registerParserFuncs<LLURI>(readURI, &LLParamSDParser::writeTypedValue<LLURI>);
 61		registerParserFuncs<LLSD>(readSD, &LLParamSDParser::writeTypedValue<LLSD>);
 62	}
 63}
 64
 65// special case handling of U32 due to ambiguous LLSD::assign overload
 66bool LLParamSDParser::writeU32Param(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
 67{
 68	LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
 69	if (!sdparser.mWriteRootSD) return false;
 70	
 71	parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
 72	LLSD& sd_to_write = LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
 73	sd_to_write.assign((S32)*((const U32*)val_ptr));
 74
 75	return true;
 76}
 77
 78bool LLParamSDParser::writeFlag(LLParamSDParser::parser_t& parser, const void* val_ptr, parser_t::name_stack_t& name_stack)
 79{
 80	LLParamSDParser& sdparser = static_cast<LLParamSDParser&>(parser);
 81	if (!sdparser.mWriteRootSD) return false;
 82
 83	parser_t::name_stack_range_t range(name_stack.begin(), name_stack.end());
 84	LLParamSDParserUtilities::getSDWriteNode(*sdparser.mWriteRootSD, range);
 85
 86	return true;
 87}
 88
 89void LLParamSDParser::submit(LLInitParam::BaseBlock& block, const LLSD& sd, LLInitParam::Parser::name_stack_t& name_stack)
 90{
 91	mCurReadSD = &sd;
 92	block.submitValue(name_stack, *this);
 93}
 94
 95void LLParamSDParser::readSD(const LLSD& sd, LLInitParam::BaseBlock& block, bool silent)
 96{
 97	mCurReadSD = NULL;
 98	mNameStack.clear();
 99	setParseSilently(silent);
100
101	LLParamSDParserUtilities::readSDValues(boost::bind(&LLParamSDParser::submit, this, boost::ref(block), _1, _2), sd, mNameStack);
102	//readSDValues(sd, block);
103}
104
105void LLParamSDParser::writeSD(LLSD& sd, const LLInitParam::BaseBlock& block)
106{
107	mNameStack.clear();
108	mWriteRootSD = &sd;
109
110	name_stack_t name_stack;
111	block.serializeBlock(*this, name_stack);
112}
113
114/*virtual*/ std::string LLParamSDParser::getCurrentElementName()
115{
116	std::string full_name = "sd";
117	for (name_stack_t::iterator it = mNameStack.begin();	
118		it != mNameStack.end();
119		++it)
120	{
121		full_name += llformat("[%s]", it->first.c_str());
122	}
123
124	return full_name;
125}
126
127
128bool LLParamSDParser::readFlag(Parser& parser, void* val_ptr)
129{
130	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
131	return self.mCurReadSD == &NO_VALUE_MARKER;
132}
133
134
135bool LLParamSDParser::readS32(Parser& parser, void* val_ptr)
136{
137	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
138
139    *((S32*)val_ptr) = self.mCurReadSD->asInteger();
140    return true;
141}
142
143bool LLParamSDParser::readU32(Parser& parser, void* val_ptr)
144{
145	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
146
147    *((U32*)val_ptr) = self.mCurReadSD->asInteger();
148    return true;
149}
150
151bool LLParamSDParser::readF32(Parser& parser, void* val_ptr)
152{
153	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
154
155    *((F32*)val_ptr) = self.mCurReadSD->asReal();
156    return true;
157}
158
159bool LLParamSDParser::readF64(Parser& parser, void* val_ptr)
160{
161	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
162
163    *((F64*)val_ptr) = self.mCurReadSD->asReal();
164    return true;
165}
166
167bool LLParamSDParser::readBool(Parser& parser, void* val_ptr)
168{
169	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
170
171    *((bool*)val_ptr) = self.mCurReadSD->asBoolean();
172    return true;
173}
174
175bool LLParamSDParser::readString(Parser& parser, void* val_ptr)
176{
177	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
178
179	*((std::string*)val_ptr) = self.mCurReadSD->asString();
180    return true;
181}
182
183bool LLParamSDParser::readUUID(Parser& parser, void* val_ptr)
184{
185	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
186
187	*((LLUUID*)val_ptr) = self.mCurReadSD->asUUID();
188    return true;
189}
190
191bool LLParamSDParser::readDate(Parser& parser, void* val_ptr)
192{
193	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
194
195	*((LLDate*)val_ptr) = self.mCurReadSD->asDate();
196    return true;
197}
198
199bool LLParamSDParser::readURI(Parser& parser, void* val_ptr)
200{
201	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
202
203	*((LLURI*)val_ptr) = self.mCurReadSD->asURI();
204    return true;
205}
206
207bool LLParamSDParser::readSD(Parser& parser, void* val_ptr)
208{
209	LLParamSDParser& self = static_cast<LLParamSDParser&>(parser);
210
211	*((LLSD*)val_ptr) = *self.mCurReadSD;
212    return true;
213}
214
215// static
216LLSD& LLParamSDParserUtilities::getSDWriteNode(LLSD& input, LLInitParam::Parser::name_stack_range_t& name_stack_range)
217{
218	LLSD* sd_to_write = &input;
219	
220	for (LLInitParam::Parser::name_stack_t::iterator it = name_stack_range.first;
221		it != name_stack_range.second;
222		++it)
223	{
224		bool new_traversal = it->second;
225
226		LLSD* child_sd = it->first.empty() ? sd_to_write : &(*sd_to_write)[it->first];
227
228		if (child_sd->isArray())
229		{
230			if (new_traversal)
231			{
232				// write to new element at end
233				sd_to_write = &(*child_sd)[child_sd->size()];
234			}
235			else
236			{
237				// write to last of existing elements, or first element if empty
238				sd_to_write = &(*child_sd)[llmax(0, child_sd->size() - 1)];
239			}
240		}
241		else
242		{
243			if (new_traversal 
244				&& child_sd->isDefined() 
245				&& !child_sd->isArray())
246			{
247				// copy child contents into first element of an array
248				LLSD new_array = LLSD::emptyArray();
249				new_array.append(*child_sd);
250				// assign array to slot that previously held the single value
251				*child_sd = new_array;
252				// return next element in that array
253				sd_to_write = &((*child_sd)[1]);
254			}
255			else
256			{
257				sd_to_write = child_sd;
258			}
259		}
260		it->second = false;
261	}
262	
263	return *sd_to_write;
264}
265
266//static
267void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd, LLInitParam::Parser::name_stack_t& stack)
268{
269	if (sd.isMap())
270	{
271		for (LLSD::map_const_iterator it = sd.beginMap();
272			it != sd.endMap();
273			++it)
274		{
275			stack.push_back(make_pair(it->first, true));
276			readSDValues(cb, it->second, stack);
277			stack.pop_back();
278		}
279	}
280	else if (sd.isArray())
281	{
282		for (LLSD::array_const_iterator it = sd.beginArray();
283			it != sd.endArray();
284			++it)
285		{
286			stack.back().second = true;
287			readSDValues(cb, *it, stack);
288		}
289	}
290	else if (sd.isUndefined())
291	{
292		if (!cb.empty())
293		{
294			cb(NO_VALUE_MARKER, stack);
295		}
296	}
297	else
298	{
299		if (!cb.empty())
300		{
301			cb(sd, stack);
302		}
303	}
304}
305
306//static
307void LLParamSDParserUtilities::readSDValues(read_sd_cb_t cb, const LLSD& sd)
308{
309	LLInitParam::Parser::name_stack_t stack = LLInitParam::Parser::name_stack_t();
310	readSDValues(cb, sd, stack);
311}
312namespace LLInitParam
313{
314	// LLSD specialization
315	// block param interface
316	bool ParamValue<LLSD, TypeValues<LLSD>, false>::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack, bool new_name)
317	{
318		LLSD& sd = LLParamSDParserUtilities::getSDWriteNode(mValue, name_stack);
319
320		LLSD::String string;
321
322		if (p.readValue<LLSD::String>(string))
323		{
324			sd = string;
325			return true;
326		}
327		return false;
328	}
329
330	//static
331	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeElement(Parser& p, const LLSD& sd, Parser::name_stack_t& name_stack)
332	{
333		p.writeValue<LLSD::String>(sd.asString(), name_stack);
334	}
335
336	void ParamValue<LLSD, TypeValues<LLSD>, false>::serializeBlock(Parser& p, Parser::name_stack_t& name_stack, const BaseBlock* diff_block) const
337	{
338		// read from LLSD value and serialize out to parser (which could be LLSD, XUI, etc)
339		Parser::name_stack_t stack;
340		LLParamSDParserUtilities::readSDValues(boost::bind(&serializeElement, boost::ref(p), _1, _2), mValue, stack);
341	}
342}