std::string russ_format(const std::string& format_str, const LLSD& context)
{
	std::string service_url(format_str);
	if(!service_url.empty() && context.isMap())
	{
		// throw in a ridiculously large limiter to make sure we don't
		// loop forever with bad input.
		int iterations = 100;
		bool keep_looping = true;
		while(keep_looping)
		{
			if(0 == --iterations)
			{
				keep_looping = false;
			}

			int depth = 0;
			int deepest = 0;
			bool find_match = false;
			std::string::iterator iter(service_url.begin());
			std::string::iterator end(service_url.end());
			std::string::iterator deepest_node(service_url.end());
			std::string::iterator deepest_node_end(service_url.end());
			// parse out the variables to replace by going through {}s
			// one at a time, starting with the "deepest" in series
			// {{}}, and otherwise replacing right-to-left
			for(; iter != end; ++iter)
			{
				switch(*iter)
				{
				case '{':
					++depth;
					if(depth > deepest)
					{
						deepest = depth;
						deepest_node = iter;
						find_match = true;
					}
					break;
				case '}':
					--depth;
					if(find_match)
					{
						deepest_node_end = iter;
						find_match = false;
					}
					break;
				default:
					break;
				}
			}
			if((deepest_node == end) || (deepest_node_end == end))
			{
				break;
			}
			//replace the variable we found in the {} above.
			// *NOTE: since the c++ implementation only understands
			// params and straight string substitution, so it's a
			// known distance of 2 to skip the directive.
			std::string key(deepest_node + 2, deepest_node_end);
			LLSD value = context[key];
			switch(*(deepest_node + 1))
			{
			case '$':
				if(value.isDefined())
				{
					service_url.replace(
						deepest_node,
						deepest_node_end + 1,
						value.asString());
				}
				else
				{
					llwarns << "Unknown key: " << key << " in option map: "
						<< LLSDOStreamer<LLSDNotationFormatter>(context)
						<< llendl;
					keep_looping = false;
				}
				break;
			case '%':
				{
					std::string query_str = LLURI::mapToQueryString(value);
					service_url.replace(
						deepest_node,
						deepest_node_end + 1,
						query_str);
				}
				break;
			default:
				llinfos << "Unknown directive: " << *(deepest_node + 1)
					<< llendl;
				keep_looping = false;
				break;
			}
		}
	}
	if (service_url.find('{') != std::string::npos)
	{
		llwarns << "Constructed a likely bogus service URL: " << service_url
			<< llendl;
	}
	return service_url;
}
Exemple #2
0
///////////////////////////////////////////
//  subtree_height(bp *b,i64 s)
//    returns the height of the subtree of s
//            0 if s is a leaf
///////////////////////////////////////////
i64 subtree_height(bp *b,i64 s)
{
    i64 t;
    t = deepest_node(b,s);
    return depth(b,t) - depth(b,s);
}