Mostly, this cleans up Lilypond_version
We no longer convert to int because it is weird, but we still want
version comparisons. Conversion to bool for checking validity seems
nice in addition.
And bombing out because of invalid data to String_convert::dec2int
seemed definitely non-nice. This version requires specifying at
least major and minor version number explicitly separated by dots.
It accepts a trailing dot, too. A trailing extra_patch_string after
major.minor.patchlevel. is also accepted but not interpreted.
#define LILYPOND_VERSION_HH
#include "std-string.hh"
#define LILYPOND_VERSION_HH
#include "std-string.hh"
struct Lilypond_version
{
struct Lilypond_version
{
Lilypond_version (const string &str);
string to_string () const;
Lilypond_version (const string &str);
string to_string () const;
+ operator bool () const;
+ static int compare (const Lilypond_version &, const Lilypond_version &);
string extra_patch_string_;
};
string extra_patch_string_;
};
+INSTANTIATE_COMPARE (const Lilypond_version &, Lilypond_version::compare);
+
extern Lilypond_version oldest_version;
#endif // LILYPOND_VERSION_HH
extern Lilypond_version oldest_version;
#endif // LILYPOND_VERSION_HH
{
Lilypond_version current ( MAJOR_VERSION "." MINOR_VERSION "." PATCH_LEVEL );
Lilypond_version ver (s);
{
Lilypond_version current ( MAJOR_VERSION "." MINOR_VERSION "." PATCH_LEVEL );
Lilypond_version ver (s);
- if (int (ver) < oldest_version)
+ if (!ver)
+ {
+ non_fatal_error (_f ("Invalid version string \"%s\"", s));
+ return false;
+ }
+ if (ver < oldest_version)
{
non_fatal_error (_f ("file too old: %s (oldest supported: %s)", ver.to_string (), oldest_version.to_string ()));
non_fatal_error (_ ("consider updating the input with the convert-ly script"));
{
non_fatal_error (_f ("file too old: %s (oldest supported: %s)", ver.to_string (), oldest_version.to_string ()));
non_fatal_error (_ ("consider updating the input with the convert-ly script"));
Lilypond_version::Lilypond_version (const string &str)
{
Lilypond_version::Lilypond_version (const string &str)
{
minor_ = 0;
patch_ = 0;
vector<string> version;
minor_ = 0;
patch_ = 0;
vector<string> version;
+ const char *digits = "0123456789";
version = string_split (str, '.');
version = string_split (str, '.');
- if (version.size () > 0 && isdigit (version[0][0]))
- major_ = String_convert::dec2int (version[0]);
- if (version.size () > 1 && isdigit (version[1][0]))
- minor_ = String_convert::dec2int (version[1]);
-
- patch_ = 0;
- if (version.size () >= 3
- && isdigit (version[2][0]))
- patch_ = String_convert::dec2int (version[2]);
-
- if (version.size () >= 4)
+ switch (version.size ()) {
+ case 4:
extra_patch_string_ = version[3];
extra_patch_string_ = version[3];
+ if (version[2].empty ())
+ return;
+ case 3:
+ if (version[2].find_first_not_of (digits) != string::npos
+ || version[1].empty ())
+ return;
+ patch_ = String_convert::dec2int (version[2]);
+ case 2:
+ if (version[1].find_first_not_of (digits) != string::npos
+ || version[1].empty () || version[0].empty ())
+ return;
+ minor_ = String_convert::dec2int (version[1]);
+ if (version[0].find_first_not_of (digits) != string::npos)
+ return;
+ major_ = String_convert::dec2int (version[0]);
+ }
}
string
Lilypond_version::to_string () const
{
}
string
Lilypond_version::to_string () const
{
+ if (major_ < 0)
+ return "invalid";
return ::to_string (major_)
+ "." + ::to_string (minor_)
+ "." + ::to_string (patch_);
}
return ::to_string (major_)
+ "." + ::to_string (minor_)
+ "." + ::to_string (patch_);
}
-Lilypond_version::operator int () const
+Lilypond_version::operator bool () const
- // ugh
- return 100000 * major_ + 1000 * minor_ + patch_;
+int
+Lilypond_version::compare (const Lilypond_version &a, const Lilypond_version &b)
+{
+ if (!a || !b)
+ return 0;
+ if (a.major_ != b.major_)
+ return a.major_ > b.major_ ? 1 : -1;
+ if (a.minor_ != b.minor_)
+ return a.minor_ > b.minor_ ? 1 : -1;
+ if (a.patch_ != b.patch_)
+ return a.patch_ > b.patch_ ? 1 : -1;
+ return 0;
+}