Skip to content

Commit

Permalink
Rename to 'Courier'.
Browse files Browse the repository at this point in the history
  • Loading branch information
nealkruis committed Feb 2, 2024
1 parent 1dc5b8f commit 04233d1
Show file tree
Hide file tree
Showing 7 changed files with 42 additions and 42 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.10) # required for gtest_discover_tests

project(courierr)
project(courier)

# Set a default build type if none was specified
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
Expand Down
44 changes: 22 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
# Courierr
# Courier

A lightweight, header-only C++ library for use in other libraries that allows client code define how to:

1. deliver context-specific error, warning, and informational messages from a library to the client's users, and
2. handle errors from a library when they occur.

Courrier itself is NOT a logger or an error handler. It simply provides a mechanism for clients to decide how to log and
Courier itself is NOT a logger or an error handler. It simply provides a mechanism for clients to decide how to log and
handle errors encountered in a library.

## Error Levels

Courierr defines four message levels (based
Courier defines four message levels (based
on [Python Logging Levels](https://docs.python.org/3/library/logging.html#logging-levels)):

1. `error`: Due to a more serious problem, the software has not been able to perform some
function. Errors encountered in library code imply that execution cannot continue reliably within the library.
Courierr allows the client to decide how to handle errors. However, if an error is ultimately not handled,
Courrier will throw an exception from the library.
Courier allows the client to decide how to handle errors. However, if an error is ultimately not handled,
Courier will throw an exception from the library.
2. `warning`: An indication that something unexpected happened, or that a problem might occur
in the near future. The software is still working as expected.
3. `info`: Confirmation that things are working as expected.
Expand All @@ -25,30 +25,30 @@ on [Python Logging Levels](https://docs.python.org/3/library/logging.html#loggin

## Usage

Courierr has two audiences:
Courier has two audiences:

1. Library developers that want to give their clients flexibility in message logging and error handling, and
2. Clients adopting such libraries

### Library Developers

Developers add a `Courierr` (though we recommend using a `std::shared_ptr<Courierr::Courierr>`) data member to any
public class in a library where an error (or other loggable event) might occur.
Developers add a `Courier` (though we recommend using a `std::shared_ptr<Courier::Courier>`) data member to any
public class in a library where an error (or other message event) might occur.

```c++
#include <courierr/courierr.h>
#include <courier/courier.h>

class LibraryClass {
public:
LibraryClass(std::string name_in, const std::shared_ptr<Courierr::Courierr>& courier_in)
LibraryClass(std::string name_in, const std::shared_ptr<Courier::Courier>& courier_in)
: name(std::move(name_in)), courier(courier_in) {}
private:
std::string name;
std::shared_ptr<Courierr::Courierr> courier;
std::shared_ptr<Courier::Courier> courier;
};
```
The `Courierr` base class defines an interface with a public methods for each of the four message levels:
The `Courier::Courier` base class defines an interface with a public methods for each of the four message levels:
- `send_debug(const std::string& message)`
- `send_info(const std::string& message)`
Expand All @@ -66,29 +66,29 @@ if (problem_exists)

#### Good Practices

The following examples illustrate ways to use `Courierr` most effectively as a library developer. These practices are
The following examples illustrate ways to use `Courier` most effectively as a library developer. These practices are
also implemented in [test/library.h](test/library.h).

1. The parent class should provide access to set and get the `Courierr` pointer:
1. The parent class should provide access to set and get the `Courier` pointer:

```c++
void set_courier(std::shared_ptr<Courierr::Courierr> courier_in)
void set_courier(std::shared_ptr<Courier::Courier> courier_in)
{
courier = std::move(courier_in);
}
std::shared_ptr<Courierr::Courierr> get_courier() { return courier; }
std::shared_ptr<Courier::Courier> get_courier() { return courier; }

```
2. By making `Courierr` shared pointers and providing access, multiple closely-related objects can share a
single `Courierr` instance.
2. By making `Courier` shared pointers and providing access, multiple closely-related objects can share a
single `Courier` instance.
3. Consider defining default derived `Courierr`. Some library users will not care how messages are handled, and don't
want the additional hassle of developing a derived `Courierr` class.
3. Consider defining default derived `Courier`. Some library users will not care how messages are handled, and don't
want the additional hassle of developing a derived `Courier` class.
### Library Adopters
Adopters must derive a class from `Courierr::Courierr`. The Courierr base class establishes four virtual functions for
Adopters must derive a class from `Courier::Courier`. The `Courier` base class establishes four virtual functions for
receiving events:
- `receive_debug(const std::string& message)`
Expand Down Expand Up @@ -136,7 +136,7 @@ in [test/client.h](test/client.h).
void receive_warning(const std::string& message) override
{
if (message_level <= MessageLevel::warning) {
write_message("WARNING", message);
make_message("WARNING", message);
}
}
```
File renamed without changes.
10 changes: 5 additions & 5 deletions include/courierr/courierr.h → include/courier/courier.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@
#include <string>
#include <iostream>

namespace Courierr {
namespace Courier {

class Courierr {
class Courier {
public:
virtual ~Courierr() = default;
virtual ~Courier() = default;

// Sending methods to be used in library source code
[[noreturn]] virtual void send_error(const std::string& message) final
{
receive_error(message);
throw std::runtime_error("Courierr: Error not handled by derived class: \"" + message +
throw std::runtime_error("Courier: Error not handled by derived class: \"" + message +
"\"");
}
virtual void send_warning(const std::string& message) final { receive_warning(message); }
Expand All @@ -31,4 +31,4 @@ class Courierr {
virtual void receive_debug(const std::string& message) = 0;
};

} // namespace Courierr
} // namespace Courier
2 changes: 1 addition & 1 deletion test/client.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class ClientClass {
LibraryClass library_object;
};

class ClientCourier : public Courierr::Courierr {
class ClientCourier : public Courier::Courier {
public:
explicit ClientCourier(ClientClass* client_class_pointer_in)
: client_class_pointer(client_class_pointer_in)
Expand Down
14 changes: 7 additions & 7 deletions test/courierr_tests.cpp → test/courier_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
EXPECT_STREQ(ExpectedOut.c_str(), buffer.str().c_str()); \
}

TEST(Courierr, Warning)
TEST(Courier, Warning)
{
ClientClass client_object("My object");
std::string expected_output {"[WARNING] ClientClass(My object) LibraryClass(My library "
"object): Something unexpected happened\n"};
EXPECT_STDOUT(client_object.library_object.generate_warning();, expected_output)
}

TEST(Courierr, Error)
TEST(Courier, Error)
{
ClientClass client_object("My object");
std::string expected_output {"[ERROR] ClientClass(My object) LibraryClass(My library object): "
Expand All @@ -31,7 +31,7 @@ TEST(Courierr, Error)
, expected_output)
}

TEST(Courierr, MessageLevel)
TEST(Courier, MessageLevel)
{
ClientClass client_object("My object");

Expand All @@ -56,9 +56,9 @@ TEST(Courierr, MessageLevel)
EXPECT_STDOUT(client_object.library_object.generate_warning();, expected_output)
}

TEST(Courierr, Minimal)
TEST(Courier, Minimal)
{
class MinimalCourier : public Courierr::Courierr {
class MinimalCourier : public Courier::Courier {
void receive_error(const std::string& message) override {}
void receive_warning(const std::string& message) override {}
void receive_info(const std::string& message) override {}
Expand All @@ -72,12 +72,12 @@ TEST(Courierr, Minimal)
}
catch (std::runtime_error& exception) {
EXPECT_STREQ(exception.what(),
"Courierr: Error not handled by derived class: \"LibraryClass(My library "
"Courier: Error not handled by derived class: \"LibraryClass(My library "
"object): Something serious happened\"");
}
}

TEST(Courierr, Default)
TEST(Courier, Default)
{
// Test message generated by LibraryDefaultCourier
LibraryClass new_library_object("My library object");
Expand Down
12 changes: 6 additions & 6 deletions test/library.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

#include <string>
#include <utility>
#include <courierr/courierr.h>
#include <courier/courier.h>
#include <fmt/format.h>

class LibraryDefaultCourier : public Courierr::Courierr {
class LibraryDefaultCourier : public Courier::Courier {
void receive_error(const std::string& message) override { write_message("ERROR", message); }
void receive_warning(const std::string& message) override { write_message("WARNING", message); }
void receive_info(const std::string& message) override { write_message("INFO", message); }
Expand All @@ -22,7 +22,7 @@ class LibraryDefaultCourier : public Courierr::Courierr {
class LibraryClass {
public:
LibraryClass(std::string name_in,
const std::shared_ptr<Courierr::Courierr>& courier_in =
const std::shared_ptr<Courier::Courier>& courier_in =
std::make_shared<LibraryDefaultCourier>())
: name(std::move(name_in)), courier(courier_in)
{
Expand All @@ -40,15 +40,15 @@ class LibraryClass {
courier->send_warning(make_message("Something unexpected happened"));
}
void generate_error() { courier->send_error(make_message("Something serious happened")); }
void set_courier(std::shared_ptr<Courierr::Courierr> courier_in)
void set_courier(std::shared_ptr<Courier::Courier> courier_in)
{
courier = std::move(courier_in);
}
std::shared_ptr<Courierr::Courierr> get_courier() { return courier; }
std::shared_ptr<Courier::Courier> get_courier() { return courier; }

private:
std::string name;
std::shared_ptr<Courierr::Courierr> courier;
std::shared_ptr<Courier::Courier> courier;
static constexpr std::string_view message_format {"LibraryClass({}): {}"};
std::string make_message(const std::string& message)
{
Expand Down

0 comments on commit 04233d1

Please sign in to comment.