Skip to content
Open
79 changes: 79 additions & 0 deletions include/pros/detail.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/**
* \file pros/detail.hpp
*
* Contains PROS internal functions used in port literal functions.
*
* This file should not be modified by users, since it gets replaced whenever
* a kernel upgrade occurs.
*
* Copyright (c) 2017-2024 Purdue University ACM SIGBots.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License v. 2.0. If a copy of the MPL was not distributed with this
* file You can obtain one at http://mozilla.org/MPL/2.0/.
*
*/
#ifndef _PROS_DETAIL_HPP_
#define _PROS_DETAIL_HPP_

#include <array>
#include <charconv>
#include <cstdint>

namespace pros::detail {
template <char ...Chars>
consteval uint8_t parse_port() {
const std::array chars{Chars...};
const char* str = chars.begin();
int base = 10;
uint8_t port_num{0};
Comment thread
ion098 marked this conversation as resolved.
if (chars.size() >= 2 && chars[0] == '0') {
str += 2;
// from_chars doesn't seem to handle hex/binary/octal prefixes,
// so we handle them ourselves
Comment on lines +32 to +33

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This sucks lmao, good catch though

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Turns out it does, I failed to read the docs lol. Fixed in bea9c44.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

oh thank god

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Turns out I failed to read the docs doubly lol: from_chars does indeed NOT auto detect base womp womp

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

lol? so what, we need to add back in the 0b and 0x detection? that sucks bruh

Comment thread
ion098 marked this conversation as resolved.
switch (chars[1]) {
case 'X': case 'x':
// hex literal
base = 16;
Comment on lines +36 to +37

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does std::from_chars handle both uppercase and lowercase hex literals?

break;
case 'B': case 'b':
// binary literal
base = 2;
break;
default:
// octal literal
str -= 1;
base = 8;
}
}
auto result = std::from_chars(str, chars.end(), port_num, base);
if (result.ptr != chars.end() || result.ec != std::errc{}) {
return 0;
}
return port_num;
}

template <char ...Chars>
consteval bool is_valid_port() {
auto port_num = parse_port<Chars...>();
return port_num >= 1 && port_num <= 21;
}
Comment thread
ion098 marked this conversation as resolved.

// Tests:
static_assert(is_valid_port<'1'>() == true, "Kernel test failed");
static_assert(is_valid_port<'0'>() == false, "Kernel test failed");
// 0x16 = 22
static_assert(is_valid_port<'0','x','1','6'>() == false, "Kernel test failed");
// 0x15 = 21
static_assert(is_valid_port<'0','x','1','5'>() == true, "Kernel test failed");
// 025 = 21
static_assert(is_valid_port<'0','2','5'>() == true, "Kernel test failed");
// 0b1 = 1
static_assert(is_valid_port<'0','b','1'>() == true, "Kernel test failed");
// 0x1 = 1
static_assert(is_valid_port<'0','x','1'>() == true, "Kernel test failed");
static_assert(is_valid_port<'2','2'>() == false, "Kernel test failed");

}

#endif // _PROS_DETAIL_HPP_
8 changes: 7 additions & 1 deletion include/pros/distance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

#include "pros/device.hpp"
#include "pros/distance.h"
#include "pros/detail.hpp"

namespace pros {
inline namespace v5 {
Expand Down Expand Up @@ -239,7 +240,12 @@ namespace literals {
* }
* \endcode
*/
const pros::Distance operator"" _dist(const unsigned long long int d);
template <char... Cs>
const pros::Distance operator"" _dist() {
static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!");
constexpr int num = pros::detail::parse_port<Cs...>();
return pros::Distance(num);
}
} // namespace literals
} // namespace v5
} // namespace pros
Expand Down
8 changes: 7 additions & 1 deletion include/pros/gps.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "pros/device.hpp"
#include "pros/gps.h"
#include "pros/detail.hpp"

