PageRenderTime 66ms CodeModel.GetById 14ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 1ms

/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
  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
 26#include "linden_common.h"
 27
 28#include "lltextparser.h"
 29
 30#include "llsd.h"
 31#include "llsdserialize.h"
 32#include "llerror.h"
 33#include "lluuid.h"
 34#include "llstring.h"
 35#include "message.h"
 36#include "llmath.h"
 37#include "v4color.h"
 38#include "lldir.h"
 39
 40//
 41// Member Functions
 42//
 43
 44LLTextParser::LLTextParser()
 45:	mLoaded(false)
 46{}
 47
 48
 49S32 LLTextParser::findPattern(const std::string &text, LLSD highlight)
 50{
 51	if (!highlight.has("pattern")) return -1;
 52	
 53	std::string pattern=std::string(highlight["pattern"]);
 54	std::string ltext=text;
 55	
 56	if (!(bool)highlight["case_sensitive"])
 57	{
 58		ltext   = utf8str_tolower(text);
 59		pattern= utf8str_tolower(pattern);
 60	}
 61
 62	size_t found=std::string::npos;
 63	
 64	switch ((S32)highlight["condition"])
 65	{
 66		case CONTAINS:
 67			found = ltext.find(pattern); 
 68			break;
 69		case MATCHES:
 70		    found = (! ltext.compare(pattern) ? 0 : std::string::npos);
 71			break;
 72		case STARTS_WITH:
 73			found = (! ltext.find(pattern) ? 0 : std::string::npos);
 74			break;
 75		case ENDS_WITH:
 76			S32 pos = ltext.rfind(pattern); 
 77			if (pos >= 0 && (ltext.length()-pattern.length()==pos)) found = pos;
 78			break;
 79	}
 80	return found;
 81}
 82
 83LLSD LLTextParser::parsePartialLineHighlights(const std::string &text, const LLColor4 &color, EHighlightPosition part, S32 index)
 84{
 85	loadKeywords();
 86
 87	//evil recursive string atomizer.
 88	LLSD ret_llsd, start_llsd, middle_llsd, end_llsd;
 89
 90	for (S32 i=index;i<mHighlights.size();i++)
 91	{
 92		S32 condition = mHighlights[i]["condition"];
 93		if ((S32)mHighlights[i]["highlight"]==PART && condition!=MATCHES)
 94		{
 95			if ( (condition==STARTS_WITH && part==START) ||
 96			     (condition==ENDS_WITH   && part==END)   ||
 97				  condition==CONTAINS    || part==WHOLE )
 98			{
 99				S32 start = findPattern(text,mHighlights[i]);
100				if (start >= 0 )
101				{
102					S32 end =  std::string(mHighlights[i]["pattern"]).length();
103					S32 len = text.length();
104					EHighlightPosition newpart;
105					if (start==0)
106					{
107						start_llsd[0]["text"] =text.substr(0,end);
108						start_llsd[0]["color"]=mHighlights[i]["color"];
109						
110						if (end < len)
111						{
112							if (part==END   || part==WHOLE) newpart=END; else newpart=MIDDLE;
113							end_llsd=parsePartialLineHighlights(text.substr( end ),color,newpart,i);
114						}
115					}
116					else
117					{
118						if (part==START || part==WHOLE) newpart=START; else newpart=MIDDLE;
119
120						start_llsd=parsePartialLineHighlights(text.substr(0,start),color,newpart,i+1);
121						
122						if (end < len)
123						{
124							middle_llsd[0]["text"] =text.substr(start,end);
125							middle_llsd[0]["color"]=mHighlights[i]["color"];
126						
127							if (part==END   || part==WHOLE) newpart=END; else newpart=MIDDLE;
128
129							end_llsd=parsePartialLineHighlights(text.substr( (start+end) ),color,newpart,i);
130						}
131						else
132						{
133							end_llsd[0]["text"] =text.substr(start,end);
134							end_llsd[0]["color"]=mHighlights[i]["color"];
135						}
136					}
137						
138					S32 retcount=0;
139					
140					//FIXME These loops should be wrapped into a subroutine.
141					for (LLSD::array_iterator iter = start_llsd.beginArray();
142						 iter != start_llsd.endArray();++iter)
143					{
144						LLSD highlight = *iter;
145						ret_llsd[retcount++]=highlight;
146					}
147						   
148					for (LLSD::array_iterator iter = middle_llsd.beginArray();
149						 iter != middle_llsd.endArray();++iter)
150					{
151						LLSD highlight = *iter;
152						ret_llsd[retcount++]=highlight;
153					}
154						   
155					for (LLSD::array_iterator iter = end_llsd.beginArray();
156						 iter != end_llsd.endArray();++iter)
157					{
158						LLSD highlight = *iter;
159						ret_llsd[retcount++]=highlight;
160					}
161						   
162					return ret_llsd;
163				}
164			}
165		}
166	}
167	
168	//No patterns found.  Just send back what was passed in.
169	ret_llsd[0]["text"] =text;
170	LLSD color_sd = color.getValue();
171	ret_llsd[0]["color"]=color_sd;
172	return ret_llsd;
173}
174
175bool LLTextParser::parseFullLineHighlights(const std::string &text, LLColor4 *color)
176{
177	loadKeywords();
178
179	for (S32 i=0;i<mHighlights.size();i++)
180	{
181		if ((S32)mHighlights[i]["highlight"]==ALL || (S32)mHighlights[i]["condition"]==MATCHES)
182		{
183			if (findPattern(text,mHighlights[i]) >= 0 )
184			{
185				LLSD color_llsd = mHighlights[i]["color"];
186				color->setValue(color_llsd);
187				return TRUE;
188			}
189		}
190	}
191	return FALSE;	//No matches found.
192}
193
194std::string LLTextParser::getFileName()
195{
196	std::string path=gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "");
197	
198	if (!path.empty())
199	{
200		path = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "highlights.xml");
201	}
202	return path;  
203}
204
205void LLTextParser::loadKeywords()
206{
207	if (mLoaded)
208	{// keywords already loaded
209		return;
210	}
211	std::string filename=getFileName();
212	if (!filename.empty())
213	{
214		llifstream file;
215		file.open(filename.c_str());
216		if (file.is_open())
217		{
218			LLSDSerialize::fromXML(mHighlights, file);
219		}
220		file.close();
221		mLoaded = true;
222	}
223}
224
225bool LLTextParser::saveToDisk(LLSD highlights)
226{
227	mHighlights=highlights;
228	std::string filename=getFileName();
229	if (filename.empty())
230	{
231		llwarns << "LLTextParser::saveToDisk() no valid user directory." << llendl; 
232		return FALSE;
233	}	
234	llofstream file;
235	file.open(filename.c_str());
236	LLSDSerialize::toPrettyXML(mHighlights, file);
237	file.close();
238	return TRUE;
239}