The 'Big Whine' patch:

Any use of a file from another package without a declared dependency will give a warning;

Also added some more _LOCALE_123_ macros so we need less format_string calls

git-svn-id: svn://svn.code.sf.net/p/magicseteditor/code/trunk@753 0fc631ac-6414-0410-93d0-97cfa31319b6
This commit is contained in:
twanvl
2007-09-24 20:24:22 +00:00
parent efcccb79c4
commit 36a36356c5
51 changed files with 246 additions and 132 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ IndexMap<Key,Value>& DelayedIndexMaps<Key,Value>::get(const String& name, const
item->read_data.init(init_with);
} else if (!item->unread_data.empty()) { // not read, read now
item->read_data.init(init_with);
Reader reader(new_shared1<wxStringInputStream>(item->unread_data), _("delayed data for ") + name);
Reader reader(new_shared1<wxStringInputStream>(item->unread_data), nullptr, _("delayed data for ") + name);
reader.handle_greedy(item->read_data);
item->unread_data.clear();
}
+27 -3
View File
@@ -178,10 +178,15 @@ class BufferedFileInputStream : private BufferedFileInputStream_aux, public wxBu
InputStreamP Package::openIn(const String& file) {
if (!file.empty() && file.GetChar(0) == _('/')) {
// absolute path, open file from another package
return packages.openFileFromPackage(file);
Packaged* p = dynamic_cast<Packaged*>(this);
return packages.openFileFromPackage(p, file);
}
FileInfos::iterator it = files.find(toStandardName(file));
if (it == files.end()) {
// does it look like a relative filename?
if (filename.find(_(".mse-")) != String::npos) {
throw PackageError(_ERROR_2_("file not found package like", file, filename));
}
throw FileNotFoundError(file, filename);
}
InputStreamP stream;
@@ -442,6 +447,7 @@ IMPLEMENT_REFLECTION(Packaged) {
REFLECT_N("icon", icon_filename);
REFLECT_NO_SCRIPT(position_hint);
REFLECT(version);
REFLECT(compatible_version);
REFLECT_NO_SCRIPT_N("depends ons", dependencies); // hack for singular_form
}
@@ -472,7 +478,7 @@ void Packaged::open(const String& package, bool just_header) {
fully_loaded = false;
if (just_header) {
// Read just the header (the part common to all Packageds)
Reader reader(openIn(typeName()), absoluteFilename() + _("/") + typeName(), true);
Reader reader(openIn(typeName()), this, absoluteFilename() + _("/") + typeName(), true);
try {
JustAsPackageProxy proxy(this);
reader.handle_greedy(proxy);
@@ -487,7 +493,7 @@ void Packaged::open(const String& package, bool just_header) {
void Packaged::loadFully() {
if (fully_loaded) return;
fully_loaded = true;
Reader reader(openIn(typeName()), absoluteFilename() + _("/") + typeName());
Reader reader(openIn(typeName()), this, absoluteFilename() + _("/") + typeName());
try {
reader.handle_greedy(*this);
validate(reader.file_app_version);
@@ -518,6 +524,24 @@ void Packaged::validate(Version) {
}
}
void Packaged::requireDependency(Packaged* package) {
if (package == this) return; // dependency on self
String n = package->relativeFilename();
FOR_EACH(dep, dependencies) {
if (dep->package == n) {
if (package->version < dep->version) {
handle_warning(_ERROR_3_("package out of date", n, package->version.toString(), dep->version.toString()), false);
} else if (package->compatible_version > dep->version) {
handle_warning(_ERROR_4_("package too new", n, package->version.toString(), dep->version.toString(), relativeFilename()), false);
} else {
return; // ok
}
}
}
// dependency not found
handle_warning(_ERROR_4_("dependency not given", name(), package->relativeFilename(), package->relativeFilename(), package->version.toString()), false);
}
// ----------------------------------------------------------------------------- : IncludePackage
String IncludePackage::typeName() const { return _("include"); }
+11 -6
View File
@@ -117,7 +117,7 @@ class Package : public IntrusivePtrVirtualBase {
template <typename T>
void readFile(const String& file, T& obj) {
Reader reader(openIn(file), absoluteFilename() + _("/") + file);
Reader reader(openIn(file), dynamic_cast<Packaged*>(this), absoluteFilename() + _("/") + file);
try {
reader.handle_greedy(obj);
} catch (const ParseError& err) {
@@ -196,12 +196,13 @@ class Packaged : public Package {
Packaged();
virtual ~Packaged() {}
Version version; ///< Version number of this package
String short_name; ///< Short name of this package
String full_name; ///< Name of this package, for menus etc.
String icon_filename; ///< Filename of icon to use in package lists
Version version; ///< Version number of this package
Version compatible_version; ///< Earliest version number this package is compatible with
String short_name; ///< Short name of this package
String full_name; ///< Name of this package, for menus etc.
String icon_filename; ///< Filename of icon to use in package lists
vector<PackageDependencyP> dependencies; ///< Dependencies of this package
int position_hint; ///< A hint for the package list
int position_hint; ///< A hint for the package list
/// Get an input stream for the package icon, if there is any
InputStreamP openIconFile();
@@ -215,6 +216,10 @@ class Packaged : public Package {
void save();
void saveAs(const String& package, bool remove_unused = true);
/// Check if this package lists a dependency on the given package
/** This is done to force people to fill in the dependencies */
void requireDependency(Packaged* package);
protected:
/// filename of the data file, and extension of the package file
virtual String typeName() const = 0;
+18 -11
View File
@@ -101,17 +101,24 @@ void PackageManager::findMatching(const String& pattern, vector<PackagedP>& out)
}
}
InputStreamP PackageManager::openFileFromPackage(const String& name) {
// we don't want an absolute path (for security reasons)
String n;
if (!name.empty() && name.GetChar(0) == _('/')) n = name.substr(1);
else n = name;
// break
size_t pos = n.find_first_of(_("/\\"));
if (pos == String::npos) throw FileNotFoundError(n, _("No package name specified, use 'package/filename'"));
// open package and file
PackagedP p = openAny(n.substr(0, pos));
return p->openIn(n.substr(pos+1));
InputStreamP PackageManager::openFileFromPackage(Packaged*& package, const String& name) {
if (!name.empty() && name.GetChar(0) == _('/')) {
// absolute name; break name
size_t pos = name.find_first_of(_("/\\"), 1);
if (pos != String::npos) {
// open package
PackagedP p = openAny(name.substr(1, pos-1));
if (package) {
package->requireDependency(p.get());
}
package = p.get();
return p->openIn(name.substr(pos + 1));
}
} else if (package) {
// relative name
return package->openIn(name);
}
throw FileNotFoundError(name, _("No package name specified, use '/package/filename'"));
}
bool PackageManager::checkDependency(const PackageDependency& dep, bool report_errors) {
+10 -4
View File
@@ -66,12 +66,18 @@ class PackageManager {
/** Only reads the package headers */
void findMatching(const String& pattern, vector<PackagedP>& out);
/// Open a file from a package, with a name encoded as "package/file"
InputStreamP openFileFromPackage(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"
* - verifies a dependency from that package if an absolute filename is used
* this is to force people to fill in the dependencies
* Afterwards, package will be set to the package the file is opened from
*/
InputStreamP openFileFromPackage(Packaged*& package, const String& name);
/// Check if the given dependency is currently installed
bool checkDependency(const PackageDependency& dep, bool report_errors = false);
bool checkDependency(const PackageDependency& dep, bool report_errors = true);
inline String getGlobalDataDir() const { return global_data_directory; }
inline String getLocalDataDir() const { return local_data_directory; }
+5 -5
View File
@@ -14,9 +14,9 @@
// ----------------------------------------------------------------------------- : Reader
Reader::Reader(const InputStreamP& input, const String& filename, bool ignore_invalid)
Reader::Reader(const InputStreamP& input, Packaged* package, const String& filename, bool ignore_invalid)
: indent(0), expected_indent(0), state(OUTSIDE)
, filename(filename), line_number(0), previous_line_number(0)
, package(package), filename(filename), line_number(0), previous_line_number(0)
, ignore_invalid(ignore_invalid)
, input(input)
{
@@ -24,12 +24,12 @@ Reader::Reader(const InputStreamP& input, const String& filename, bool ignore_in
handleAppVersion();
}
Reader::Reader(const String& filename)
Reader::Reader(Packaged* pkg, const String& filename)
: indent(0), expected_indent(0), state(OUTSIDE)
, filename(filename), line_number(0), previous_line_number(0)
, package(pkg), filename(filename), line_number(0), previous_line_number(0)
, ignore_invalid(false)
, input(packages.openFileFromPackage(filename))
{
input = packages.openFileFromPackage(package, filename);
moveNext();
handleAppVersion();
}
+12 -4
View File
@@ -16,6 +16,7 @@ template <typename T> class Defaultable;
template <typename T> class Scriptable;
DECLARE_POINTER_TYPE(Game);
DECLARE_POINTER_TYPE(StyleSheet);
class Packaged;
// ----------------------------------------------------------------------------- : Reader
@@ -35,11 +36,13 @@ class Reader {
/// Construct a reader that reads from the given input stream
/** filename is used only for error messages
*/
Reader(const InputStreamP& input, const String& filename = wxEmptyString, bool ignore_invalid = false);
Reader(const InputStreamP& input, Packaged* package = nullptr, const String& filename = wxEmptyString, bool ignore_invalid = false);
/// Construct a reader that reads a file in a package
/** Used for "include file" keys. */
Reader(const String& filename);
/** Used for "include file" keys.
* package can be nullptr
*/
Reader(Packaged* package, const String& filename);
~Reader() { showWarnings(); }
@@ -108,6 +111,9 @@ class Reader {
/// Indicate that the last value from getValue() was not handled, allowing it to be handled again
void unhandle();
/// The package being read from
inline Packaged* getPackage() const { return package; }
// --------------------------------------------------- : Data
/// App version this file was made with
Version file_app_version;
@@ -141,6 +147,8 @@ class Reader {
/// Filename for error messages
String filename;
/// Package this file is from, if any
Packaged* package;
/// Line number of the current line for error messages
int line_number;
/// Line number of the previous_line
@@ -172,7 +180,7 @@ class Reader {
template <typename T>
void unknownKey(T& v) {
if (key == _("include file")) {
Reader reader(value);
Reader reader(package, value);
reader.handle_greedy(v);
moveNext();
} else {
+14
View File
@@ -98,12 +98,23 @@ String tr(const SymbolFont&, const String& key, const String& def);
/// A localized string for button text, with 1 argument (printf style)
#define _BUTTON_1_(s,a) format_string(_BUTTON_(s), a)
/// A localized string for window titles, with 1 argument (printf style)
#define _TITLE_1_(s,a) format_string(_TITLE_(s), a)
/// A localized string for type names in scripts, with 1 argument (printf style)
#define _TYPE_1_(s,a) format_string(_TYPE_(s), a)
/// A localized string for action names, with 1 argument (printf style)
#define _ACTION_1_(s,a) format_string(_ACTION_(s), a)
/// A localized string for error messages, with 1 argument (printf style)
#define _ERROR_1_(s,a) format_string(_ERROR_(s), a)
/// A localized string for error messages, with 2 argument (printf style)
#define _ERROR_2_(s,a,b) format_string(_ERROR_(s), a, b)
/// A localized string for error messages, with 3 argument (printf style)
#define _ERROR_3_(s,a,b,c) format_string(_ERROR_(s), a, b, c)
/// A localized string for error messages, with 4 argument (printf style)
#define _ERROR_4_(s,a,b,c,d) format_string(_ERROR_(s), a, b, c, d)
/// Format a string
/** Equivalent to sprintf / String::Format, but allows strings to be passed as arguments (gcc)
@@ -124,6 +135,9 @@ inline String format_string(const String& format, const String& a0, const String
inline String format_string(const String& format, const String& a0, const String& a1, const String& a2) {
return String::Format(format, a0.c_str(), a1.c_str(), a2.c_str());
}
inline String format_string(const String& format, const String& a0, const String& a1, const String& a2, const String& a3) {
return String::Format(format, a0.c_str(), a1.c_str(), a2.c_str(), a3.c_str());
}
// ----------------------------------------------------------------------------- : EOF
#endif