summaryrefslogtreecommitdiff
path: root/indra/newview/llsyntaxid.cpp
diff options
context:
space:
mode:
authorRider Linden <rider@lindenlab.com>2026-04-28 10:23:44 -0700
committerRider Linden <rider@lindenlab.com>2026-04-28 10:23:44 -0700
commit364ff6e6d45087653a302b96ccd8c9e02db2b9d1 (patch)
tree3da2f933413d2e7cf640c674b28287918b0753a4 /indra/newview/llsyntaxid.cpp
parent65b9b2cb5cde2c344da51a7b677c1b99591d8ad3 (diff)
Refactor the LLSyntaxIDLSL/Lua into single LLSyntaxDefCache, use new cap when available to retrieve all language definition files and cache them locally.
Retrieve the default definition files from the LSL definitions precompiled library.
Diffstat (limited to 'indra/newview/llsyntaxid.cpp')
-rw-r--r--indra/newview/llsyntaxid.cpp515
1 files changed, 329 insertions, 186 deletions
diff --git a/indra/newview/llsyntaxid.cpp b/indra/newview/llsyntaxid.cpp
index 16274f59bc..3d0a9d80b4 100644
--- a/indra/newview/llsyntaxid.cpp
+++ b/indra/newview/llsyntaxid.cpp
@@ -38,37 +38,53 @@
//-----------------------------------------------------------------------------
// LLSyntaxIdLSL
//-----------------------------------------------------------------------------
-const std::string SYNTAX_ID_CAPABILITY_NAME = "LSLSyntax";
-const std::string SYNTAX_ID_SIMULATOR_FEATURE = "LSLSyntaxId";
-const std::string FILENAME_DEFAULT_LSL = "keywords_lsl_default.xml";
-const std::string FILENAME_DEFAULT_LUA = "keywords_lua_default.xml";
+namespace
+{
+ const std::string SYNTAX_ID_CAPABILITY_NAME = "LSLSyntax";
+ const std::string SYNTAX_DEF_CAPABILITY_NAME = "ScriptDefinitions";
+ const std::string SYNTAX_ID_SIMULATOR_FEATURE = "LSLSyntaxId";
+ const std::string FILENAME_INTERNAL_LSL = "lsl_keywords.xml";
+ const std::string FILENAME_INTERNAL_LUA = "slua_keywords.xml";
-/**
- * @brief LLSyntaxIdLSL constructor
- */
-LLSyntaxIdLSL::LLSyntaxIdLSL()
-: mKeywordsXml(LLSD())
-, mCapabilityURL(std::string())
-, mFilePath(LL_PATH_APP_SETTINGS)
-, mSyntaxId(LLUUID())
-, mInitialized(false)
+ constexpr U32 LLSD_SYNTAX_LSL_VERSION_EXPECTED = 2;
+ const std::string LLSD_SYNTAX_LSL_VERSION_KEY("llsd-lsl-syntax-version");
+
+ const std::unordered_set<std::string> MEMCACHED_LLSD = {
+ FILENAME_INTERNAL_LSL,
+ FILENAME_INTERNAL_LUA
+ };
+} // namespace
+
+//========================================================================
+void LLSyntaxDefCache::initSingleton()
{
- loadDefaultKeywordsIntoLLSD();
- mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLSyntaxIdLSL::handleRegionChanged, this));
+ buildDefaultCache();
+ loadKeywordsIntoLLSD();
+ mRegionChangedCallback = gAgent.addRegionChangedCallback(boost::bind(&LLSyntaxDefCache::handleRegionChanged, this));
handleRegionChanged(); // Kick off an initial caps query and fetch
}
-void LLSyntaxIdLSL::buildFullFileSpec()
+void LLSyntaxDefCache::cleanupSingleton()
{
- ELLPath path = mSyntaxId.isNull() ? LL_PATH_APP_SETTINGS : LL_PATH_CACHE;
- const std::string filename = mSyntaxId.isNull() ? FILENAME_DEFAULT_LSL : "keywords_lsl_" + mSyntaxId.asString() + ".llsd.xml";
- mFullFileSpec = gDirUtilp->getExpandedFilename(path, filename);
+ gAgent.removeRegionChangedCallback(mRegionChangedCallback);
+ mLSLKeywords = LLSD();
+ mLuaKeywords = LLSD();
+ mCapabilityURL = std::string();
+ mSyntaxId = LLUUID();
+ mFileCachePaths.clear();
}
-//-----------------------------------------------------------------------------
-// syntaxIdChange()
-//-----------------------------------------------------------------------------
-bool LLSyntaxIdLSL::syntaxIdChanged()
+boost::signals2::connection LLSyntaxDefCache::addSyntaxIDCallback(const syntax_id_changed_signal_t::slot_type& cb)
+{
+ return mSyntaxIDChangedSignal.connect(cb);
+}
+
+//========================================================================
+// checkSyntaxId()
+// Checks the current region for the LSLSyntaxId feature and capability, and
+// if found checks the syntax ID against the one we have. If they differ,
+// updates the syntax ID and returns true. Otherwise returns false.
+bool LLSyntaxDefCache::updateSyntaxId()
{
LLViewerRegion* region = gAgent.getRegion();
@@ -83,51 +99,97 @@ bool LLSyntaxIdLSL::syntaxIdChanged()
{
// get and check the hash
LLUUID new_syntax_id = sim_features[SYNTAX_ID_SIMULATOR_FEATURE].asUUID();
- mCapabilityURL = region->getCapability(SYNTAX_ID_CAPABILITY_NAME);
+
+ // *Note* the syntax ID may not have changed, but the region almost certainly has.
+ // update the cap URL
+ mCapabilityURL = region->getCapability(SYNTAX_DEF_CAPABILITY_NAME);
+ mUseDefsCap = !mCapabilityURL.empty();
+ if (!mUseDefsCap)
+ {
+ mCapabilityURL = region->getCapability(SYNTAX_ID_CAPABILITY_NAME);
+ }
LL_DEBUGS("SyntaxLSL") << SYNTAX_ID_SIMULATOR_FEATURE << " capability URL: " << mCapabilityURL << LL_ENDL;
+
if (new_syntax_id != mSyntaxId)
{
LL_DEBUGS("SyntaxLSL") << "New SyntaxID '" << new_syntax_id << "' found." << LL_ENDL;
mSyntaxId = new_syntax_id;
return true;
}
- else
- LL_DEBUGS("SyntaxLSL") << "SyntaxID matches what we have." << LL_ENDL;
+
+ LL_DEBUGS("SyntaxLSL") << "SyntaxID has not changed. Still " << mSyntaxId << LL_ENDL;
}
}
else
{
- region->setCapabilitiesReceivedCallback(boost::bind(&LLSyntaxIdLSL::handleCapsReceived, this, _1));
+ region->setCapabilitiesReceivedCallback(boost::bind(&LLSyntaxDefCache::handleCapsReceived, this, _1));
LL_DEBUGS("SyntaxLSL") << "Region has not received capabilities. Waiting for caps..." << LL_ENDL;
}
}
return false;
}
+void LLSyntaxDefCache::handleRegionChanged()
+{
+ if (updateSyntaxId())
+ {
+ if (!checkCacheAndLoad(mSyntaxId))
+ {
+ fetchKeywords();
+ }
+ }
+}
+
+void LLSyntaxDefCache::handleCapsReceived(const LLUUID& region_uuid)
+{
+ LLViewerRegion* current_region = gAgent.getRegion();
+
+ if (region_uuid.notNull() && current_region->getRegionID() == region_uuid)
+ {
+ updateSyntaxId();
+ if (!checkCacheAndLoad(mSyntaxId))
+ {
+ fetchKeywords();
+ }
+ }
+}
+
//-----------------------------------------------------------------------------
-// fetchKeywordsFile
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::fetchKeywordsFile(const std::string& filespec)
+// fetchKeywords
+// Initiates a fetch of the current language definitions from the region caps.
+void LLSyntaxDefCache::fetchKeywords()
{
- LLCoros::instance().launch("LLSyntaxIdLSL::fetchKeywordsFileCoro",
- boost::bind(&LLSyntaxIdLSL::fetchKeywordsFileCoro, this, mCapabilityURL, filespec));
- LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId capability URL is: " << mCapabilityURL << ". Filename to use is: '" << filespec << "'." << LL_ENDL;
+ if (mCapabilityURL.empty())
+ {
+ LL_WARNS("SyntaxLSL") << "No capability URL for fetching syntax definitions." << LL_ENDL;
+ return;
+ }
+ if (mUseDefsCap)
+ {
+ LLCoros::instance().launch("LLSyntaxIdLSL::fetchKeywordsDefsCoro",
+ boost::bind(&LLSyntaxDefCache::fetchKeywordsDefsCoro, this, mCapabilityURL, mSyntaxId));
+ }
+ else
+ {
+ LLCoros::instance().launch("LLSyntaxIdLSL::fetchKeywordsFileCoro",
+ boost::bind(&LLSyntaxDefCache::fetchKeywordsFileCoro, this, mCapabilityURL, mSyntaxId));
+ }
}
//-----------------------------------------------------------------------------
// fetchKeywordsFileCoro
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
+// This uses the legacy languge cap which only sends the LSL keywords file.
+void LLSyntaxDefCache::fetchKeywordsFileCoro(std::string url, LLUUID syntax_id)
{
LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t
httpAdapter = std::make_shared<LLCoreHttpUtil::HttpCoroutineAdapter>("fetchKeywordsFileCoro", httpPolicy);
LLCore::HttpRequest::ptr_t httpRequest = std::make_shared<LLCore::HttpRequest>();
- std::pair<std::set<std::string>::iterator, bool> insrt = mInflightFetches.insert(fileSpec);
+ auto insrt = mInflightFetches.insert(syntax_id);
if (!insrt.second)
{
- LL_WARNS("SyntaxLSL") << "Already downloading keyword file called \"" << fileSpec << "\"." << LL_ENDL;
+ LL_WARNS("SyntaxLSL") << "Already downloading keyword file for syntax ID \"" << syntax_id << "\"." << LL_ENDL;
return;
}
@@ -136,11 +198,11 @@ void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
- mInflightFetches.erase(fileSpec);
+ mInflightFetches.erase(syntax_id);
if (!status)
{
- LL_WARNS("SyntaxLSL") << "Failed to fetch syntax file \"" << fileSpec << "\"" << LL_ENDL;
+ LL_WARNS("SyntaxLSL") << "Failed to fetch syntax file for syntax ID \"" << syntax_id << "\"" << LL_ENDL;
return;
}
@@ -148,13 +210,38 @@ void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
if (isSupportedVersion(result))
{
- // Shuttle this task to the main coro/worker.
- // loadKeywordsIntoLLSD will attempt to get a mutex which is not coro aware.
- LLAppViewer::instance()->postToMainCoro([this, result, fileSpec]()
+ std::string path = buildCacheDirectoryName(syntax_id);
+
+ if (!LLFile::exists(path))
+ {
+ LL_DEBUGS("SyntaxLSL") << "Cache directory '" << path << "' does not exist. Attempting to create." << LL_ENDL;
+ if (LLFile::mkdir(path))
{
- setKeywordsXml(result);
- cacheFile(fileSpec, result);
- loadKeywordsIntoLLSD();
+ LL_WARNS("SyntaxLSL") << "Failed to create cache directory '" << path << "'. Cannot cache syntax defs file." << LL_ENDL;
+ return;
+ }
+ }
+
+ // Note that after this call the file cache will have all well known files pointing
+ // to the default versions, so below, where we get the path to the lua keywords
+ // well be loading the default version.
+ buildDefaultCache();
+
+ // The LSL keywords we just received
+ std::string full_path = gDirUtilp->add(path, FILENAME_INTERNAL_LSL);
+ if (writeCacheFile(full_path, result))
+ {
+ mFileCachePaths.addNamePath(FILENAME_INTERNAL_LSL, full_path);
+ }
+ // We need to manually load the Lua keywords
+ full_path = mFileCachePaths.getPath(FILENAME_INTERNAL_LUA);
+ LLSD lua_defs = loadDeserializedCacheFile(full_path);
+
+ setKeywords(result, lua_defs);
+
+ // Shuttle this task to the main coro/worker.
+ LLAppViewer::instance()->postToMainCoro([this]() {
+ mSyntaxIDChangedSignal();
});
}
else
@@ -164,73 +251,196 @@ void LLSyntaxIdLSL::fetchKeywordsFileCoro(std::string url, std::string fileSpec)
}
-//-----------------------------------------------------------------------------
-// cacheFile
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::cacheFile(const std::string &fileSpec, const LLSD& content_ref)
+void LLSyntaxDefCache::fetchKeywordsDefsCoro(std::string url, LLUUID syntax_id)
{
- std::stringstream str;
- LLSDSerialize::toXML(content_ref, str);
- const std::string xml = str.str();
+ LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID);
+ LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t httpAdapter =
+ std::make_shared<LLCoreHttpUtil::HttpCoroutineAdapter>("fetchKeywordsDefsCoro", httpPolicy);
+ LLCore::HttpRequest::ptr_t httpRequest = std::make_shared<LLCore::HttpRequest>();
- // save the str to disk, usually to the cache.
- llofstream file(fileSpec.c_str(), std::ios_base::out);
- file.write(xml.c_str(), str.str().size());
- file.close();
+ static std::set<LLUUID> inflightDefsFetches;
+ auto insrt = inflightDefsFetches.insert(syntax_id);
+ //auto insrt = mInflightFetches.insert(syntax_id);
+ if (!insrt.second)
+ {
+ LL_WARNS("SyntaxLSL") << "Already downloading keyword defs for \"" << syntax_id << "\"." << LL_ENDL;
+ return;
+ }
- LL_DEBUGS("SyntaxLSL") << "Syntax file received, saving as: '" << fileSpec << "'" << LL_ENDL;
-}
+ LLSD result = httpAdapter->getAndSuspend(httpRequest, url);
-//-----------------------------------------------------------------------------
-// initialize
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::initialize()
-{
- if(mInitialized) return;
- if (mSyntaxId.isNull())
+ LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS];
+ LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults);
+
+ inflightDefsFetches.erase(syntax_id);
+
+ if (!status)
{
- loadDefaultKeywordsIntoLLSD();
+ LL_WARNS("SyntaxLSL") << "Failed to fetch syntax file \"" << syntax_id << "\"" << LL_ENDL;
+ result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+ return;
}
- else if (!mCapabilityURL.empty())
+
+ // Now we need to walk through the returned LLSD. It consists of a map keyed on the file name containing a binary
+ // blob of the actual file contents.
+ LLSD files = result["files"];
+ LLSD memcached_keywords;
+ if (files.isMap())
{
- LL_DEBUGS("SyntaxLSL") << "LSL version has changed, getting appropriate file." << LL_ENDL;
+ std::string path = buildCacheDirectoryName(syntax_id);
- // Need a full spec regardless of file source, so build it now.
- buildFullFileSpec();
- if (mSyntaxId.notNull())
+ if (!LLFile::exists(path))
{
- if (!gDirUtilp->fileExists(mFullFileSpec))
- { // Does not exist, so fetch it from the capability
- LL_DEBUGS("SyntaxLSL") << "LSL syntax not cached, attempting download." << LL_ENDL;
- fetchKeywordsFile(mFullFileSpec);
- }
- else
+ LL_DEBUGS("SyntaxLSL") << "Cache directory '" << path << "' does not exist. Attempting to create." << LL_ENDL;
+ if (LLFile::mkdir(path))
{
- LL_DEBUGS("SyntaxLSL") << "Found cached Syntax file: " << mFullFileSpec << " Loading keywords." << LL_ENDL;
- loadKeywordsIntoLLSD();
+ LL_WARNS("SyntaxLSL") << "Failed to create cache directory '" << path << "'. Cannot cache syntax defs file." << LL_ENDL;
+ return;
}
}
- else
+
+ buildDefaultCache();
+
+ for (const auto &[filename, contents] : llsd::inMap(files))
{
- LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId is null. Loading default values" << LL_ENDL;
- loadDefaultKeywordsIntoLLSD();
+ std::string full_path = gDirUtilp->add(path, filename);
+
+ if (MEMCACHED_LLSD.find(filename) != MEMCACHED_LLSD.end())
+ { // Maintain some keyword LLSDs internally, LSL and Lua
+ memcached_keywords[filename] = contents;
+ }
+
+ if (writeCacheFile(full_path, contents))
+ {
+ mFileCachePaths.addNamePath(filename, full_path);
+ }
}
}
else
{
- LL_DEBUGS("SyntaxLSL") << "LSLSyntaxId capability URL is empty." << LL_ENDL;
- loadDefaultKeywordsIntoLLSD();
+ LL_WARNS("SyntaxLSL") << "Malformed syntax defs response, missing 'files' map." << LL_ENDL;
+ }
+
+ result.erase(LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS);
+
+ setKeywords(memcached_keywords["lsl_keywords.xml"], memcached_keywords["lua_keywords.xml"]);
+ LLAppViewer::instance()->postToMainCoro(
+ [this]()
+ {
+ mSyntaxIDChangedSignal();
+ });
+}
+
+//-----------------------------------------------------------------------------
+// buildCache
+// Constructs the cache file paths for the given syntax ID. If the syntax ID is null,
+// constructs the default cache file paths.
+void LLSyntaxDefCache::buildCachePaths(const LLUUID &syntax_id)
+{
+ if (syntax_id.notNull())
+ { // Initialize the cache files to point to the default files
+ buildCachePaths(LLUUID::null);
+ }
+ else
+ {
+ mFileCachePaths.clear();
+ }
+
+ std::string cache_dir = buildCacheDirectoryName(syntax_id);
+ if (!LLFile::exists(cache_dir))
+ {
+ LL_DEBUGS("SyntaxLSL") << "Cache directory '" << cache_dir << "' does not exist." << LL_ENDL;
+ return;
+ }
+
+ auto files = gDirUtilp->getFilesInDir(cache_dir);
+ for (const auto &file : files)
+ {
+ mFileCachePaths.addNamePath(file, gDirUtilp->add(cache_dir, file));
+ }
+}
+
+bool LLSyntaxDefCache::writeCacheFile(const std::string &fileSpec, const LLSD& content_ref)
+{
+ bool binary(content_ref.isBinary());
+ std::ofstream file(fileSpec.c_str(), (binary)? std::ios_base::binary : 0);
+
+ if (!file.is_open())
+ {
+ LL_WARNS("SyntaxLSL") << "Failed to open file for writing: '" << fileSpec << "'" << LL_ENDL;
+ return false;
+ }
+
+ if (binary)
+ {
+ LL_DEBUGS("SyntaxLSL") << "Caching raw content to '" << fileSpec << "'" << LL_ENDL;
+ file.write((const char*)content_ref.asBinary().data(), content_ref.asBinary().size());
+ }
+ else
+ {
+ LL_DEBUGS("SyntaxLSL") << "Caching XML content to '" << fileSpec << "'" << LL_ENDL;
+ LLSDSerialize::serialize(content_ref, file, LLSDSerialize::LLSD_XML, LLSDFormatter::OPTIONS_PRETTY);
+ }
+ file.close();
+
+ if (!file.good())
+ {
+ LL_WARNS("SyntaxLSL") << "Failed to write content to file: '" << fileSpec << "'" << LL_ENDL;
+ return false;
}
- mInitialized = true;
+ return true;
}
//-----------------------------------------------------------------------------
+// checkCacheAndLoad
+// Tests the local cache for the given syntax ID. If found it loads the keywords
+// from the cache into LLSD and returns true. Otherwise returns false.
+bool LLSyntaxDefCache::checkCacheAndLoad(const LLUUID& syntax_id)
+{
+ if (checkLocalCache(syntax_id))
+ {
+ buildCachePaths(syntax_id);
+ loadKeywordsIntoLLSD();
+ return true;
+ }
+ return false;
+}
+
+std::string LLSyntaxDefCache::buildCacheDirectoryName(const LLUUID& syntax_id)
+{
+ if (syntax_id.isNull())
+ {
+ LL_DEBUGS("SyntaxLSL") << "No SyntaxID, using app settings directory." << LL_ENDL;
+ return gDirUtilp->getExpandedFilename(LL_PATH_CACHE, "syntax_default");
+ }
+ else
+ {
+ LL_DEBUGS("SyntaxLSL") << "Using cache directory for SyntaxID '" << syntax_id << "'." << LL_ENDL;
+ std::string cache_dir_name = "syntax_" + syntax_id.asString();
+
+ return gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, cache_dir_name);
+ }
+}
+
+bool LLSyntaxDefCache::checkLocalCache(const LLUUID& syntax_id) const
+{
+ if (syntax_id.isNull())
+ { // Cache check will always fail if we don't have a valid SyntaxID, so skip it in that case.
+ LL_DEBUGS("SyntaxLSL") << "No SyntaxID, skipping local cache check." << LL_ENDL;
+ return false;
+ }
+
+ // Check for the existence of the cache directory for this syntax ID. If it doesn't exist, then we don't have a cached file.
+ std::string cache_dir = buildCacheDirectoryName(syntax_id);
+ return gDirUtilp->fileExists(cache_dir);
+}
+
+
+//-----------------------------------------------------------------------------
// isSupportedVersion
//-----------------------------------------------------------------------------
-const U32 LLSD_SYNTAX_LSL_VERSION_EXPECTED = 2;
-const std::string LLSD_SYNTAX_LSL_VERSION_KEY("llsd-lsl-syntax-version");
-bool LLSyntaxIdLSL::isSupportedVersion(const LLSD& content)
+bool LLSyntaxDefCache::isSupportedVersion(const LLSD& content)
{
bool is_valid = false;
/*
@@ -256,128 +466,61 @@ bool LLSyntaxIdLSL::isSupportedVersion(const LLSD& content)
}
//-----------------------------------------------------------------------------
-// loadDefaultKeywordsIntoLLSD()
-//-----------------------------------------------------------------------------
-void LLSyntaxIdLSL::loadDefaultKeywordsIntoLLSD()
-{
- mSyntaxId.setNull();
- buildFullFileSpec();
- loadKeywordsIntoLLSD();
-}
-
-//-----------------------------------------------------------------------------
-// loadKeywordsFileIntoLLSD
+// loadKeywordsIntoLLSD
//-----------------------------------------------------------------------------
/**
* @brief Load xml serialized LLSD
- * @desc Opens the specified filespec and attempts to deserializes the
- * contained data to the specified LLSD object. indicate success/failure with
- * sLoaded/sLoadFailed members.
+ * @desc Open the internal lsl keywords files and deserialize them into the correct
+ * members.
*/
-void LLSyntaxIdLSL::loadKeywordsIntoLLSD()
+void LLSyntaxDefCache::loadKeywordsIntoLLSD()
{
- LLSD content;
- llifstream file;
- file.open(mFullFileSpec.c_str());
- if (file.is_open())
+ for (auto& filename : MEMCACHED_LLSD)
{
- if (LLSDSerialize::fromXML(content, file) != LLSDParser::PARSE_FAILURE)
+ // Note, in the case of the legacy language cap (it only delivers the LSL keywords file)
+ // The mFileCachePaths will have been initialized in such a way that the Lua keywords
+ // point to the default file.
+ std::string full_path = mFileCachePaths.getPath(filename);
+ if (!full_path.empty())
{
- if (isSupportedVersion(content))
+ LLSD content = loadDeserializedCacheFile(full_path);
+ if (!content.isUndefined() && isSupportedVersion(content))
{
- LL_DEBUGS("SyntaxLSL") << "Deserialized: " << mFullFileSpec << LL_ENDL;
+ LL_DEBUGS("SyntaxLSL") << "Deserialized cached file: " << full_path << LL_ENDL;
+ if (filename == FILENAME_INTERNAL_LSL)
+ {
+ mLSLKeywords = content;
+ }
+ else if (filename == FILENAME_INTERNAL_LUA)
+ {
+ mLuaKeywords = content;
+ }
}
else
{
- LL_WARNS("SyntaxLSL") << "Unknown or unsupported version of syntax file." << LL_ENDL;
+ LL_WARNS("SyntaxLSL") << "Unknown or unsupported version of syntax file " << full_path << "." << LL_ENDL;
}
}
}
- else
- {
- LL_WARNS("SyntaxLSL") << "Failed to open: " << mFullFileSpec << LL_ENDL;
- }
- mKeywordsXml = content;
- mSyntaxIDChangedSignal();
-}
-
-bool LLSyntaxIdLSL::keywordFetchInProgress()
-{
- return !mInflightFetches.empty();
-}
-
-void LLSyntaxIdLSL::handleRegionChanged()
-{
- if (syntaxIdChanged())
- {
- buildFullFileSpec();
- fetchKeywordsFile(mFullFileSpec);
- mInitialized = false;
- }
-}
-
-void LLSyntaxIdLSL::handleCapsReceived(const LLUUID& region_uuid)
-{
- LLViewerRegion* current_region = gAgent.getRegion();
-
- if (region_uuid.notNull()
- && current_region->getRegionID() == region_uuid)
- {
- syntaxIdChanged();
- }
-}
-
-boost::signals2::connection LLSyntaxIdLSL::addSyntaxIDCallback(const syntax_id_changed_signal_t::slot_type& cb)
-{
- return mSyntaxIDChangedSignal.connect(cb);
-}
-
-
-
-//-----------------------------------------------------------------------------
-// LLSyntaxLua
-//-----------------------------------------------------------------------------
-LLSyntaxLua::LLSyntaxLua()
- : mKeywordsXml(LLSD())
- , mInitialized(false)
-{
-}
-
-void LLSyntaxLua::initialize()
-{
- if (mInitialized) return;
- loadDefaultKeywordsIntoLLSD();
- loadLuaTypesIntoLLSD();
- mInitialized = true;
+ mSyntaxIDChangedSignal();
}
-void LLSyntaxLua::loadDefaultKeywordsIntoLLSD()
+LLSD LLSyntaxDefCache::loadDeserializedCacheFile(const std::string& file_path)
{
- std::string fullFileSpec = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, FILENAME_DEFAULT_LUA);
- llifstream file(fullFileSpec.c_str());
-
+ std::ifstream file(file_path.c_str());
if (file.good())
{
LLSD content;
- if (LLSDSerialize::fromXML(content, file) != LLSDParser::PARSE_FAILURE)
+ if (LLSDSerialize::deserialize(content, file, -1))
{
- mKeywordsXml = content;
+ return content;
}
}
-}
-
-void LLSyntaxLua::loadLuaTypesIntoLLSD()
-{
- std::string fullFileSpec = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "types_lua_default.xml");
- llifstream file(fullFileSpec.c_str());
-
- if (file.good())
+ else
{
- LLSD content;
- if (LLSDSerialize::fromXML(content, file) != LLSDParser::PARSE_FAILURE)
- {
- mTypesXml = content;
- }
+ LL_WARNS("SyntaxLSL") << "Failed to open cached file: " << file_path << LL_ENDL;
}
+ return LLSD();
}
+