diff --git a/doc/function/exists_in_package.txt b/doc/function/exists_in_package.txt new file mode 100644 index 00000000..20f8d096 --- /dev/null +++ b/doc/function/exists_in_package.txt @@ -0,0 +1,13 @@ +Function: exists_in_package + +--Usage-- +> exists_in_package("/package/filename") + +Check if a file exists in a given package. + +--Parameters-- +! Parameter Type Description +| @input@ [[type:string]] Path of the file, starting from the data directory. + +--Examples-- +> exists_in_package("/magic-modules.mse-include/watermarks/custom_user_watermark.png") == true diff --git a/doc/function/index.txt b/doc/function/index.txt index f0bfa889..13ed7844 100644 --- a/doc/function/index.txt +++ b/doc/function/index.txt @@ -113,3 +113,4 @@ These functions are built into the program, other [[type:function]]s can be defi | [[fun:assert]] Check a condition for debugging purposes. | [[fun:warning]] Output a warning message. | [[fun:error]] Output an error message. +| [[fun:exists_in_package]] Checks if a file exists in a package. diff --git a/src/script/functions/basic.cpp b/src/script/functions/basic.cpp index ca00b002..c6b16795 100644 --- a/src/script/functions/basic.cpp +++ b/src/script/functions/basic.cpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -62,7 +63,13 @@ SCRIPT_FUNCTION(error) { queue_message(MESSAGE_ERROR, input); } return script_nil; -} +} + +SCRIPT_FUNCTION(exists_in_package) { + SCRIPT_PARAM_C(String, input); + bool result = package_manager.existsInPackage(input); + SCRIPT_RETURN(result); +} // ----------------------------------------------------------------------------- : Conversion @@ -749,6 +756,7 @@ void init_script_basic_functions(Context& ctx) { ctx.setVariable(_("trace"), script_trace); ctx.setVariable(_("warning"), script_warning); ctx.setVariable(_("error"), script_error); + ctx.setVariable(_("exists_in_package"), script_exists_in_package); // conversion ctx.setVariable(_("to_string"), script_to_string); ctx.setVariable(_("to_int"), script_to_int); diff --git a/src/util/io/package.cpp b/src/util/io/package.cpp index b2384737..78df3cd8 100644 --- a/src/util/io/package.cpp +++ b/src/util/io/package.cpp @@ -186,6 +186,35 @@ public: // ----------------------------------------------------------------------------- : Package : inside +bool Package::existsIn(const String& file) { + FileInfos::iterator it = files.find(normalize_internal_filename(file)); + if (it == files.end()) { + // does it look like a relative filename? + if (filename.find(_(".mse-")) != String::npos) { + return false; + } + } + + unique_ptr stream; + if (it != files.end() && it->second.wasWritten()) { + // written to this file, open the temp file + stream = make_unique(it->second.tempName); + } + else if (wxFileExists(filename + _("/") + file)) { + // a file in directory package + stream = make_unique(filename + _("/") + file); + } + else if (wxFileExists(filename) && it != files.end() && it->second.zipEntry) { + // a file in a zip archive + stream = make_unique(filename, it->second.zipEntry); + } + else { + // shouldn't happen, packaged changed by someone else since opening it + return false; + } + return stream && stream->IsOk(); +} + unique_ptr Package::openIn(const String& file) { if (!file.empty() && file.GetChar(0) == _('/')) { // absolute path, open file from another package diff --git a/src/util/io/package.hpp b/src/util/io/package.hpp index 6d15df9c..eee03149 100644 --- a/src/util/io/package.hpp +++ b/src/util/io/package.hpp @@ -132,10 +132,16 @@ public: // --------------------------------------------------- : Managing the inside of the package + /// Check if a file is in the package. + bool existsIn(const String& file); + inline bool existsIn(const LocalFileName& file) { + return existsIn(file.fn); + } + /// Open an input stream for a file in the package. unique_ptr openIn(const String& file); inline unique_ptr openIn(const LocalFileName& file) { - return openIn(file.fn); + return openIn(file.fn); } /// Open an output stream for a file in the package. diff --git a/src/util/io/package_manager.cpp b/src/util/io/package_manager.cpp index 2f368ad0..9eeca4f2 100644 --- a/src/util/io/package_manager.cpp +++ b/src/util/io/package_manager.cpp @@ -95,6 +95,20 @@ void PackageManager::findMatching(const String& pattern, vector& out) } } +bool PackageManager::existsInPackage(const String& name) { + if (!name.empty() && name.GetChar(0) == _('/')) { + // break name + size_t start = name.find_first_not_of(_("/\\"), 1); // allow "//package/name" from incorrect scripts + size_t pos = name.find_first_of(_("/\\"), start); + if (start < pos && pos != String::npos) { + // open package + PackagedP p = openAny(name.substr(start, pos - start)); + return p->existsIn(name.substr(pos + 1)); + } + } + throw FileNotFoundError(name, _("No package name specified, use '/package/filename'")); +} + pair,Packaged*> PackageManager::openFileFromPackage(Packaged* package, const String& name) { if (!name.empty() && name.GetChar(0) == _('/')) { // absolute name; break name diff --git a/src/util/io/package_manager.hpp b/src/util/io/package_manager.hpp index 4178d310..7e6037c4 100644 --- a/src/util/io/package_manager.hpp +++ b/src/util/io/package_manager.hpp @@ -139,7 +139,10 @@ public: /// Find all packages that match a filename pattern, store them in out /** Only reads the package headers */ void findMatching(const String& pattern, vector& out); - + + /// Check if a file exists in a package + bool existsInPackage(const String& name); + /// Open a file from a package, with a name encoded as "/package/file" /** If 'package' is set then: * - tries to open a relative file from the package if the name is "file" @@ -148,7 +151,7 @@ public: * Returns the opened file and the package it is in */ pair,Packaged*> openFileFromPackage(Packaged* package, const String& name); - + /// Get a filename to open from a package /** WARNING: this is a bit of a hack, since not all package types support names in this way. * It is needed for third party libraries (i.e. hunspell) that load stuff from files. diff --git a/tools/website/drupal/mse-drupal-modules/highlight.inc b/tools/website/drupal/mse-drupal-modules/highlight.inc index afe0b0d7..2c9f908d 100644 --- a/tools/website/drupal/mse-drupal-modules/highlight.inc +++ b/tools/website/drupal/mse-drupal-modules/highlight.inc @@ -102,6 +102,7 @@ $built_in_functions = array( // other 'trace' =>'', 'assert' =>'', + 'exists_in_package' =>'', );