PageRenderTime 43ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llui/lltextparser.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 239 lines | 178 code | 31 blank | 30 comment | 40 complexity | 256137d4e7c61f416b97688fa6fadfe1 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file lltextparser.cpp
  3. *
  4. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  5. * Second Life Viewer Source Code
  6. * Copyright (C) 2010, Linden Research, Inc.
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation;
  11. * version 2.1 of the License only.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. *
  22. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  23. * $/LicenseInfo$
  24. */
  25. #include "linden_common.h"
  26. #include "lltextparser.h"
  27. #include "llsd.h"
  28. #include "llsdserialize.h"
  29. #include "llerror.h"
  30. #include "lluuid.h"
  31. #include "llstring.h"
  32. #include "message.h"
  33. #include "llmath.h"
  34. #include "v4color.h"
  35. #include "lldir.h"
  36. //
  37. // Member Functions
  38. //
  39. LLTextParser::LLTextParser()
  40. : mLoaded(false)
  41. {}
  42. S32 LLTextParser::findPattern(const std::string &text, LLSD highlight)
  43. {
  44. if (!highlight.has("pattern")) return -1;
  45. std::string pattern=std::string(highlight["pattern"]);
  46. std::string ltext=text;
  47. if (!(bool)highlight["case_sensitive"])
  48. {
  49. ltext = utf8str_tolower(text);
  50. pattern= utf8str_tolower(pattern);
  51. }
  52. size_t found=std::string::npos;
  53. switch ((S32)highlight["condition"])
  54. {
  55. case CONTAINS:
  56. found = ltext.find(pattern);
  57. break;
  58. case MATCHES:
  59. found = (! ltext.compare(pattern) ? 0 : std::string::npos);
  60. break;
  61. case STARTS_WITH:
  62. found = (! ltext.find(pattern) ? 0 : std::string::npos);
  63. break;
  64. case ENDS_WITH:
  65. S32 pos = ltext.rfind(pattern);
  66. if (pos >= 0 && (ltext.length()-pattern.length()==pos)) found = pos;
  67. break;
  68. }
  69. return found;
  70. }
  71. LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, EHighlightPosition part, S32 index)
  72. {
  73. loadKeywords();
  74. //evil recursive string atomizer.
  75. LLSD ret_llsd, start_llsd, middle_llsd, end_llsd;
  76. for (S32 i=index;i<mHighlights.size();i++)
  77. {
  78. S32 condition = mHighlights[i]["condition"];
  79. if ((S32)mHighlights[i]["highlight"]==PART && condition!=MATCHES)
  80. {
  81. if ( (condition==STARTS_WITH && part==START) ||
  82. (condition==ENDS_WITH && part==END) ||
  83. condition==CONTAINS || part==WHOLE )
  84. {
  85. S32 start = findPattern(text,mHighlights[i]);
  86. if (start >= 0 )
  87. {
  88. S32 end = std::string(mHighlights[i]["pattern"]).length();
  89. S32 len = text.length();
  90. EHighlightPosition newpart;
  91. if (start==0)
  92. {
  93. start_llsd[0]["text"] =text.substr(0,end);
  94. start_llsd[0]["color"]=mHighlights[i]["color"];
  95. if (end < len)
  96. {
  97. if (part==END || part==WHOLE) newpart=END; else newpart=MIDDLE;
  98. end_llsd=parsePartialLineHighlights(text.substr( end ),color,newpart,i);
  99. }
  100. }
  101. else
  102. {
  103. if (part==START || part==WHOLE) newpart=START; else newpart=MIDDLE;
  104. start_llsd=parsePartialLineHighlights(text.substr(0,start),color,newpart,i+1);
  105. if (end < len)
  106. {
  107. middle_llsd[0]["text"] =text.substr(start,end);
  108. middle_llsd[0]["color"]=mHighlights[i]["color"];
  109. if (part==END || part==WHOLE) newpart=END; else newpart=MIDDLE;
  110. end_llsd=parsePartialLineHighlights(text.substr( (start+end) ),color,newpart,i);
  111. }
  112. else
  113. {
  114. end_llsd[0]["text"] =text.substr(start,end);
  115. end_llsd[0]["color"]=mHighlights[i]["color"];
  116. }
  117. }
  118. S32 retcount=0;
  119. //FIXME These loops should be wrapped into a subroutine.
  120. for (LLSD::array_iterator iter = start_llsd.beginArray();
  121. iter != start_llsd.endArray();++iter)
  122. {
  123. LLSD highlight = *iter;
  124. ret_llsd[retcount++]=highlight;
  125. }
  126. for (LLSD::array_iterator iter = middle_llsd.beginArray();
  127. iter != middle_llsd.endArray();++iter)
  128. {
  129. LLSD highlight = *iter;
  130. ret_llsd[retcount++]=highlight;
  131. }
  132. for (LLSD::array_iterator iter = end_llsd.beginArray();
  133. iter != end_llsd.endArray();++iter)
  134. {
  135. LLSD highlight = *iter;
  136. ret_llsd[retcount++]=highlight;
  137. }
  138. return ret_llsd;
  139. }
  140. }
  141. }
  142. }
  143. //No patterns found. Just send back what was passed in.
  144. ret_llsd[0]["text"] =text;
  145. LLSD color_sd = color.getValue();
  146. ret_llsd[0]["color"]=color_sd;
  147. return ret_llsd;
  148. }
  149. bool LLTextParser::parseFullLineHighlights(const std::string &text, LLColor4 *color)
  150. {
  151. loadKeywords();
  152. for (S32 i=0;i<mHighlights.size();i++)
  153. {
  154. if ((S32)mHighlights[i]["highlight"]==ALL || (S32)mHighlights[i]["condition"]==MATCHES)
  155. {
  156. if (findPattern(text,mHighlights[i]) >= 0 )
  157. {
  158. LLSD color_llsd = mHighlights[i]["color"];
  159. color->setValue(color_llsd);
  160. return TRUE;
  161. }
  162. }
  163. }
  164. return FALSE; //No matches found.
  165. }
  166. std::string LLTextParser::getFileName()
  167. {
  168. std::string path=gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "");
  169. if (!path.empty())
  170. {
  171. path = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "highlights.xml");
  172. }
  173. return path;
  174. }
  175. void LLTextParser::loadKeywords()
  176. {
  177. if (mLoaded)
  178. {// keywords already loaded
  179. return;
  180. }
  181. std::string filename=getFileName();
  182. if (!filename.empty())
  183. {
  184. llifstream file;
  185. file.open(filename.c_str());
  186. if (file.is_open())
  187. {
  188. LLSDSerialize::fromXML(mHighlights, file);
  189. }
  190. file.close();
  191. mLoaded = true;
  192. }
  193. }
  194. bool LLTextParser::saveToDisk(LLSD highlights)
  195. {
  196. mHighlights=highlights;
  197. std::string filename=getFileName();
  198. if (filename.empty())
  199. {
  200. llwarns << "LLTextParser::saveToDisk() no valid user directory." << llendl;
  201. return FALSE;
  202. }
  203. llofstream file;
  204. file.open(filename.c_str());
  205. LLSDSerialize::toPrettyXML(mHighlights, file);
  206. file.close();
  207. return TRUE;
  208. }