Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: 🥅 Change all error handling to use errno, add int32_t return codes #25

Merged
merged 15 commits into from
Feb 3, 2025
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions include/gamepad/button.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class Button {
* gamepad::master.Up.onPress("upPress1", []() { std::cout << "I was pressed!" << std::endl; });
* @endcode
*/
bool onPress(std::string listenerName, std::function<void(void)> func) const;
uint32_t onPress(std::string listenerName, std::function<void(void)> func) const;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the functions return INT_MAX when errno is set, which is the maximum value of an int32_t. Consider changing them to int32_t for clarity, but this is not a requirement

Suggested change
uint32_t onPress(std::string listenerName, std::function<void(void)> func) const;
int32_t onPress(std::string listenerName, std::function<void(void)> func) const;

/**
* @brief Register a function to run when the button is long pressed.
*
Expand All @@ -108,7 +108,7 @@ class Button {
* std::endl; });
* @endcode
*/
bool onLongPress(std::string listenerName, std::function<void(void)> func) const;
uint32_t onLongPress(std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Register a function to run when the button is released.
*
Expand All @@ -125,7 +125,7 @@ class Button {
* gamepad::master.Y.onRelease("stopIntake", []() { intake.move(0); });
* @endcode
*/
bool onRelease(std::string listenerName, std::function<void(void)> func) const;
uint32_t onRelease(std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Register a function to run when the button is short released.
*
Expand All @@ -147,7 +147,7 @@ class Button {
* gamepad::master.B.onShortRelease("intakeOnePiece", []() { intake.move_relative(600, 100); });
* @endcode
*/
bool onShortRelease(std::string listenerName, std::function<void(void)> func) const;
uint32_t onShortRelease(std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Register a function to run when the button is long released.
*
Expand All @@ -168,7 +168,7 @@ class Button {
* @endcode
*
*/
bool onLongRelease(std::string listenerName, std::function<void(void)> func) const;
uint32_t onLongRelease(std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Register a function to run periodically after its been held
*
Expand All @@ -189,7 +189,7 @@ class Button {
* @endcode
*
*/
bool onRepeatPress(std::string listenerName, std::function<void(void)> func) const;
uint32_t onRepeatPress(std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Register a function to run for a given event.
*
Expand All @@ -207,7 +207,7 @@ class Button {
* gamepad::master.L1.addListener(gamepad::ON_RELEASE, "stop_spin", []() { motor1.brake(); });
* @endcode
*/
bool addListener(EventType event, std::string listenerName, std::function<void(void)> func) const;
uint32_t addListener(EventType event, std::string listenerName, std::function<void(void)> func) const;
/**
* @brief Removes a listener from the button
* @warning Usage of this function is discouraged.
Expand All @@ -224,7 +224,7 @@ class Button {
* gamepad::master.L1.removeListener("do_something");
* @endcode
*/
bool removeListener(std::string listenerName) const;
uint32_t removeListener(std::string listenerName) const;

/**
* @brief Returns a value indicating whether the button is currently being held.
Expand Down
20 changes: 10 additions & 10 deletions include/gamepad/event_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,33 +24,33 @@ template <typename Key, typename... Args> class EventHandler {
*
* @param key The listener key (this must be a unique key value)
* @param func The function to run when this event is fired
* @return true The listener was successfully added
* @return false The listener was NOT successfully added (there is already a listener with the same key)
* @return 0 The listener was successfully added
* @return UINT32_MAX The listener was NOT successfully added (there is already a listener with the same key)
*/
bool addListener(Key key, Listener func) {
uint32_t addListener(Key key, Listener func) {
std::lock_guard lock(m_mutex);
if (std::find(m_keys.begin(), m_keys.end(), key) != m_keys.end()) return false;
if (std::find(m_keys.begin(), m_keys.end(), key) != m_keys.end()) return UINT32_MAX;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functions should return INT32_MAX when errno is set, so it does not differ from PROS and other LemLib projects

Suggested change
if (std::find(m_keys.begin(), m_keys.end(), key) != m_keys.end()) return UINT32_MAX;
if (std::find(m_keys.begin(), m_keys.end(), key) != m_keys.end()) return INT32_MAX;

m_keys.push_back(key);
m_listeners.push_back(func);
return true;
return 0;
}

/**
* @brief Remove a listener from the list of listeners
*
* @param key The listener key (this must be a unique key value)
* @return true The listener was successfully removed
* @return false The listener was NOT successfully removed (there is no listener with the same key)
* @return 0 The listener was successfully removed
* @return UINT32_MAX The listener was NOT successfully removed (there is no listener with the same key)
*/
bool removeListener(Key key) {
uint32_t removeListener(Key key) {
std::lock_guard lock(m_mutex);
auto i = std::find(m_keys.begin(), m_keys.end(), key);
if (i != m_keys.end()) {
m_keys.erase(i);
m_listeners.erase(m_listeners.begin() + (i - m_keys.begin()));
return true;
return 0;
}
return false;
return UINT32_MAX;
}

/**
Expand Down
16 changes: 14 additions & 2 deletions include/gamepad/gamepad.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,20 @@ class Gamepad {
* @param line the line number to print the string on (0-2)
* @param str the string to print onto the controller (\n to go to the next line)
*
* This function uses the following value(s) of errno when an error state is reached:
*
* EINVAL: The line number is not in the interval [0, 2]
*
* @b Example:
* @code {.cpp}
* gamepad::master.printLine(1, "This will print on the middle line");
* gamepad::master.printLine(0, "this will print\n\naround the middle line");
* @endcode
*
* @return 0 if the alert was added successfully
* @return INT32_MAX if there was an error, setting errno
*/
void printLine(uint8_t line, std::string str);
int32_t printLine(uint8_t line, std::string str);
/**
* @brief clears all lines on the controller, similar to the pros function (low priority)
*
Expand All @@ -81,6 +89,10 @@ class Gamepad {
* @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles,
* dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters.
*
* This function uses the following value(s) of errno when an error state is reached:
*
* EINVAL: The rumble pattern was truncated to 8 characters
*
* @b Example:
* @code {.cpp}
* // rumbles in the following pattern: short, pause, long, short short
Expand Down Expand Up @@ -150,7 +162,7 @@ class Gamepad {
* @return std::string A unique listener name
*/
static std::string uniqueName();
static Button Gamepad::*buttonToPtr(pros::controller_digital_e_t button);
static Button Gamepad::* buttonToPtr(pros::controller_digital_e_t button);
void updateButton(pros::controller_digital_e_t button_id);

void updateScreens();
Expand Down
10 changes: 9 additions & 1 deletion include/gamepad/screens/alertScreen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,16 @@ class AlertScreen : public AbstractScreen {
* @param duration how long the alert should persist on the screen
* @param rumble A string consisting of the characters '.', '-', and ' ', where dots are short rumbles,
* dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters.
*
* This function uses the following value(s) of errno when an error state is reached:
*
* EINVAL: The line number is not in the interval [0, 2]
*
* @return 0 if the alert was added successfully
* @return INT32_MAX if there was an error, setting errno
*
*/
void addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = "");
int32_t addAlerts(uint8_t line, std::string strs, uint32_t duration, std::string rumble = "");
private:
struct AlertBuffer {
ScreenBuffer screen;
Expand Down
11 changes: 9 additions & 2 deletions include/gamepad/screens/defaultScreen.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,23 @@ class DefaultScreen : public AbstractScreen {
*
* @param line the line number to print the string on (0-2)
* @param str the string to print onto the controller (\n to go to the next line)
*
* This function uses the following value(s) of errno when an error state is reached:
*
* EINVAL: The line number is not in the interval [0, 2]
*
* @return 0 if the alert was added successfully
* @return INT32_MAX if there was an error, setting errno
*/
void printLine(uint8_t line, std::string str);
int32_t printLine(uint8_t line, std::string str);

/**
* makes the controller rumble like pros
*
* @param rumble_pattern A string consisting of the characters '.', '-', and ' ', where dots are short rumbles,
* dashes are long rumbles, and spaces are pauses. Maximum supported length is 8 characters.
*/
void rumble(std::string rumble_pattern);
int32_t rumble(std::string rumble_pattern);
private:
ScreenBuffer m_current_buffer {};
pros::Mutex m_mutex {};
Expand Down
12 changes: 10 additions & 2 deletions include/gamepad/todo.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
#pragma once

#define DO_PRAGMA(x) _Pragma(#x)
#define TODO(x) DO_PRAGMA(message("TODO - " #x))
#define FIXME(x) DO_PRAGMA(warning("FIXME - " #x))

// We only define the TODO/FIXME macros if the file is being compiled by Microsoft Intellisense
// or clangd. This way, the TODO/FIXME messages don't clutter the compilation messages.
#if defined(_debug) || defined(__clang__)
#define TODO(x) DO_PRAGMA(message("TODO - " x))
#define FIXME(x) DO_PRAGMA(warning("FIXME - " x))
#else
#define TODO(x)
#define FIXME(x)
#endif
18 changes: 9 additions & 9 deletions src/gamepad/button.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,31 @@ void Button::setLongPressThreshold(uint32_t threshold) const { m_long_press_thre

void Button::setRepeatCooldown(uint32_t cooldown) const { m_repeat_cooldown = cooldown; }

bool Button::onPress(std::string listenerName, std::function<void(void)> func) const {
uint32_t Button::onPress(std::string listenerName, std::function<void(void)> func) const {
return m_on_press_event.addListener(std::move(listenerName) + "_user", std::move(func));
}

bool Button::onLongPress(std::string listenerName, std::function<void(void)> func) const {
uint32_t Button::onLongPress(std::string listenerName, std::function<void(void)> func) const {
return m_on_long_press_event.addListener(std::move(listenerName) + "_user", std::move(func));
}

bool Button::onRelease(std::string listenerName, std::function<void(void)> func) const {
uint32_t Button::onRelease(std::string listenerName, std::function<void(void)> func) const {
return m_on_release_event.addListener(std::move(listenerName) + "_user", std::move(func));
}

bool Button::onShortRelease(std::string listenerName, std::function<void(void)> func) const {
uint32_t Button::onShortRelease(std::string listenerName, std::function<void(void)> func) const {
return m_on_short_release_event.addListener(std::move(listenerName) + "_user", std::move(func));
}

bool Button::onLongRelease(std::string listenerName, std::function<void(void)> func) const {
uint32_t Button::onLongRelease(std::string listenerName, std::function<void(void)> func) const {
return m_on_long_release_event.addListener(std::move(listenerName) + "_user", std::move(func));
}

bool Button::onRepeatPress(std::string listenerName, std::function<void(void)> func) const {
uint32_t Button::onRepeatPress(std::string listenerName, std::function<void(void)> func) const {
return m_on_repeat_press_event.addListener(std::move(listenerName) + "_user", std::move(func));
}

bool Button::addListener(EventType event, std::string listenerName, std::function<void(void)> func) const {
uint32_t Button::addListener(EventType event, std::string listenerName, std::function<void(void)> func) const {
switch (event) {
case gamepad::EventType::ON_PRESS: return this->onPress(std::move(listenerName), std::move(func));
case gamepad::EventType::ON_LONG_PRESS: return this->onLongPress(std::move(listenerName), std::move(func));
Expand All @@ -44,11 +44,11 @@ bool Button::addListener(EventType event, std::string listenerName, std::functio
default:
TODO("add error logging")
errno = EINVAL;
return false;
return UINT32_MAX;
}
}

bool Button::removeListener(std::string listenerName) const {
uint32_t Button::removeListener(std::string listenerName) const {
return m_on_press_event.removeListener(listenerName + "_user") ||
m_on_long_press_event.removeListener(listenerName + "_user") ||
m_on_release_event.removeListener(listenerName + "_user") ||
Expand Down
16 changes: 5 additions & 11 deletions src/gamepad/gamepad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Gamepad::Gamepad(pros::controller_id_e_t id)
}

void Gamepad::updateButton(pros::controller_digital_e_t button_id) {
Button Gamepad::*button = Gamepad::buttonToPtr(button_id);
Button Gamepad::* button = Gamepad::buttonToPtr(button_id);
bool is_held = m_controller.get_digital(button_id);
(this->*button).update(is_held);
}
Expand Down Expand Up @@ -130,7 +130,7 @@ void Gamepad::addScreen(std::shared_ptr<AbstractScreen> screen) {
m_screens.emplace(m_screens.begin() + pos, screen);
}

void Gamepad::printLine(uint8_t line, std::string str) { m_default_screen->printLine(line, str); }
int32_t Gamepad::printLine(uint8_t line, std::string str) { return m_default_screen->printLine(line, str); }

void Gamepad::clear() { m_default_screen->printLine(0, " \n \n "); }

Expand All @@ -146,10 +146,7 @@ float Gamepad::operator[](pros::controller_analog_e_t axis) {
case pros::E_CONTROLLER_ANALOG_LEFT_Y: return this->LeftY;
case pros::E_CONTROLLER_ANALOG_RIGHT_X: return this->RightX;
case pros::E_CONTROLLER_ANALOG_RIGHT_Y: return this->RightY;
default:
TODO("add error logging")
errno = EINVAL;
return 0;
default: TODO("add error logging") return 0;
}
}

Expand All @@ -158,7 +155,7 @@ std::string Gamepad::uniqueName() {
return std::to_string(i++) + "_internal";
}

Button Gamepad::*Gamepad::buttonToPtr(pros::controller_digital_e_t button) {
Button Gamepad::* Gamepad::buttonToPtr(pros::controller_digital_e_t button) {
switch (button) {
case pros::E_CONTROLLER_DIGITAL_L1: return &Gamepad::m_L1;
case pros::E_CONTROLLER_DIGITAL_L2: return &Gamepad::m_L2;
Expand All @@ -172,10 +169,7 @@ Button Gamepad::*Gamepad::buttonToPtr(pros::controller_digital_e_t button) {
case pros::E_CONTROLLER_DIGITAL_B: return &Gamepad::m_B;
case pros::E_CONTROLLER_DIGITAL_Y: return &Gamepad::m_Y;
case pros::E_CONTROLLER_DIGITAL_A: return &Gamepad::m_A;
default:
TODO("add error logging")
errno = EINVAL;
return &Gamepad::Fake;
default: TODO("add error logging") return &Gamepad::Fake;
}
}
} // namespace gamepad
13 changes: 8 additions & 5 deletions src/gamepad/screens/alertScreen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ void AlertScreen::update(uint32_t delta_time) {
if (pros::millis() - m_line_set_time >= m_screen_contents->duration) m_screen_contents = std::nullopt;
}

void AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) {
TODO("change handling for off screen lines")
if (line > 2) std::exit(1);
int32_t AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, std::string rumble) {
if (line > 2) {
TODO("add error logging")
errno = EINVAL;
return INT32_MAX;
}

TODO("warn instead of throw error if there are too many lines")
if (std::ranges::count(str, '\n') > 2) std::exit(1);
if (std::ranges::count(str, '\n') > 2) { TODO("add warn logging") }

std::vector<std::string> strs(3, "");
std::stringstream ss(str);
Expand All @@ -56,6 +58,7 @@ void AlertScreen::addAlerts(uint8_t line, std::string str, uint32_t duration, st

std::lock_guard<pros::Mutex> guard(m_mutex);
m_screen_buffer.push_back({buffer, duration});
return 0;
}

} // namespace gamepad
Loading
Loading