namespace pros {
inline namespace v5 {
Expand Down Expand Up @@ -924,7 +925,12 @@ namespace literals {
* }
* \endcode
*/
const pros::Gps operator""_gps(const unsigned long long int g);
template <char... Cs>
const pros::Gps operator"" _gps() {
static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!");
constexpr int num = pros::detail::parse_port<Cs...>();
return pros::Gps(num);
}
} // namespace literals

/// @brief
Expand Down
8 changes: 7 additions & 1 deletion include/pros/imu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "pros/device.hpp"
#include "pros/imu.h"
#include "pros/detail.hpp"

namespace pros {
/**
Expand Down Expand Up @@ -1067,7 +1068,12 @@ namespace literals {
* }
* \endcode
*/
const pros::Imu operator"" _imu(const unsigned long long int i);
template <char... Cs>
const pros::Imu operator"" _imu() {
static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!");
constexpr int num = pros::detail::parse_port<Cs...>();
return pros::Imu(num);
}
} // namespace literals

using IMU = Imu;
Expand Down
16 changes: 14 additions & 2 deletions include/pros/motors.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "pros/abstract_motor.hpp"
#include "pros/device.hpp"
#include "pros/motors.h"
#include "pros/detail.hpp"
#include "rtos.hpp"

namespace pros {
Expand Down Expand Up @@ -2405,7 +2406,13 @@ namespace literals {
* }
* \endcode
*/
const pros::Motor operator"" _mtr(const unsigned long long int m);
template <char... Cs>
const pros::Motor operator"" _mtr() {
static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!");
constexpr int num = pros::detail::parse_port<Cs...>();
return pros::Motor(num);
}

/**
* Constructs a reversed Motor from a literal ending in _rmtr
*
Expand All @@ -2419,7 +2426,12 @@ const pros::Motor operator"" _mtr(const unsigned long long int m);
* }
* \endcode
*/
const pros::Motor operator"" _rmtr(const unsigned long long int m);
template <char... Cs>
const pros::Motor operator"" _rmtr() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I wonder if theres a single pros project in the whole world that uses _rmtr

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!");
constexpr int num = pros::detail::parse_port<Cs...>();
return pros::Motor(-num);
}
} // namespace literals
} // namespace v5
} // namespace pros
Expand Down
8 changes: 7 additions & 1 deletion include/pros/optical.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include "pros/device.hpp"
#include "pros/optical.h"
#include "pros/detail.hpp"

namespace pros {
inline namespace v5 {
Expand Down Expand Up @@ -431,7 +432,12 @@ namespace literals {
* }
* \endcode
*/
const pros::Optical operator"" _opt(const unsigned long long int o);
template <char... Cs>
const pros::Optical operator"" _opt() {
static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!");
constexpr int num = pros::detail::parse_port<Cs...>();
return pros::Optical(num);
}
} // namespace literals
} // namespace v5
} // namespace pros
Expand Down
25 changes: 24 additions & 1 deletion include/pros/rotation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include "pros/device.hpp"
#include "pros/rotation.h"
#include "pros/detail.hpp"

namespace pros {
inline namespace v5 {
Expand Down Expand Up @@ -369,6 +370,23 @@ class Rotation : public Device {
*/
friend std::ostream& operator<<(std::ostream& os, const pros::Rotation& rotation);

/**
* Returns a rotation sesnor that has the same port as the original, but reversed.
*
* This can only be used on a temporary object (such as a device literal).
*
* \b Example
* \code
* using namespace pros::literals;
*
* void opcontrol() {
* pros::Rotation rotation_sensor = -1_rot;
* printf("Reversed: %d \n", rotation_sensor.get_reversed());
* }
* \endcode
*/
Rotation operator-() && { return Rotation(-this->get_port()); }
Comment on lines +373 to +388

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why should this exist? can you not create negatives with the other user-defined literal operator? If you can, then this probably shouldnt exist

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Oh I see that its rvalue-this-qualified. still a little weird

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No, not for rotation sensors. Both 10_rrot and 10_rotr seem a bit confusing compared to -10_rot (negative port numbers also match how the ctors work)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If this is necessary for rotation, its surely necessary for motors too?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

hopefully its not necessary for either though lol

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

im just confused why this doesnt work with the user-defined literal directly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Because -10_rot is -(operator""_rot<'1','0'>()), not operator""_rot<'-','1','0'>()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Motors have _rmtr so its not needed for motors, although adding this to motors might be a good idea for consistency

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

oh i see. yeah that sucks lmao. i think this should be added to motors as well if it has to exist.


///@}
};

Expand All @@ -386,7 +404,12 @@ namespace literals {
* }
* \endcode
*/
const pros::Rotation operator"" _rot(const unsigned long long int r);
template <char... Cs>
const pros::Rotation operator"" _rot() {
static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!");
constexpr int num = pros::detail::parse_port<Cs...>();
return pros::Rotation(num);
}
} // namespace literals
} // namespace v5
} // namespace pros
Expand Down
7 changes: 6 additions & 1 deletion include/pros/serial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,12 @@ namespace literals {
* }
* \endcode
*/
const pros::Serial operator"" _ser(const unsigned long long int m);
template <char... Cs>
const pros::Serial operator"" _ser() {
static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!");
constexpr int num = pros::detail::parse_port<Cs...>();
return pros::Serial(num);
}
} // namespace literals
} // namespace pros
#endif // _PROS_SERIAL_HPP_
7 changes: 6 additions & 1 deletion include/pros/vision.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -781,7 +781,12 @@ namespace literals {
* }
* \endcode
*/
const pros::Vision operator"" _vis(const unsigned long long int m);
template<char... Cs>
const pros::Vision operator"" _vis() {
static_assert(pros::detail::is_valid_port<Cs...>(), "Invalid port number!");
constexpr int num = pros::detail::parse_port<Cs...>();
return pros::Vision(num);
}
} // namespace literals
} // namespace pros
#endif // _PROS_VISION_HPP_
5 changes: 0 additions & 5 deletions src/devices/vdml_distance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,5 @@ std::ostream& operator<<(std::ostream& os, pros::Distance& distance) {
return os;
}

