llinitparam.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:15k
源码类别:

游戏引擎

开发平台:

C++ Builder

  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=viewergpl$
  7.  * 
  8.  * Copyright (c) 2008-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. #include "linden_common.h"
  34. #include "llinitparam.h"
  35. namespace LLInitParam
  36. {
  37. //
  38. // Param
  39. //
  40. Param::Param(BaseBlock* enclosing_block)
  41. : mIsProvided(false)
  42. {
  43. const U8* my_addr = reinterpret_cast<const U8*>(this);
  44. const U8* block_addr = reinterpret_cast<const U8*>(enclosing_block);
  45. mEnclosingBlockOffset = (U16)(my_addr - block_addr);
  46. }
  47. //
  48. // Parser
  49. //
  50. Parser::~Parser()
  51. {}
  52. void Parser::parserWarning(const std::string& message)
  53. {
  54. if (mParseSilently) return;
  55. llwarns << message << llendl;
  56. }
  57. void Parser::parserError(const std::string& message)
  58. {
  59. if (mParseSilently) return;
  60. llerrs << message << llendl;
  61. }
  62. //
  63. // BlockDescriptor
  64. //
  65. void BlockDescriptor::aggregateBlockData(BlockDescriptor& src_block_data) 
  66. {
  67. mNamedParams.insert(src_block_data.mNamedParams.begin(), src_block_data.mNamedParams.end());
  68. mSynonyms.insert(src_block_data.mSynonyms.begin(), src_block_data.mSynonyms.end());
  69. std::copy(src_block_data.mUnnamedParams.begin(), src_block_data.mUnnamedParams.end(), std::back_inserter(mUnnamedParams));
  70. std::copy(src_block_data.mValidationList.begin(), src_block_data.mValidationList.end(), std::back_inserter(mValidationList));
  71. std::copy(src_block_data.mAllParams.begin(), src_block_data.mAllParams.end(), std::back_inserter(mAllParams));
  72. }
  73. //
  74. // BaseBlock
  75. //
  76. BaseBlock::BaseBlock()
  77. : mChangeVersion(0),
  78. mBlockDescriptor(NULL)
  79. {}
  80. BaseBlock::~BaseBlock()
  81. {}
  82. // called by each derived class in least to most derived order
  83. void BaseBlock::init(BlockDescriptor& descriptor, BlockDescriptor& base_descriptor, size_t block_size)
  84. {
  85. mBlockDescriptor = &descriptor;
  86. descriptor.mCurrentBlockPtr = this;
  87. descriptor.mMaxParamOffset = block_size;
  88. switch(descriptor.mInitializationState)
  89. {
  90. case BlockDescriptor::UNINITIALIZED:
  91. // copy params from base class here
  92. descriptor.aggregateBlockData(base_descriptor);
  93. descriptor.mInitializationState = BlockDescriptor::INITIALIZING;
  94. break;
  95. case BlockDescriptor::INITIALIZING:
  96. descriptor.mInitializationState = BlockDescriptor::INITIALIZED;
  97. break;
  98. case BlockDescriptor::INITIALIZED:
  99. // nothing to do
  100. break;
  101. }
  102. }
  103. param_handle_t BaseBlock::getHandleFromParam(const Param* param) const
  104. {
  105. const U8* param_address = reinterpret_cast<const U8*>(param);
  106. const U8* baseblock_address = reinterpret_cast<const U8*>(this);
  107. return (param_address - baseblock_address);
  108. }
  109. bool BaseBlock::submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent)
  110. {
  111. if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end())))
  112. {
  113. if (!silent)
  114. {
  115. p.parserWarning(llformat("Failed to parse parameter "%s"", p.getCurrentElementName().c_str()));
  116. }
  117. return false;
  118. }
  119. return true;
  120. }
  121. bool BaseBlock::validateBlock(bool emit_errors) const
  122. {
  123. const BlockDescriptor& block_data = getBlockDescriptor();
  124. for (BlockDescriptor::param_validation_list_t::const_iterator it = block_data.mValidationList.begin(); it != block_data.mValidationList.end(); ++it)
  125. {
  126. const Param* param = getParamFromHandle(it->first);
  127. if (!it->second(param))
  128. {
  129. if (emit_errors)
  130. {
  131. llwarns << "Invalid param "" << getParamName(block_data, param) << """ << llendl;
  132. }
  133. return false;
  134. }
  135. }
  136. return true;
  137. }
  138. bool BaseBlock::serializeBlock(Parser& parser, Parser::name_stack_t name_stack, const LLInitParam::BaseBlock* diff_block) const
  139. {
  140. // named param is one like LLView::Params::follows
  141. // unnamed param is like LLView::Params::rect - implicit
  142. const BlockDescriptor& block_data = getBlockDescriptor();
  143. for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); 
  144. it != block_data.mUnnamedParams.end(); 
  145. ++it)
  146. {
  147. param_handle_t param_handle = (*it)->mParamHandle;
  148. const Param* param = getParamFromHandle(param_handle);
  149. ParamDescriptor::serialize_func_t serialize_func = (*it)->mSerializeFunc;
  150. if (serialize_func)
  151. {
  152. const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
  153. // each param descriptor remembers its serial number
  154. // so we can inspect the same param under different names
  155. // and see that it has the same number
  156. (*it)->mGeneration = parser.newParseGeneration();
  157. name_stack.push_back(std::make_pair("", (*it)->mGeneration));
  158. serialize_func(*param, parser, name_stack, diff_param);
  159. name_stack.pop_back();
  160. }
  161. }
  162. for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
  163. it != block_data.mNamedParams.end();
  164. ++it)
  165. {
  166. param_handle_t param_handle = it->second->mParamHandle;
  167. const Param* param = getParamFromHandle(param_handle);
  168. ParamDescriptor::serialize_func_t serialize_func = it->second->mSerializeFunc;
  169. if (serialize_func)
  170. {
  171. // Ensure this param has not already been serialized
  172. // Prevents <rect> from being serialized as its own tag.
  173. bool duplicate = false;
  174. for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); 
  175. it2 != block_data.mUnnamedParams.end(); 
  176. ++it2)
  177. {
  178. if (param_handle == (*it2)->mParamHandle)
  179. {
  180. duplicate = true;
  181. break;
  182. }
  183. }
  184. //FIXME: for now, don't attempt to serialize values under synonyms, as current parsers
  185. // don't know how to detect them
  186. if (duplicate) 
  187. {
  188. continue;
  189. }
  190. if (!duplicate)
  191. {
  192. it->second->mGeneration = parser.newParseGeneration();
  193. }
  194. name_stack.push_back(std::make_pair(it->first, it->second->mGeneration));
  195. const Param* diff_param = diff_block ? diff_block->getParamFromHandle(param_handle) : NULL;
  196. serialize_func(*param, parser, name_stack, diff_param);
  197. name_stack.pop_back();
  198. }
  199. }
  200. return true;
  201. }
  202. bool BaseBlock::inspectBlock(Parser& parser, Parser::name_stack_t name_stack) const
  203. {
  204. // named param is one like LLView::Params::follows
  205. // unnamed param is like LLView::Params::rect - implicit
  206. const BlockDescriptor& block_data = getBlockDescriptor();
  207. for (BlockDescriptor::param_list_t::const_iterator it = block_data.mUnnamedParams.begin(); 
  208. it != block_data.mUnnamedParams.end(); 
  209. ++it)
  210. {
  211. param_handle_t param_handle = (*it)->mParamHandle;
  212. const Param* param = getParamFromHandle(param_handle);
  213. ParamDescriptor::inspect_func_t inspect_func = (*it)->mInspectFunc;
  214. if (inspect_func)
  215. {
  216. (*it)->mGeneration = parser.newParseGeneration();
  217. name_stack.push_back(std::make_pair("", (*it)->mGeneration));
  218. inspect_func(*param, parser, name_stack, (*it)->mMinCount, (*it)->mMaxCount);
  219. name_stack.pop_back();
  220. }
  221. }
  222. for(BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin();
  223. it != block_data.mNamedParams.end();
  224. ++it)
  225. {
  226. param_handle_t param_handle = it->second->mParamHandle;
  227. const Param* param = getParamFromHandle(param_handle);
  228. ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc;
  229. if (inspect_func)
  230. {
  231. // Ensure this param has not already been inspected
  232. bool duplicate = false;
  233. for (BlockDescriptor::param_list_t::const_iterator it2 = block_data.mUnnamedParams.begin(); 
  234. it2 != block_data.mUnnamedParams.end(); 
  235. ++it2)
  236. {
  237. if (param_handle == (*it2)->mParamHandle)
  238. {
  239. duplicate = true;
  240. break;
  241. }
  242. }
  243. if (!duplicate)
  244. {
  245. it->second->mGeneration = parser.newParseGeneration();
  246. }
  247. name_stack.push_back(std::make_pair(it->first, it->second->mGeneration));
  248. inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
  249. name_stack.pop_back();
  250. }
  251. }
  252. for(BlockDescriptor::param_map_t::const_iterator it = block_data.mSynonyms.begin();
  253. it != block_data.mSynonyms.end();
  254. ++it)
  255. {
  256. param_handle_t param_handle = it->second->mParamHandle;
  257. const Param* param = getParamFromHandle(param_handle);
  258. ParamDescriptor::inspect_func_t inspect_func = it->second->mInspectFunc;
  259. if (inspect_func)
  260. {
  261. // use existing serial number for param
  262. name_stack.push_back(std::make_pair(it->first, it->second->mGeneration));
  263. inspect_func(*param, parser, name_stack, it->second->mMinCount, it->second->mMaxCount);
  264. name_stack.pop_back();
  265. }
  266. }
  267. return true;
  268. }
  269. bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack)
  270. {
  271. BlockDescriptor& block_data = getBlockDescriptor();
  272. bool names_left = name_stack.first != name_stack.second;
  273. if (names_left)
  274. {
  275. const std::string& top_name = name_stack.first->first;
  276. ParamDescriptor::deserialize_func_t deserialize_func = NULL;
  277. Param* paramp = NULL;
  278. BlockDescriptor::param_map_t::iterator found_it = block_data.mNamedParams.find(top_name);
  279. if (found_it != block_data.mNamedParams.end())
  280. {
  281. // find pointer to member parameter from offset table
  282. paramp = getParamFromHandle(found_it->second->mParamHandle);
  283. deserialize_func = found_it->second->mDeserializeFunc;
  284. }
  285. else
  286. {
  287. BlockDescriptor::param_map_t::iterator found_it = block_data.mSynonyms.find(top_name);
  288. if (found_it != block_data.mSynonyms.end())
  289. {
  290. // find pointer to member parameter from offset table
  291. paramp = getParamFromHandle(found_it->second->mParamHandle);
  292. deserialize_func = found_it->second->mDeserializeFunc;
  293. }
  294. }
  295. Parser::name_stack_range_t new_name_stack(name_stack.first, name_stack.second);
  296. ++new_name_stack.first;
  297. if (deserialize_func)
  298. {
  299. return deserialize_func(*paramp, p, new_name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second);
  300. }
  301. }
  302. // try to parse unnamed parameters, in declaration order
  303. for ( BlockDescriptor::param_list_t::iterator it = block_data.mUnnamedParams.begin(); 
  304. it != block_data.mUnnamedParams.end(); 
  305. ++it)
  306. {
  307. Param* paramp = getParamFromHandle((*it)->mParamHandle);
  308. ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc;
  309. if (deserialize_func && deserialize_func(*paramp, p, name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second))
  310. {
  311. return true;
  312. }
  313. }
  314. return false;
  315. }
  316. //static 
  317. void BaseBlock::addParam(BlockDescriptor& block_data, const ParamDescriptor& in_param, const char* char_name)
  318. {
  319. // create a copy of the paramdescriptor in allparams
  320. // so other data structures can store a pointer to it
  321. block_data.mAllParams.push_back(in_param);
  322. ParamDescriptor& param(block_data.mAllParams.back());
  323. std::string name(char_name);
  324. if ((size_t)param.mParamHandle > block_data.mMaxParamOffset)
  325. {
  326. 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;
  327. }
  328. if (name.empty())
  329. {
  330. block_data.mUnnamedParams.push_back(&param);
  331. }
  332. else
  333. {
  334. // don't use insert, since we want to overwrite existing entries
  335. block_data.mNamedParams[name] = &param;
  336. }
  337. if (param.mValidationFunc)
  338. {
  339. block_data.mValidationList.push_back(std::make_pair(param.mParamHandle, param.mValidationFunc));
  340. }
  341. }
  342. void BaseBlock::addSynonym(Param& param, const std::string& synonym)
  343. {
  344. BlockDescriptor& block_data = getBlockDescriptor();
  345. if (block_data.mInitializationState == BlockDescriptor::INITIALIZING)
  346. {
  347. param_handle_t handle = getHandleFromParam(&param);
  348. // check for invalid derivation from a paramblock (i.e. without using
  349. // Block<T, Base_Class>
  350. if ((size_t)handle > block_data.mMaxParamOffset)
  351. {
  352. 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;
  353. }
  354. ParamDescriptor* param_descriptor = findParamDescriptor(handle);
  355. if (param_descriptor)
  356. {
  357. if (synonym.empty())
  358. {
  359. block_data.mUnnamedParams.push_back(param_descriptor);
  360. }
  361. else
  362. {
  363. block_data.mSynonyms[synonym] = param_descriptor;
  364. }
  365. }
  366. }
  367. }
  368. void BaseBlock::setLastChangedParam(const Param& last_param, bool user_provided)
  369. if (user_provided)
  370. {
  371. mChangeVersion++;
  372. }
  373. }
  374. const std::string& BaseBlock::getParamName(const BlockDescriptor& block_data, const Param* paramp) const
  375. {
  376. param_handle_t handle = getHandleFromParam(paramp);
  377. for (BlockDescriptor::param_map_t::const_iterator it = block_data.mNamedParams.begin(); it != block_data.mNamedParams.end(); ++it)
  378. {
  379. if (it->second->mParamHandle == handle)
  380. {
  381. return it->first;
  382. }
  383. }
  384. for (BlockDescriptor::param_map_t::const_iterator it = block_data.mSynonyms.begin(); it != block_data.mSynonyms.end(); ++it)
  385. {
  386. if (it->second->mParamHandle == handle)
  387. {
  388. return it->first;
  389. }
  390. }
  391. return LLStringUtil::null;
  392. }
  393. ParamDescriptor* BaseBlock::findParamDescriptor(param_handle_t handle)
  394. {
  395. BlockDescriptor& descriptor = getBlockDescriptor();
  396. BlockDescriptor::all_params_list_t::iterator end_it = descriptor.mAllParams.end();
  397. for (BlockDescriptor::all_params_list_t::iterator it = descriptor.mAllParams.begin();
  398. it != end_it;
  399. ++it)
  400. {
  401. if (it->mParamHandle == handle) return &(*it);
  402. }
  403. return NULL;
  404. }
  405. // take all provided params from other and apply to self
  406. // NOTE: this requires that "other" is of the same derived type as this
  407. bool BaseBlock::merge(BlockDescriptor& block_data, const BaseBlock& other, bool overwrite)
  408. {
  409. bool param_changed = false;
  410. BlockDescriptor::all_params_list_t::const_iterator end_it = block_data.mAllParams.end();
  411. for (BlockDescriptor::all_params_list_t::const_iterator it = block_data.mAllParams.begin();
  412. it != end_it;
  413. ++it)
  414. {
  415. const Param* other_paramp = other.getParamFromHandle(it->mParamHandle);
  416. ParamDescriptor::merge_func_t merge_func = it->mMergeFunc;
  417. if (merge_func)
  418. {
  419. Param* paramp = getParamFromHandle(it->mParamHandle);
  420. param_changed |= merge_func(*paramp, *other_paramp, overwrite);
  421. }
  422. }
  423. return param_changed;
  424. }
  425. bool ParamCompare<LLSD, false>::equals(const LLSD &a, const LLSD &b)
  426. {
  427. return false;
  428. }
  429. }