PageRenderTime 124ms CodeModel.GetById 57ms RepoModel.GetById 0ms app.codeStats 1ms

/indra/llxuixml/llinitparam.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 469 lines | 352 code | 51 blank | 66 comment | 60 complexity | 6411e9d6c3cc83b453f16a1449cff485 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llinitparam.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. #include "linden_common.h"
  28. #include "llinitparam.h"
  29. namespace LLInitParam
  30. {
  31. //
  32. // Param
  33. //
  34. Param::Param(BaseBlock* enclosing_block)
  35. : mIsProvided(false)
  36. {
  37. const U8* my_addr = reinterpret_cast<const U8*>(this);
  38. const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
  39. mEnclosingBlockOffset = 0x7FFFffff & (U32)(my_addr - block_addr);
  40. }
  41. //
  42. // ParamDescriptor
  43. //
  44. ParamDescriptor::ParamDescriptor(param_handle_t p,
  45. merge_func_t merge_func,
  46. deserialize_func_t deserialize_func,
  47. serialize_func_t serialize_func,
  48. validation_func_t validation_func,
  49. inspect_func_t inspect_func,
  50. S32 min_count,
  51. S32 max_count)
  52. : mParamHandle(p),
  53. mMergeFunc(merge_func),
  54. mDeserializeFunc(deserialize_func),
  55. mSerializeFunc(serialize_func),
  56. mValidationFunc(validation_func),
  57. mInspectFunc(inspect_func),
  58. mMinCount(min_count),
  59. mMaxCount(max_count),
  60. mUserData(NULL)
  61. {}
  62. ParamDescriptor::ParamDescriptor()
  63. : mParamHandle(0),
  64. mMergeFunc(NULL),
  65. mDeserializeFunc(NULL),
  66. mSerializeFunc(NULL),
  67. mValidationFunc(NULL),
  68. mInspectFunc(NULL),
  69. mMinCount(0),
  70. mMaxCount(0),
  71. mUserData(NULL)
  72. {}
  73. ParamDescriptor::~ParamDescriptor()
  74. {
  75. delete mUserData;
  76. }
  77. //
  78. // Parser
  79. //
  80. Parser::~Parser()
  81. {}
  82. void Parser::parserWarning(const std::string& message)
  83. {
  84. if (mParseSilently) return;
  85. llwarns << message << llendl;
  86. }
  87. void Parser::parserError(const std::string& message)
  88. {
  89. if (mParseSilently) return;
  90. llerrs << message << llendl;
  91. }
  92. //
  93. // BlockDescriptor
  94. //
  95. void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data)
  96. {
  97. mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end());
  98. std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams));
  99. std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList));
  100. std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
  101. }
  102. BlockDescriptor::BlockDescriptor()
  103. : mMaxParamOffset(0),
  104. mInitializationState(UNINITIALIZED),
  105. mCurrentBlockPtr(NULL)
  106. {}
  107. // called by each derived class in least to most derived order
  108. void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
  109. {
  110. descriptor.mCurrentBlockPtr = this;
  111. descriptor.mMaxParamOffset = block_size;
  112. switch(descriptor.mInitializationState)
  113. {
  114. case BlockDescriptor::UNINITIALIZED:
  115. // copy params from base class here
  116. descriptor.aggregateBlockData(base_descriptor);
  117. descriptor.mInitializationState = BlockDescriptor::INITIALIZING;
  118. break;
  119. case BlockDescriptor::INITIALIZING:
  120. descriptor.mInitializationState = BlockDescriptor::INITIALIZED;
  121. break;
  122. case BlockDescriptor::INITIALIZED:
  123. // nothing to do
  124. break;
  125. }
  126. }
  127. param_handle_t BaseBlock::getHandleFromParam(const Param* param) const
  128. {
  129. const U8* param_address = reinterpret_cast<const U8*>(param);
  130. const U8* baseblock_address = reinterpret_cast<const U8*>(this);
  131. return (param_address - baseblock_address);
  132. }
  133. bool BaseBlock::submitValue(Parser::name_stack_t& name_stack, Parser& p, bool silent)
  134. {
  135. if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end()), true))
  136. {
  137. if (!silent)
  138. {
  139. p.parserWarning(llformat("Failed to parse parameter \"%s\"", p.getCurrentElementName().c_str()));
  140. }
  141. return false;
  142. }
  143. return true;
  144. }
  145. bool BaseBlock::validateBlock(bool emit_errors) const
  146. {
  147. const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
  148. for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
  149. {
  150. const Param* param = getParamFromHandle(it->first);
  151. if (!it->second(param))
  152. {
  153. if (emit_errors)
  154. {
  155. llwarns << "Invalid param \"" << getParamName(block_data, param) << "\"" << llendl;
  156. }
  157. return false;
  158. }
  159. }
  160. return true;
  161. }
  162. void BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t& name_stack, const LLInitParam::BaseBlock* diff_block) const
  163. {
  164. // named param is one like LLView::Params::follows
  165. // unnamed param is like LLView::Params::rect - implicit
  166. const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
  167. for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin();
  168. it != block_data.mUnnamedParams.end();
  169. ++it)
  170. {
  171. param_handle_t param_handle = (*it)->mParamHandle;
  172. const Param* param = getParamFromHandle(param_handle);
  173. ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc;
  174. if (serialize_func)
  175. {
  176. const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
  177. // each param descriptor remembers its serial number
  178. // so we can inspect the same param under different names
  179. // and see that it has the same number
  180. name_stack.push_back(std::make_pair("", true));
  181. serialize_func(*param, parser, name_stack, diff_param);
  182. name_stack.pop_back();
  183. }
  184. }
  185. for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
  186. it != block_data.mNamedParams.end();
  187. ++it)
  188. {
  189. param_handle_t param_handle = it->second->mParamHandle;
  190. const Param* param = getParamFromHandle(param_handle);
  191. ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc;
  192. if (serialize_func && param->anyProvided())
  193. {
  194. // Ensure this param has not already been serialized
  195. // Prevents <rect> from being serialized as its own tag.
  196. bool duplicate = false;
  197. for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin();
  198. it2 != block_data.mUnnamedParams.end();
  199. ++it2)
  200. {
  201. if (param_handle == (*it2)->mParamHandle)
  202. {
  203. duplicate = true;
  204. break;
  205. }
  206. }
  207. //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers
  208. // don't know how to detect them
  209. if (duplicate)
  210. {
  211. continue;
  212. }
  213. name_stack.push_back(std::make_pair(it->first, !duplicate));
  214. const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
  215. serialize_func(*param, parser, name_stack, diff_param);
  216. name_stack.pop_back();
  217. }
  218. }
  219. }
  220. bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack, S32 min_count, S32 max_count) const
  221. {
  222. // named param is one like LLView::Params::follows
  223. // unnamed param is like LLView::Params::rect - implicit
  224. const BlockDescriptor& block_data = mostDerivedBlockDescriptor();
  225. for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin();
  226. it != block_data.mUnnamedParams.end();
  227. ++it)
  228. {
  229. param_handle_t param_handle = (*it)->mParamHandle;
  230. const Param* param = getParamFromHandle(param_handle);
  231. ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc;
  232. if (inspect_func)
  233. {
  234. name_stack.push_back(std::make_pair("", true));
  235. inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount);
  236. name_stack.pop_back();
  237. }
  238. }
  239. for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
  240. it != block_data.mNamedParams.end();
  241. ++it)
  242. {
  243. param_handle_t param_handle = it->second->mParamHandle;
  244. const Param* param = getParamFromHandle(param_handle);
  245. ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc;
  246. if (inspect_func)
  247. {
  248. // Ensure this param has not already been inspected
  249. bool duplicate = false;
  250. for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin();
  251. it2 != block_data.mUnnamedParams.end();
  252. ++it2)
  253. {
  254. if (param_handle == (*it2)->mParamHandle)
  255. {
  256. duplicate = true;
  257. break;
  258. }
  259. }
  260. name_stack.push_back(std::make_pair(it->first, !duplicate));
  261. inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
  262. name_stack.pop_back();
  263. }
  264. }
  265. return true;
  266. }
  267. bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack_range, bool ignored)
  268. {
  269. BlockDescriptor& block_data = mostDerivedBlockDescriptor();
  270. bool names_left = name_stack_range.first != name_stack_range.second;
  271. bool new_name = names_left
  272. ? name_stack_range.first->second
  273. : true;
  274. if (names_left)
  275. {
  276. const std::string& top_name = name_stack_range.first->first;
  277. ParamDescriptor::deserialize_func_t deserialize_func = NULL;
  278. Param* paramp = NULL;
  279. BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);
  280. if (found_it != block_data.mNamedParams.end())
  281. {
  282. // find pointer to member parameter from offset table
  283. paramp = getParamFromHandle(found_it->second->mParamHandle);
  284. deserialize_func = found_it->second->mDeserializeFunc;
  285. Parser::name_stack_range_t new_name_stack(name_stack_range.first, name_stack_range.second);
  286. ++new_name_stack.first;
  287. if (deserialize_func(*paramp, p, new_name_stack, new_name))
  288. {
  289. // value is no longer new, we know about it now
  290. name_stack_range.first->second = false;
  291. return true;
  292. }
  293. else
  294. {
  295. return false;
  296. }
  297. }
  298. }
  299. // try to parse unnamed parameters, in declaration order
  300. for ( BlockDescriptor::param_list_t::iterator it = block_data.mUnnamedParams.begin();
  301. it != block_data.mUnnamedParams.end();
  302. ++it)
  303. {
  304. Param* paramp = getParamFromHandle((*it)->mParamHandle);
  305. ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc;
  306. if (deserialize_func && deserialize_func(*paramp, p, name_stack_range, new_name))
  307. {
  308. return true;
  309. }
  310. }
  311. // if no match, and no names left on stack, this is just an existence assertion of this block
  312. // verify by calling readValue with NoParamValue type, an inherently unparseable type
  313. if (!names_left)
  314. {
  315. Flag no_value;
  316. return p.readValue(no_value);
  317. }
  318. return false;
  319. }
  320. //static
  321. void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptorPtr in_param, const char* char_name)
  322. {
  323. // create a copy of the param descriptor in mAllParams
  324. // so other data structures can store a pointer to it
  325. block_data.mAllParams.push_back(in_param);
  326. ParamDescriptorPtr param(block_data.mAllParams.back());
  327. std::string name(char_name);
  328. if ((size_t)param->mParamHandle > block_data.mMaxParamOffset)
  329. {
  330. llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
  331. }
  332. if (name.empty())
  333. {
  334. block_data.mUnnamedParams.push_back(param);
  335. }
  336. else
  337. {
  338. // don't use insert, since we want to overwrite existing entries
  339. block_data.mNamedParams[name] = param;
  340. }
  341. if (param->mValidationFunc)
  342. {
  343. block_data.mValidationList.push_back(std::make_pair(param->mParamHandle, param->mValidationFunc));
  344. }
  345. }
  346. void BaseBlock::addSynonym(Param& param, const std::string& synonym)
  347. {
  348. BlockDescriptor& block_data = mostDerivedBlockDescriptor();
  349. if (block_data.mInitializationState == BlockDescriptor::INITIALIZING)
  350. {
  351. param_handle_t handle = getHandleFromParam(&param);
  352. // check for invalid derivation from a paramblock (i.e. without using
  353. // Block<T, Base_Class>
  354. if ((size_t)handle > block_data.mMaxParamOffset)
  355. {
  356. llerrs << "Attempted to register param with block defined for parent class, make sure to derive from LLInitParam::Block<YOUR_CLASS, PARAM_BLOCK_BASE_CLASS>" << llendl;
  357. }
  358. ParamDescriptorPtr param_descriptor = findParamDescriptor(param);
  359. if (param_descriptor)
  360. {
  361. if (synonym.empty())
  362. {
  363. block_data.mUnnamedParams.push_back(param_descriptor);
  364. }
  365. else
  366. {
  367. block_data.mNamedParams[synonym] = param_descriptor;
  368. }
  369. }
  370. }
  371. }
  372. const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const
  373. {
  374. param_handle_t handle = getHandleFromParam(paramp);
  375. for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it)
  376. {
  377. if (it->second->mParamHandle == handle)
  378. {
  379. return it->first;
  380. }
  381. }
  382. return LLStringUtil::null;
  383. }
  384. ParamDescriptorPtr BaseBlock::findParamDescriptor(const Param& param)
  385. {
  386. param_handle_t handle = getHandleFromParam(&param);
  387. BlockDescriptor& descriptor = mostDerivedBlockDescriptor();
  388. BlockDescriptor::all_params_list_t::iterator end_it = descriptor.mAllParams.end();
  389. for (BlockDescriptor::all_params_list_t::iterator it = descriptor.mAllParams.begin();
  390. it != end_it;
  391. ++it)
  392. {
  393. if ((*it)->mParamHandle == handle) return *it;
  394. }
  395. return ParamDescriptorPtr();
  396. }
  397. // take all provided params from other and apply to self
  398. // NOTE: this requires that "other" is of the same derived type as this
  399. bool BaseBlock::mergeBlock(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
  400. {
  401. bool some_param_changed = false;
  402. BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end();
  403. for (BlockDescriptor::all_params_list_t::const_iterator it = block_data.mAllParams.begin();
  404. it != end_it;
  405. ++it)
  406. {
  407. const Param* other_paramp = other.getParamFromHandle((*it)->mParamHandle);
  408. ParamDescriptor::merge_func_t merge_func = (*it)->mMergeFunc;
  409. if (merge_func)
  410. {
  411. Param* paramp = getParamFromHandle((*it)->mParamHandle);
  412. llassert(paramp->mEnclosingBlockOffset == (*it)->mParamHandle);
  413. some_param_changed |= merge_func(*paramp, *other_paramp, overwrite);
  414. }
  415. }
  416. return some_param_changed;
  417. }
  418. }