namespace literals {
const pros::Distance operator"" _dist(const unsigned long long int d) {
return pros::Distance(d);
}
} // namespace literals
} // namespace v5
} // namespace pros
5 changes: 0 additions & 5 deletions src/devices/vdml_gps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,5 @@ pros::Gps pros::Gps::get_gps() {
return Gps(PROS_ERR_BYTE);
}

namespace literals {
const pros::Gps operator""_gps(const unsigned long long int g) {
return pros::Gps(g);
}
} // namespace literals
} // namespace v5
} // namespace pros
5 changes: 0 additions & 5 deletions src/devices/vdml_imu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,5 @@ std::ostream& operator<<(std::ostream& os, const pros::Imu& imu) {
return os;
}

namespace literals {
const pros::Imu operator"" _imu(const unsigned long long int i) {
return pros::Imu(i);
}
} // namespace literals
} // namespace v5
} // namespace pros
8 changes: 0 additions & 8 deletions src/devices/vdml_motors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,12 +551,4 @@ std::ostream& operator<<(std::ostream& os, pros::Motor& motor) {
}

} // namespace v5
namespace literals {
const pros::Motor operator"" _mtr(const unsigned long long int m) {
return pros::Motor(m);
}
const pros::Motor operator"" _rmtr(const unsigned long long int m) {
return pros::Motor(-m);
}
} // namespace literals
} // namespace pros
6 changes: 0 additions & 6 deletions src/devices/vdml_optical.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,5 @@ std::ostream& operator<<(std::ostream& os, pros::Optical& optical) {
return os;
}

namespace literals {
const pros::Optical operator"" _opt(const unsigned long long int o) {
return pros::Optical(o);
}
} //

} // namespace v5
} // namespace pros
6 changes: 0 additions & 6 deletions src/devices/vdml_rotation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,5 @@ std::ostream& operator<<(std::ostream& os, const pros::Rotation& rotation) {
return os;
}

namespace literals {
const pros::Rotation operator"" _rot(const unsigned long long int r) {
return pros::Rotation(r);
}
} // namespace literals

} // namespace v5
} // namespace pros
5 changes: 0 additions & 5 deletions src/devices/vdml_serial.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,4 @@ std::int32_t Serial::write(std::uint8_t* buffer, std::int32_t length) const {
return serial_write(_port, buffer, length);
}

namespace literals {
const pros::Serial operator"" _ser(const unsigned long long int m) {
return pros::Serial(m);
}
} // namespace literals
} // namespace pros
6 changes: 0 additions & 6 deletions src/devices/vdml_vision.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,4 @@ Vision Vision::get_vision() {
}

} // namespace v5
namespace literals {
const pros::Vision operator"" _vis(const unsigned long long int m) {
return Vision(m);
}

} // namespace literals
} // namespace pros