This function is similar to simgear::strutils::to_int(), except it is:
- generic: the return type, selected with the first template
parameter, can be an arbitrary integral type. This type also defines
the set of accepted input strings ("values").
- stricter regarding the input: it must be non-empty and contain only
valid digits for the specified base (second template parameter). If
the input doesn't conform to these constraints or is too large to
fit into the specified type, an exception with a suitable error
message is raised.
- faster (12 to 17 times as fast as simgear::strutils::to_int() on my
system, depending on compilation flags): this is probably a
consequence of not using std::stringstream to do the conversion.
The function template is only instantiated for <int, 10> and
<unsigned int, 10> in order to be sure not to waste memory (see comments
in strutils.cxx). If you need it for other combinations of type and
base, just enable them by adjusting the corresponding '#if 0 / #endif'
pairs in strutils.cxx and strutils_test.cxx.
The existance of a dns entry with a protocol defined caused the
naptr callback being terminated early and the request never completed.
This patch also adds a unit test for this particular case.
test_dns now also accepts up to two command line parameters:
first: dns DN to query for NAPTR records (default: terrasync.flightgear.org)
second: service to query (default: empty)
Since the virtuality of a method is inherited by derived classes, this
makes the virtual status of such methods clearly visible in the
declarations of derived classes.
The Windows and Mac builders on jenkins complain that '\U12345678' is
an invalid universal character; let's try with '\U000000E9' instead,
which should be LATIN SMALL LETTER E WITH ACUTE.
Also replace '\uab42' with '\u00e0' to remove a warning on the Windows
builder, due to the fact that '\uab42' cannot be represented in the
current code page (1252). This doesn't mean '\uab42' was incorrect,
though; I'm only changing this to make the warning disappear.
This function complements the existing strutils::unescape(). It
backslash-escapes a string for C/C++ string literal syntax.
For every std::string s, the following holds:
unescape(escape(s)) == s
(not the other way around, because there are many ways to escape a given
character in a string literal)
An octal escape sequence in a string literal can't have more than 3
octal digits after the backslash. The previous code was using up to 4
digits per octal escape sequence.
Such an argument is /a priori/ perfectly valid, and not an option.
Typical use in a command line:
-o -
equivalent to:
-o-
The former way wasn't accepted before this commit; now it is (also
'--output -', equivalent to '--output=-').
If the last option is followed by an argument consisting of a single
'-', this argument marks the end of options and is the first non-option
argument (contrary to '--' which, given its special status, would mark
the end of options but would *not* count as a non-option argument).
This commit also adds an std::string length check in
ArgumentParser::parseArgs() that was missing before using operator[]()
(important difference between operator[]() for std::string and std::map
or std::unordered_map!).
Previously, SGPath::pathListSep was a char in static memory, that could
be followed by anything (often '\0', as it seems... but not always).
This is (was) dangerous, because it is then tempting to take its address
and pass it to functions expecting a char * corresponding to a
null-terminated string (C-style).
SGPath::pathListSep is now a static array of two const chars: the path
list separator followed by a '\0'. This implies that
&SGPath::pathListSep can now be reliably interpreted as a C-style string
of length 1 (not counting the null terminator), containing only the path
list separator.
See simgear/misc/argparse.hxx for API and documentation
(simgear/misc/argparse_test.cxx also has examples, although argparse.hxx
features a very simple one at the top).
These classes were also presented in
<https://sourceforge.net/p/flightgear/mailman/message/35785019/>.
The popup/no popup logic in SG_LOG() could be wrong before this commit,
because of missing parentheses around uses of the second macro argument.
For instance, this:
SG_LOG(SG_NAVCACHE, t == 0 ? SG_WARN : SG_ALERT, "Message");
could cause a popup window to be displayed even though neither SG_WARN
nor SG_ALERT should do that in the current state of the logging system.
Thanks to Szymon Acedański for finding this.
Add an alternate constructor to each of the following classes:
ZlibAbstractIStreambuf, ZlibCompressorIStreambuf,
ZlibDecompressorIStreambuf, ZlibCompressorIStream and
ZlibDecompressorIStream. These new constructors are passed the source
std::istream wrapped inside an std::unique_ptr instead of by reference,
and store the unique_ptr object as an instance member. This ensures that
the source std::istream object is available as long as the
ZlibDecompressorIStreambuf, etc. instance is alive (which is necessary
for its getInputData() method) without any additional work for callers,
and that it is automatically destroyed afterwards.
This is particularly useful when writing functions that create and
return an object 'zobj' whose type is a subclass of
ZlibAbstractIStreambuf, when the source std::istream is only of interest
for its role of feeding data to 'zobj'. For instance:
std::unique_ptr<simgear::ZlibCompressorIStream>
myZlibCompressorIStreamProducer(std::string str)
{
std::unique_ptr<std::istringstream> iss(new std::istringstream(str));
return std::unique_ptr<simgear::ZlibCompressorIStream>(
new simgear::ZlibCompressorIStream(std::move(iss))); // new ctor here
}
Callers of such a function get access to a new ZlibCompressorIStream
instance fed by an std::istringstream object ('iss'), but they don't
even have to know this detail, nor to take any measure to ensure that
'iss' lives at least as long as the ZlibCompressorIStream object. The
std::unique_ptr<std::istream> pointing to 'iss' and stored as a member
of the ZlibCompressorIStream object by its constructor automatically
takes care of this lifetime problem.
New automated test for ZlibDecompressorIStreambuf::xsgetn(). xsgetn() is
called by sgetn() from the base class std::streambuf. In our case,
xsgetn() is actually defined in the base class ZlibAbstractIStreambuf
(subclass of std::streambuf), therefore this new test also applies to
ZlibCompressorIStreambuf and the two other related classes,
ZlibCompressorIStream and ZlibDecompressorIStream.
This test asks [x]sgetn() the largest possible amount of chars every
time it is called, i.e., the largest value that can be represented by
std::streamsize. This exercises the code in interesting ways due to the
various types involved (zlib's uInt, std::size_t and std::streamsize,
which have various sizes depending on the platform).