Commit 85e76a10 authored by Brad King's avatar Brad King
Browse files

Status: Add class to hold an OS-specific status of a system operation

parent db93a594
......@@ -142,6 +142,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
set(KWSYS_USE_MD5 1)
set(KWSYS_USE_Process 1)
set(KWSYS_USE_RegularExpression 1)
set(KWSYS_USE_Status 1)
set(KWSYS_USE_System 1)
set(KWSYS_USE_SystemTools 1)
set(KWSYS_USE_CommandLineArguments 1)
......@@ -630,7 +631,7 @@ set(KWSYS_HXX_FILES Configure String)
# Add selected C++ classes.
set(cppclasses
Directory DynamicLoader Encoding Glob RegularExpression SystemTools
CommandLineArguments FStream SystemInformation ConsoleBuf
CommandLineArguments FStream SystemInformation ConsoleBuf Status
)
foreach(cpp ${cppclasses})
if(KWSYS_USE_${cpp})
......@@ -963,6 +964,7 @@ if(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
# C++ tests
set(KWSYS_CXX_TESTS ${KWSYS_CXX_TESTS}
testConfigure.cxx
testStatus.cxx
testSystemTools.cxx
testCommandLineArguments.cxx
testCommandLineArguments1.cxx
......
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Status.hxx)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
# include "Status.hxx.in"
#endif
#include <cerrno>
#include <cstring>
#include <string>
#if defined(_WIN32)
# include <windows.h>
#endif
namespace KWSYS_NAMESPACE {
Status Status::POSIX_errno()
{
return Status::POSIX(errno);
}
#ifdef _WIN32
Status Status::Windows_GetLastError()
{
return Status::Windows(GetLastError());
}
#endif
std::string Status::GetString() const
{
std::string err;
switch (this->Kind_) {
case Kind::Success:
err = "Success";
break;
case Kind::POSIX:
err = strerror(this->POSIX_);
break;
#ifdef _WIN32
case Kind::Windows: {
LPSTR message = NULL;
DWORD size = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, this->Windows_, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPSTR)&message, 0, NULL);
err = std::string(message, size);
LocalFree(message);
} break;
#endif
};
return err;
}
} // namespace KWSYS_NAMESPACE
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#ifndef @KWSYS_NAMESPACE@_Status_hxx
#define @KWSYS_NAMESPACE@_Status_hxx
#include <@KWSYS_NAMESPACE@/Configure.hxx>
#include <string>
namespace @KWSYS_NAMESPACE@ {
/** \class Status
* \brief OS-specific status of a system operation.
*/
class @KWSYS_NAMESPACE@_EXPORT Status
{
public:
enum class Kind
{
Success,
POSIX,
#ifdef _WIN32
Windows,
#endif
};
/** Construct with kind "Success". */
Status() = default;
/** Construct with kind "Success". */
static Status Success() { return Status(); }
/** Construct with kind "POSIX" using given errno-style value. */
static Status POSIX(int e)
{
Status s(Kind::POSIX);
s.POSIX_ = e;
return s;
}
/** Construct with kind "POSIX" using errno. */
static Status POSIX_errno();
#ifdef _WIN32
/** Construct with kind "Windows" using given GetLastError()-style value. */
static Status Windows(unsigned int e)
{
Status s(Kind::Windows);
s.Windows_ = e;
return s;
}
/** Construct with kind "Windows" using GetLastError(). */
static Status Windows_GetLastError();
#endif
/** Return true on "Success", false otherwise. */
explicit operator bool() const { return this->Kind_ == Kind::Success; }
/** Return the kind of status. */
Kind GetKind() const { return this->Kind_; }
/** If the kind is "POSIX", returns the errno-style value.
Otherwise, returns 0. */
int GetPOSIX() const
{
return this->Kind_ == Kind::POSIX ? this->POSIX_ : 0;
}
#ifdef _WIN32
/** If the kind is "Windows", returns the GetLastError()-style value.
Otherwise, returns 0. */
int GetWindows() const
{
return this->Kind_ == Kind::Windows ? this->Windows_ : 0;
}
#endif
/** Return a human-readable description of the status. */
std::string GetString() const;
private:
Status(Kind kind)
: Kind_(kind)
{
}
Kind Kind_ = Kind::Success;
union
{
int POSIX_;
#ifdef _WIN32
unsigned int Windows_;
#endif
};
};
} // namespace @KWSYS_NAMESPACE@
#endif
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
file Copyright.txt or https://cmake.org/licensing#kwsys for details. */
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Status.hxx)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
# include "Status.hxx.in"
#endif
#include <cerrno>
#include <iostream>
#ifdef _WIN32
# include <windows.h>
#endif
int testStatus(int, char* [])
{
bool res = true;
{
kwsys::Status status;
if (status.GetKind() != kwsys::Status::Kind::Success) {
std::cerr << "Status default constructor does not produce Success\n";
res = false;
}
status = kwsys::Status::Success();
if (status.GetKind() != kwsys::Status::Kind::Success) {
std::cerr << "Status Success constructor does not produce Success\n";
res = false;
}
if (!status) {
std::cerr << "Status Success kind is not true\n";
res = false;
}
if (status.GetPOSIX() != 0) {
std::cerr << "Status Success kind does not return POSIX 0\n";
res = false;
}
#ifdef _WIN32
if (status.GetWindows() != 0) {
std::cerr << "Status Success kind does not return Windows 0\n";
res = false;
}
#endif
if (status.GetString() != "Success") {
std::cerr << "Status Success kind does not return \"Success\" string\n";
res = false;
}
status = kwsys::Status::POSIX(EINVAL);
if (status.GetKind() != kwsys::Status::Kind::POSIX) {
std::cerr << "Status POSIX constructor does not produce POSIX\n";
res = false;
}
if (status) {
std::cerr << "Status POSIX kind is not false\n";
res = false;
}
if (status.GetPOSIX() != EINVAL) {
std::cerr << "Status POSIX kind does not preserve POSIX value\n";
res = false;
}
#ifdef _WIN32
if (status.GetWindows() != 0) {
std::cerr << "Status POSIX kind does not return Windows 0\n";
res = false;
}
#endif
if (status.GetString().empty()) {
std::cerr << "Status POSIX kind returns empty string\n";
res = false;
}
errno = ENOENT;
status = kwsys::Status::POSIX_errno();
if (status.GetPOSIX() != ENOENT) {
std::cerr << "Status POSIX_errno did not use errno\n";
res = false;
}
errno = 0;
#ifdef _WIN32
status = kwsys::Status::Windows(ERROR_INVALID_PARAMETER);
if (status.GetKind() != kwsys::Status::Kind::Windows) {
std::cerr << "Status Windows constructor does not produce Windows\n";
res = false;
}
if (status) {
std::cerr << "Status Windows kind is not false\n";
res = false;
}
if (status.GetWindows() != ERROR_INVALID_PARAMETER) {
std::cerr << "Status Windows kind does not preserve Windows value\n";
res = false;
}
if (status.GetPOSIX() != 0) {
std::cerr << "Status Windows kind does not return POSIX 0\n";
res = false;
}
if (status.GetString().empty()) {
std::cerr << "Status Windows kind returns empty string\n";
res = false;
}
SetLastError(ERROR_FILE_NOT_FOUND);
status = kwsys::Status::Windows_GetLastError();
if (status.GetWindows() != ERROR_FILE_NOT_FOUND) {
std::cerr << "Status Windows_GetLastError did not use GetLastError()\n";
res = false;
}
SetLastError(ERROR_SUCCESS);
#endif
}
return res ? 0 : 1;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment