Fix flags usage and make Commander Flags capable.
- Programs should exit on Flags parse error. - Commander now accepts a string vector for interop with Flags.
This commit is contained in:
parent
1420ff343d
commit
8b63985ac9
|
@ -9,7 +9,10 @@ jobs:
|
||||||
- run:
|
- run:
|
||||||
name: Setup cmake build
|
name: Setup cmake build
|
||||||
command: cmake-build-and-test.sh
|
command: cmake-build-and-test.sh
|
||||||
static_analysis:
|
- run:
|
||||||
|
name: Valgrind checks.
|
||||||
|
command: cmake-run-valgrind.sh
|
||||||
|
NOT_REQUIRED_static_analysis:
|
||||||
docker:
|
docker:
|
||||||
- image: git.wntrmute.dev/sc/dev:main
|
- image: git.wntrmute.dev/sc/dev:main
|
||||||
steps:
|
steps:
|
||||||
|
@ -24,4 +27,4 @@ workflows:
|
||||||
- ctest
|
- ctest
|
||||||
static_analysis:
|
static_analysis:
|
||||||
jobs:
|
jobs:
|
||||||
- static_analysis
|
- NOT_REQUIRED_static_analysis
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace geom {
|
||||||
template<typename T>
|
template<typename T>
|
||||||
class Quaternion {
|
class Quaternion {
|
||||||
public:
|
public:
|
||||||
/// \brief Construct an identity MakeQuaternion.
|
/// \brief Construct an identity Quaternion.
|
||||||
Quaternion() : v(Vector<T, 3>{0.0, 0.0, 0.0}), w(1.0)
|
Quaternion() : v(Vector<T, 3>{0.0, 0.0, 0.0}), w(1.0)
|
||||||
{
|
{
|
||||||
scmp::DefaultEpsilon(this->eps);
|
scmp::DefaultEpsilon(this->eps);
|
||||||
|
@ -68,7 +68,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// \brief Construct a MakeQuaternion with an Axis and Angle of
|
/// \brief Construct a Quaternion with an Axis and Angle of
|
||||||
/// rotation.
|
/// rotation.
|
||||||
///
|
///
|
||||||
/// A Quaternion may be initialised with a Vector<T, 3> Axis
|
/// A Quaternion may be initialised with a Vector<T, 3> Axis
|
||||||
|
@ -119,7 +119,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Set the comparison tolerance for this MakeQuaternion.
|
/// \brief Set the comparison tolerance for this Quaternion.
|
||||||
///
|
///
|
||||||
/// \param epsilon A tolerance value.
|
/// \param epsilon A tolerance value.
|
||||||
void
|
void
|
||||||
|
@ -130,9 +130,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Return the Axis of rotation of this MakeQuaternion.
|
/// \brief Return the Axis of rotation of this Quaternion.
|
||||||
///
|
///
|
||||||
/// \return The Axis of rotation of this MakeQuaternion.
|
/// \return The Axis of rotation of this Quaternion.
|
||||||
Vector<T, 3>
|
Vector<T, 3>
|
||||||
Axis() const
|
Axis() const
|
||||||
{
|
{
|
||||||
|
@ -140,9 +140,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Return the Angle of rotation of this MakeQuaternion.
|
/// \brief Return the Angle of rotation of this Quaternion.
|
||||||
///
|
///
|
||||||
/// \return the Angle of rotation of this MakeQuaternion.
|
/// \return the Angle of rotation of this Quaternion.
|
||||||
T
|
T
|
||||||
Angle() const
|
Angle() const
|
||||||
{
|
{
|
||||||
|
@ -152,7 +152,7 @@ public:
|
||||||
|
|
||||||
/// \brief Compute the Dot product of two quaternions.
|
/// \brief Compute the Dot product of two quaternions.
|
||||||
///
|
///
|
||||||
/// \param other Another MakeQuaternion.
|
/// \param other Another Quaternion.
|
||||||
/// \return The Dot product between the two quaternions.
|
/// \return The Dot product between the two quaternions.
|
||||||
T
|
T
|
||||||
Dot(const Quaternion<T> &other) const
|
Dot(const Quaternion<T> &other) const
|
||||||
|
@ -166,7 +166,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Compute the Norm of a MakeQuaternion.
|
/// \brief Compute the Norm of a Quaternion.
|
||||||
///
|
///
|
||||||
/// Treating the Quaternion as a Vector<T, 4>, this is the same
|
/// Treating the Quaternion as a Vector<T, 4>, this is the same
|
||||||
/// process as computing the Magnitude.
|
/// process as computing the Magnitude.
|
||||||
|
@ -186,18 +186,18 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Return the unit MakeQuaternion.
|
/// \brief Return the unit Quaternion.
|
||||||
///
|
///
|
||||||
/// \return The unit MakeQuaternion.
|
/// \return The unit Quaternion.
|
||||||
Quaternion
|
Quaternion
|
||||||
UnitQuaternion()
|
UnitQuaternion()
|
||||||
{
|
{
|
||||||
return *this / this->Norm();
|
return *this / this->Norm();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Compute the Conjugate of a MakeQuaternion.
|
/// \brief Compute the Conjugate of a Quaternion.
|
||||||
///
|
///
|
||||||
/// \return The Conjugate of this MakeQuaternion.
|
/// \return The Conjugate of this Quaternion.
|
||||||
Quaternion
|
Quaternion
|
||||||
Conjugate() const
|
Conjugate() const
|
||||||
{
|
{
|
||||||
|
@ -205,9 +205,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Compute the Inverse of a MakeQuaternion.
|
/// \brief Compute the Inverse of a Quaternion.
|
||||||
///
|
///
|
||||||
/// \return The Inverse of this MakeQuaternion.
|
/// \return The Inverse of this Quaternion.
|
||||||
Quaternion
|
Quaternion
|
||||||
Inverse() const
|
Inverse() const
|
||||||
{
|
{
|
||||||
|
@ -217,9 +217,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Determine whether this is an identity MakeQuaternion.
|
/// \brief Determine whether this is an identity Quaternion.
|
||||||
///
|
///
|
||||||
/// \return true if this is an identity MakeQuaternion.
|
/// \return true if this is an identity Quaternion.
|
||||||
bool
|
bool
|
||||||
IsIdentity() const {
|
IsIdentity() const {
|
||||||
return this->v.IsZero() &&
|
return this->v.IsZero() &&
|
||||||
|
@ -227,22 +227,23 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Determine whether this is a unit MakeQuaternion.
|
/// \brief Determine whether this is a unit Quaternion.
|
||||||
///
|
///
|
||||||
/// \return true if this is a unit MakeQuaternion.
|
/// \return true if this is a unit Quaternion.
|
||||||
bool
|
bool
|
||||||
IsUnitQuaternion() const
|
IsUnitQuaternion() const
|
||||||
{
|
{
|
||||||
return scmp::WithinTolerance(this->Norm(), (T) 1.0, this->eps);
|
auto normal = this->Norm();
|
||||||
|
return scmp::WithinTolerance(normal, (T) 1.0, this->eps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Convert to Vector form.
|
/// \brief Convert to Vector form.
|
||||||
///
|
///
|
||||||
/// Return the MakeQuaternion as a Vector<T, 4>, with the Axis of
|
/// Return the Quaternion as a Vector<T, 4>, with the Axis of
|
||||||
/// rotation followed by the Angle of rotation.
|
/// rotation followed by the Angle of rotation.
|
||||||
///
|
///
|
||||||
/// \return A vector representation of the MakeQuaternion.
|
/// \return A vector representation of the Quaternion.
|
||||||
Vector<T, 4>
|
Vector<T, 4>
|
||||||
AsVector() const
|
AsVector() const
|
||||||
{
|
{
|
||||||
|
@ -250,7 +251,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Rotate Vector vr about this MakeQuaternion.
|
/// \brief Rotate Vector vr about this Quaternion.
|
||||||
///
|
///
|
||||||
/// \param vr The vector to be rotated.
|
/// \param vr The vector to be rotated.
|
||||||
/// \return The rotated vector.
|
/// \return The rotated vector.
|
||||||
|
@ -261,9 +262,9 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Return Euler angles for this MakeQuaternion.
|
/// \brief Return Euler angles for this Quaternion.
|
||||||
///
|
///
|
||||||
/// Return the Euler angles for this MakeQuaternion as a vector of
|
/// Return the Euler angles for this Quaternion as a vector of
|
||||||
/// <yaw, pitch, roll>.
|
/// <yaw, pitch, roll>.
|
||||||
///
|
///
|
||||||
/// \warning Users of this function should watch out for gimbal
|
/// \warning Users of this function should watch out for gimbal
|
||||||
|
@ -289,7 +290,7 @@ public:
|
||||||
|
|
||||||
/// \brief Quaternion addition.
|
/// \brief Quaternion addition.
|
||||||
///
|
///
|
||||||
/// \param other The MakeQuaternion to be added with this one.
|
/// \param other The Quaternion to be added with this one.
|
||||||
/// \return The result of adding the two quaternions together.
|
/// \return The result of adding the two quaternions together.
|
||||||
Quaternion
|
Quaternion
|
||||||
operator+(const Quaternion<T> &other) const
|
operator+(const Quaternion<T> &other) const
|
||||||
|
@ -300,8 +301,8 @@ public:
|
||||||
|
|
||||||
/// \brief Quaternion subtraction.
|
/// \brief Quaternion subtraction.
|
||||||
///
|
///
|
||||||
/// \param other The MakeQuaternion to be subtracted from this one.
|
/// \param other The Quaternion to be subtracted from this one.
|
||||||
/// \return The result of subtracting the other MakeQuaternion from this one.
|
/// \return The result of subtracting the other Quaternion from this one.
|
||||||
Quaternion
|
Quaternion
|
||||||
operator-(const Quaternion<T> &other) const
|
operator-(const Quaternion<T> &other) const
|
||||||
{
|
{
|
||||||
|
@ -312,7 +313,7 @@ public:
|
||||||
/// \brief Scalar multiplication.
|
/// \brief Scalar multiplication.
|
||||||
///
|
///
|
||||||
/// \param k The scaling value.
|
/// \param k The scaling value.
|
||||||
/// \return A scaled MakeQuaternion.
|
/// \return A scaled Quaternion.
|
||||||
Quaternion
|
Quaternion
|
||||||
operator*(const T k) const
|
operator*(const T k) const
|
||||||
{
|
{
|
||||||
|
@ -323,7 +324,7 @@ public:
|
||||||
/// \brief Scalar division.
|
/// \brief Scalar division.
|
||||||
///
|
///
|
||||||
/// \param k The scalar divisor.
|
/// \param k The scalar divisor.
|
||||||
/// \return A scaled MakeQuaternion.
|
/// \return A scaled Quaternion.
|
||||||
Quaternion
|
Quaternion
|
||||||
operator/(const T k) const
|
operator/(const T k) const
|
||||||
{
|
{
|
||||||
|
@ -334,11 +335,11 @@ public:
|
||||||
/// \brief Quaternion Hamilton multiplication with a three-
|
/// \brief Quaternion Hamilton multiplication with a three-
|
||||||
/// dimensional vector.
|
/// dimensional vector.
|
||||||
///
|
///
|
||||||
/// This is done by treating the vector as a pure MakeQuaternion
|
/// This is done by treating the vector as a pure Quaternion
|
||||||
/// (e.g. with an Angle of rotation of 0).
|
/// (e.g. with an Angle of rotation of 0).
|
||||||
///
|
///
|
||||||
/// \param vector The vector to multiply with this MakeQuaternion.
|
/// \param vector The vector to multiply with this Quaternion.
|
||||||
/// \return The Hamilton product of the MakeQuaternion and vector.
|
/// \return The Hamilton product of the Quaternion and vector.
|
||||||
Quaternion
|
Quaternion
|
||||||
operator*(const Vector<T, 3> &vector) const
|
operator*(const Vector<T, 3> &vector) const
|
||||||
{
|
{
|
||||||
|
@ -349,7 +350,7 @@ public:
|
||||||
|
|
||||||
/// \brief Quaternion Hamilton multiplication.
|
/// \brief Quaternion Hamilton multiplication.
|
||||||
///
|
///
|
||||||
/// \param other The other MakeQuaternion to multiply with this one.
|
/// \param other The other Quaternion to multiply with this one.
|
||||||
/// @result The Hamilton product of the two quaternions.
|
/// @result The Hamilton product of the two quaternions.
|
||||||
Quaternion
|
Quaternion
|
||||||
operator*(const Quaternion<T> &other) const
|
operator*(const Quaternion<T> &other) const
|
||||||
|
@ -365,7 +366,7 @@ public:
|
||||||
|
|
||||||
/// \brief Quaternion equivalence.
|
/// \brief Quaternion equivalence.
|
||||||
///
|
///
|
||||||
/// \param other The MakeQuaternion to check equality against.
|
/// \param other The Quaternion to check equality against.
|
||||||
/// \return True if the two quaternions are equal within their tolerance.
|
/// \return True if the two quaternions are equal within their tolerance.
|
||||||
bool
|
bool
|
||||||
operator==(const Quaternion<T> &other) const
|
operator==(const Quaternion<T> &other) const
|
||||||
|
@ -377,7 +378,7 @@ public:
|
||||||
|
|
||||||
/// \brief Quaternion non-equivalence.
|
/// \brief Quaternion non-equivalence.
|
||||||
///
|
///
|
||||||
/// \param other The MakeQuaternion to check inequality against.
|
/// \param other The Quaternion to check inequality against.
|
||||||
/// \return True if the two quaternions are unequal within their tolerance.
|
/// \return True if the two quaternions are unequal within their tolerance.
|
||||||
bool
|
bool
|
||||||
operator!=(const Quaternion<T> &other) const
|
operator!=(const Quaternion<T> &other) const
|
||||||
|
@ -386,13 +387,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// \brief Output a MakeQuaternion to a stream in the form
|
/// \brief Output a Quaternion to a stream in the form
|
||||||
/// `a + <i, j, k>`.
|
/// `a + <i, j, k>`.
|
||||||
///
|
///
|
||||||
/// \todo improve the formatting.
|
/// \todo improve the formatting.
|
||||||
///
|
///
|
||||||
/// \param outs An output stream
|
/// \param outs An output stream
|
||||||
/// \param q A MakeQuaternion
|
/// \param q A Quaternion
|
||||||
/// \return The output stream
|
/// \return The output stream
|
||||||
friend std::ostream &
|
friend std::ostream &
|
||||||
operator<<(std::ostream &outs, const Quaternion<T> &q)
|
operator<<(std::ostream &outs, const Quaternion<T> &q)
|
||||||
|
@ -438,41 +439,41 @@ typedef Quaternion<double> Quaterniond;
|
||||||
|
|
||||||
/// \brief Convenience Quaternion construction function.
|
/// \brief Convenience Quaternion construction function.
|
||||||
///
|
///
|
||||||
/// Return a float MakeQuaternion scaled appropriately from a vector and
|
/// Return a float Quaternion scaled appropriately from a vector and
|
||||||
/// Angle, e.g.
|
/// Angle, e.g.
|
||||||
/// angle = cos(Angle / 2),
|
/// angle = cos(Angle / 2),
|
||||||
/// Axis.UnitVector() * sin(Angle / 2).
|
/// Axis.UnitVector() * sin(Angle / 2).
|
||||||
///
|
///
|
||||||
/// \param axis The Axis of rotation.
|
/// \param axis The Axis of rotation.
|
||||||
/// \param angle The Angle of rotation.
|
/// \param angle The Angle of rotation.
|
||||||
/// \return A MakeQuaternion.
|
/// \return A Quaternion.
|
||||||
/// \relatesalso Quaternion
|
/// \relatesalso Quaternion
|
||||||
Quaternionf MakeQuaternion(Vector3F axis, float angle);
|
Quaternionf MakeQuaternion(Vector3F axis, float angle);
|
||||||
|
|
||||||
/// \brief Convience Quaternion construction function.
|
/// \brief Convience Quaternion construction function.
|
||||||
///
|
///
|
||||||
/// Return a double MakeQuaternion scaled appropriately from a vector and
|
/// Return a double Quaternion scaled appropriately from a vector and
|
||||||
/// Angle, e.g.
|
/// Angle, e.g.
|
||||||
/// Angle = cos(Angle / 2),
|
/// Angle = cos(Angle / 2),
|
||||||
/// Axis.UnitVector() * sin(Angle / 2).
|
/// Axis.UnitVector() * sin(Angle / 2).
|
||||||
///
|
///
|
||||||
/// \param axis The Axis of rotation.
|
/// \param axis The Axis of rotation.
|
||||||
/// \param angle The Angle of rotation.
|
/// \param angle The Angle of rotation.
|
||||||
/// \return A MakeQuaternion.
|
/// \return A Quaternion.
|
||||||
/// \relatesalso Quaternion
|
/// \relatesalso Quaternion
|
||||||
Quaterniond MakeQuaternion(Vector3D axis, double angle);
|
Quaterniond MakeQuaternion(Vector3D axis, double angle);
|
||||||
|
|
||||||
|
|
||||||
/// \brief Convience Quaternion construction function.
|
/// \brief Convience Quaternion construction function.
|
||||||
///
|
///
|
||||||
/// Return a double MakeQuaternion scaled appropriately from a vector and
|
/// Return a double Quaternion scaled appropriately from a vector and
|
||||||
/// Angle, e.g.
|
/// Angle, e.g.
|
||||||
/// Angle = cos(Angle / 2),
|
/// Angle = cos(Angle / 2),
|
||||||
/// Axis.UnitVector() * sin(Angle / 2).
|
/// Axis.UnitVector() * sin(Angle / 2).
|
||||||
///
|
///
|
||||||
/// \param axis The Axis of rotation.
|
/// \param axis The Axis of rotation.
|
||||||
/// \param angle The Angle of rotation.
|
/// \param angle The Angle of rotation.
|
||||||
/// \return A MakeQuaternion.
|
/// \return A Quaternion.
|
||||||
/// \relatesalso Quaternion
|
/// \relatesalso Quaternion
|
||||||
template <typename T>
|
template <typename T>
|
||||||
Quaternion<T>
|
Quaternion<T>
|
||||||
|
@ -513,8 +514,8 @@ Quaterniond DoubleQuaternionFromEuler(Vector3D euler);
|
||||||
/// fraction of the distance between them.
|
/// fraction of the distance between them.
|
||||||
///
|
///
|
||||||
/// \tparam T
|
/// \tparam T
|
||||||
/// \param p The starting MakeQuaternion.
|
/// \param p The starting Quaternion.
|
||||||
/// \param q The ending MakeQuaternion.
|
/// \param q The ending Quaternion.
|
||||||
/// \param t The fraction of the distance between the two quaternions to
|
/// \param t The fraction of the distance between the two quaternions to
|
||||||
/// interpolate.
|
/// interpolate.
|
||||||
/// \return A Quaternion representing the linear interpolation of the
|
/// \return A Quaternion representing the linear interpolation of the
|
||||||
|
@ -534,8 +535,8 @@ LERP(Quaternion<T> p, Quaternion<T> q, T t)
|
||||||
/// distance between them.
|
/// distance between them.
|
||||||
///
|
///
|
||||||
/// \tparam T
|
/// \tparam T
|
||||||
/// \param p The starting MakeQuaternion.
|
/// \param p The starting Quaternion.
|
||||||
/// \param q The ending MakeQuaternion.Short
|
/// \param q The ending Quaternion.
|
||||||
/// \param t The fraction of the distance between the two quaternions
|
/// \param t The fraction of the distance between the two quaternions
|
||||||
/// to interpolate.
|
/// to interpolate.
|
||||||
/// \return A Quaternion representing the shortest path between two
|
/// \return A Quaternion representing the shortest path between two
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace scsl {
|
||||||
/// CommanderFunc describes a function that can be run in Commander.
|
/// CommanderFunc describes a function that can be run in Commander.
|
||||||
///
|
///
|
||||||
/// It expects an argument count and a list of arguments.
|
/// It expects an argument count and a list of arguments.
|
||||||
using CommanderFunc = std::function<bool (int, char **)>;
|
using CommanderFunc = std::function<bool (std::vector<std::string>)>;
|
||||||
|
|
||||||
|
|
||||||
/// \brief Subcommands used by Commander.
|
/// \brief Subcommands used by Commander.
|
||||||
|
@ -72,8 +72,8 @@ public:
|
||||||
/// \param name The subcommand name; this is the name that will select this command.
|
/// \param name The subcommand name; this is the name that will select this command.
|
||||||
/// \param argc The minimum number of arguments required by this subcommand.
|
/// \param argc The minimum number of arguments required by this subcommand.
|
||||||
/// \param func A valid CommanderFunc.
|
/// \param func A valid CommanderFunc.
|
||||||
Subcommand(std::string name, int argc, CommanderFunc func)
|
Subcommand(std::string name, size_t argc, CommanderFunc func)
|
||||||
: fn(func), args(argc), command(name)
|
: fn(func), requiredArgs(argc), command(name)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// Name returns the name of this subcommand.
|
/// Name returns the name of this subcommand.
|
||||||
|
@ -81,13 +81,12 @@ public:
|
||||||
|
|
||||||
/// Run attempts to run the CommanderFunc for this subcommand.
|
/// Run attempts to run the CommanderFunc for this subcommand.
|
||||||
///
|
///
|
||||||
/// \param argc The number of arguments supplied.
|
/// \param args The argument list.
|
||||||
/// \param argv The argument list.
|
|
||||||
/// \return A Status type indicating the status of running the command.
|
/// \return A Status type indicating the status of running the command.
|
||||||
Status Run(int argc, char **argv);
|
Status Run(std::vector<std::string> args);
|
||||||
private:
|
private:
|
||||||
CommanderFunc fn;
|
CommanderFunc fn;
|
||||||
int args;
|
size_t requiredArgs;
|
||||||
std::string command;
|
std::string command;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,7 +118,7 @@ public:
|
||||||
bool Register(Subcommand scmd);
|
bool Register(Subcommand scmd);
|
||||||
|
|
||||||
/// Try to run a subcommand registered with this Commander.
|
/// Try to run a subcommand registered with this Commander.
|
||||||
Subcommand::Status Run(std::string command, int argc, char **argv);
|
Subcommand::Status Run(std::string command, std::vector<std::string> args);
|
||||||
private:
|
private:
|
||||||
std::map<std::string, Subcommand *> cmap;
|
std::map<std::string, Subcommand *> cmap;
|
||||||
};
|
};
|
||||||
|
|
|
@ -27,48 +27,50 @@ using namespace std;
|
||||||
#include <scsl/Arena.h>
|
#include <scsl/Arena.h>
|
||||||
#include <scsl/Commander.h>
|
#include <scsl/Commander.h>
|
||||||
#include <scsl/Dictionary.h>
|
#include <scsl/Dictionary.h>
|
||||||
|
#include <scsl/Flags.h>
|
||||||
|
|
||||||
|
|
||||||
using namespace scsl;
|
using namespace scsl;
|
||||||
|
|
||||||
static const char *defaultPhonebook = "pb.dat";
|
static const char *defaultPhonebook = "pb.dat";
|
||||||
static char *pbFile = (char *)defaultPhonebook;
|
static std::string pbFile(defaultPhonebook);
|
||||||
static Arena arena;
|
static Arena arena;
|
||||||
static Dictionary pb(arena);
|
static Dictionary pb(arena);
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
listFiles(int argc, char **argv)
|
listFiles(std::vector<std::string> argv)
|
||||||
{
|
{
|
||||||
(void)argc; (void)argv;
|
(void) argv; // provided for interface compatibility.
|
||||||
cout << "[+] keys in '" << pbFile << "':\n";
|
cout << "[+] keys in '" << pbFile << "':\n";
|
||||||
cout << pb;
|
cout << pb;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
newPhonebook(int argc, char **argv)
|
|
||||||
{
|
|
||||||
(void)argc;
|
|
||||||
|
|
||||||
auto size = std::stoul(string(argv[0]));
|
static bool
|
||||||
|
newPhonebook(std::vector<std::string> argv)
|
||||||
|
{
|
||||||
|
auto size = std::stoul(argv[0]);
|
||||||
cout << "[+] create new " << size << "B phonebook '" << pbFile << "'\n";
|
cout << "[+] create new " << size << "B phonebook '" << pbFile << "'\n";
|
||||||
|
|
||||||
return arena.Create(pbFile, size) == 0;
|
return arena.Create(pbFile.c_str(), size) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
delKey(int argc, char **argv)
|
delKey(std::vector<std::string> argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
|
||||||
string key = argv[0];
|
string key = argv[0];
|
||||||
|
|
||||||
cout << "[+] deleting key '" << key << "'\n";
|
cout << "[+] deleting key '" << key << "'\n";
|
||||||
return pb.Delete(key.c_str(), key.size());
|
return pb.Delete(key.c_str(), key.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
hasKey(int argc, char **argv)
|
hasKey(std::vector<std::string> argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
|
||||||
string key = argv[0];
|
string key = argv[0];
|
||||||
|
|
||||||
cout << "[+] looking up '" << key << "': ";
|
cout << "[+] looking up '" << key << "': ";
|
||||||
|
@ -81,10 +83,10 @@ hasKey(int argc, char **argv)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
getKey(int argc, char **argv)
|
getKey(std::vector<std::string> argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
|
||||||
TLV::Record rec;
|
TLV::Record rec;
|
||||||
auto key = string(argv[0]);
|
auto key = string(argv[0]);
|
||||||
|
|
||||||
|
@ -100,9 +102,8 @@ getKey(int argc, char **argv)
|
||||||
|
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
putKey(int argc, char **argv)
|
putKey(std::vector<std::string> argv)
|
||||||
{
|
{
|
||||||
(void)argc;
|
|
||||||
auto key = string(argv[0]);
|
auto key = string(argv[0]);
|
||||||
auto val = string(argv[1]);
|
auto val = string(argv[1]);
|
||||||
|
|
||||||
|
@ -116,6 +117,7 @@ putKey(int argc, char **argv)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
usage(ostream &os, int exc)
|
usage(ostream &os, int exc)
|
||||||
{
|
{
|
||||||
|
@ -136,28 +138,35 @@ usage(ostream &os, int exc)
|
||||||
int
|
int
|
||||||
main(int argc, char *argv[])
|
main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int optind = 1;
|
bool help = false;
|
||||||
|
std::string fileName(pbFile);
|
||||||
|
|
||||||
for (optind = 1; optind < argc; optind++) {
|
auto *flags = new scsl::Flags("phonebook",
|
||||||
auto arg = string(argv[optind]);
|
"A tool for interacting with Arena-backed dictionary files.");
|
||||||
if (arg[0] != '-') break;
|
flags->Register("-f", pbFile, "path to a phonebook file");
|
||||||
if (arg == "-h") usage(cout, 0);
|
flags->Register("-h", false, "print a help message");
|
||||||
if (arg == "-f") {
|
|
||||||
pbFile = argv[optind+1];
|
auto parsed = flags->Parse(argc, argv);
|
||||||
optind++;
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
continue;
|
std::cerr << "Failed to parse flags: "
|
||||||
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
usage(cerr, 1);
|
flags->GetString("-f", fileName);
|
||||||
|
flags->GetBool("-h", help);
|
||||||
|
|
||||||
|
pbFile = fileName;
|
||||||
|
|
||||||
|
if (help) {
|
||||||
|
usage(std::cerr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc <= 1) {
|
if (flags->NumArgs() == 0) {
|
||||||
usage(cout, 0);
|
usage(std::cerr, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto command = string(argv[optind++]);
|
|
||||||
Commander commander;
|
Commander commander;
|
||||||
|
|
||||||
commander.Register(Subcommand("list", 0, listFiles));
|
commander.Register(Subcommand("list", 0, listFiles));
|
||||||
commander.Register(Subcommand("new", 1, newPhonebook));
|
commander.Register(Subcommand("new", 1, newPhonebook));
|
||||||
commander.Register(Subcommand("del", 1, delKey));
|
commander.Register(Subcommand("del", 1, delKey));
|
||||||
|
@ -165,15 +174,19 @@ main(int argc, char *argv[])
|
||||||
commander.Register(Subcommand("get", 1, getKey));
|
commander.Register(Subcommand("get", 1, getKey));
|
||||||
commander.Register(Subcommand("put", 2, putKey));
|
commander.Register(Subcommand("put", 2, putKey));
|
||||||
|
|
||||||
|
auto command = flags->Arg(0);
|
||||||
if (command != "new") {
|
if (command != "new") {
|
||||||
cout << "[+] loading phonebook from " << pbFile << "\n";
|
cout << "[+] loading phonebook from " << pbFile << "\n";
|
||||||
if (arena.Open(pbFile) != 0) {
|
if (arena.Open(pbFile.c_str()) != 0) {
|
||||||
cerr << "Failed to open " << pbFile << "\n";
|
cerr << "Failed to open " << pbFile << "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = commander.Run(command, argc-optind, argv+optind);
|
auto args = flags->Args();
|
||||||
|
args.erase(args.begin());
|
||||||
|
|
||||||
|
auto result = commander.Run(command, args);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case Subcommand::Status::OK:
|
case Subcommand::Status::OK:
|
||||||
std::cout << "[+] OK\n";
|
std::cout << "[+] OK\n";
|
||||||
|
|
|
@ -29,15 +29,16 @@ namespace scsl {
|
||||||
|
|
||||||
|
|
||||||
Subcommand::Status
|
Subcommand::Status
|
||||||
Subcommand::Run(int argc, char **argv)
|
Subcommand::Run(std::vector<std::string> args)
|
||||||
{
|
{
|
||||||
if (argc < this->args) {
|
auto argc = args.size();
|
||||||
|
if (argc < this->requiredArgs) {
|
||||||
std::cerr << "[!] " << this->command << " expects ";
|
std::cerr << "[!] " << this->command << " expects ";
|
||||||
std::cerr << this->args << " args, but was given ";
|
std::cerr << this->requiredArgs << " args, but was given ";
|
||||||
std::cerr << argc << " args.\n";
|
std::cerr << argc << " args.\n";
|
||||||
return Subcommand::Status::NotEnoughArgs;
|
return Subcommand::Status::NotEnoughArgs;
|
||||||
}
|
}
|
||||||
if (this->fn(argc, argv)) {
|
if (this->fn(args)) {
|
||||||
return Subcommand::Status::OK;
|
return Subcommand::Status::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,14 +65,14 @@ Commander::Register(Subcommand scmd)
|
||||||
|
|
||||||
|
|
||||||
Subcommand::Status
|
Subcommand::Status
|
||||||
Commander::Run(std::string command, int argc, char **argv)
|
Commander::Run(std::string command, std::vector<std::string> args)
|
||||||
{
|
{
|
||||||
if (this->cmap.count(command) != 1) {
|
if (this->cmap.count(command) != 1) {
|
||||||
return Subcommand::Status::CommandNotRegistered;
|
return Subcommand::Status::CommandNotRegistered;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto scmd = this->cmap[command];
|
auto scmd = this->cmap[command];
|
||||||
return scmd->Run(argc, argv);
|
return scmd->Run(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -95,7 +95,7 @@ Flags::~Flags()
|
||||||
bool
|
bool
|
||||||
Flags::Register(std::string fName, FlagType fType, std::string fDescription)
|
Flags::Register(std::string fName, FlagType fType, std::string fDescription)
|
||||||
{
|
{
|
||||||
if (!std::regex_search(fName, isFlag) || fName == "-h") {
|
if (!std::regex_search(fName, isFlag)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sctest::SimpleSuite suite;
|
sctest::SimpleSuite suite;
|
||||||
|
|
|
@ -270,6 +270,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleSuite suite;
|
SimpleSuite suite;
|
||||||
|
|
|
@ -122,6 +122,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sctest::SimpleSuite suite;
|
sctest::SimpleSuite suite;
|
||||||
|
|
|
@ -245,6 +245,7 @@ main(int argc, char **argv)
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sctest::SimpleSuite suite;
|
sctest::SimpleSuite suite;
|
||||||
|
|
|
@ -133,6 +133,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sctest::SimpleSuite suite;
|
sctest::SimpleSuite suite;
|
||||||
|
|
|
@ -99,6 +99,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleSuite suite;
|
SimpleSuite suite;
|
||||||
|
|
|
@ -442,6 +442,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleSuite suite;
|
SimpleSuite suite;
|
||||||
|
|
|
@ -66,6 +66,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sctest::SimpleSuite suite;
|
sctest::SimpleSuite suite;
|
||||||
|
|
|
@ -149,6 +149,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sctest::SimpleSuite suite;
|
sctest::SimpleSuite suite;
|
||||||
|
|
|
@ -151,6 +151,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
sctest::SimpleSuite suite;
|
sctest::SimpleSuite suite;
|
||||||
|
|
|
@ -442,6 +442,7 @@ main(int argc, char *argv[])
|
||||||
if (parsed != scsl::Flags::ParseStatus::OK) {
|
if (parsed != scsl::Flags::ParseStatus::OK) {
|
||||||
std::cerr << "Failed to parse flags: "
|
std::cerr << "Failed to parse flags: "
|
||||||
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
<< scsl::Flags::ParseStatusToString(parsed) << "\n";
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimpleSuite suite;
|
SimpleSuite suite;
|
||||||
|
|
Loading…
Reference in New Issue