Skip to content

Commit

Permalink
Fixed compilation on AVR boards
Browse files Browse the repository at this point in the history
Turns out AVR/Arduino doesn't necessarily have a complete c++ library. Which includes std::forward, so here I include a custom implementation in the hopes that this library will _just work_.

I was tempted by the idea of using the standard library implementation of std::forward if it were defined, but without the type traits library, I'm not sure it's possible, so instead this implementation gets used for everything (even if std::forward exists)
  • Loading branch information
DanForever committed Aug 14, 2022
1 parent 01e611d commit 128c77e
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 10 deletions.
11 changes: 5 additions & 6 deletions src/DF-Print.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,8 @@
# define DEBUG_PRINTLN(format, ...)
#endif

#include <cstring>

#include "DF-PrintInternal.h"
#include "DF-StdUtility.h"

namespace DF
{
Expand All @@ -59,8 +58,8 @@ namespace DF
{
size_t charactersPrinted = 0;

charactersPrinted += Internal::PrintTextWithArgument(format, std::forward<Arg>(arg));
charactersPrinted += Print(format, std::forward<Args>(args)...);
charactersPrinted += Internal::PrintTextWithArgument(format, DF::forward<Arg>(arg));
charactersPrinted += Print(format, DF::forward<Args>(args)...);

return charactersPrinted;
}
Expand All @@ -70,7 +69,7 @@ namespace DF
{
size_t charactersPrinted = 0;

charactersPrinted += Print(format, std::forward<Args>(args)...);
charactersPrinted += Print(format, DF::forward<Args>(args)...);

return charactersPrinted;
}
Expand All @@ -80,7 +79,7 @@ namespace DF
{
size_t charactersPrinted = 0;

charactersPrinted += Print(format, std::forward<Args>(args)...);
charactersPrinted += Print(format, DF::forward<Args>(args)...);
charactersPrinted += Serial.println("");
// Alternatively, could do Serial.write("\r\n"); - more efficient? Is it worth making that string be read from PROGMEM?

Expand Down
13 changes: 9 additions & 4 deletions src/DF-PrintInternal.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@

#include <Arduino.h>

// Some Arduino platform implementations do not comprehensively cover the C++ standard, so we need to use string.h instead of cstring
#include <string.h>

#include "DF-StdUtility.h"

namespace DF
{
namespace Internal
Expand All @@ -35,7 +40,7 @@ namespace DF
// Format is modified to remove the text that was printed
inline size_t PrintTextBeforeFirstArgumentSpecifier(const char*& format)
{
const char* argStart = std::strchr(format, '{');
const char* argStart = strchr(format, '{');

if (!argStart)
{
Expand All @@ -55,12 +60,12 @@ namespace DF
template <typename Arg>
inline size_t PrintArgumentInPlaceOfSpecifier(const char*& format, Arg&& arg)
{
const char* argEnd = std::strchr(format, '}');
const char* argEnd = strchr(format, '}');

if (argEnd)
format = argEnd + 1;

return Serial.print(std::forward<Arg>(arg));
return Serial.print(DF::forward<Arg>(arg));
}

// This will print All the text before an argument specifier (e.g. {0}),
Expand All @@ -79,7 +84,7 @@ namespace DF
size_t charactersPrinted = 0;

charactersPrinted += PrintTextBeforeFirstArgumentSpecifier(format);
charactersPrinted += PrintArgumentInPlaceOfSpecifier(format, std::forward<Arg>(arg));
charactersPrinted += PrintArgumentInPlaceOfSpecifier(format, DF::forward<Arg>(arg));
charactersPrinted += PrintTextBeforeFirstArgumentSpecifier(format);

return charactersPrinted;
Expand Down
64 changes: 64 additions & 0 deletions src/DF-StdUtility.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* MIT License
* Copyright (c) 2022 Daniel Neve
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/

#ifndef __DF_STD_UTILITY_INTERNAL_H__
#define __DF_STD_UTILITY_INTERNAL_H__

// This exists because not every arduino platform implements std::forward
namespace DF
{
template <typename T>
struct remove_reference
{
using type = T;
};

template <typename T>
struct remove_reference<T&>
{
using type = T;
};

template <typename T>
struct remove_reference<T&&>
{
using type = T;
};

template <typename T>
using remove_reference_t = typename remove_reference<T>::type;

template <typename T>
constexpr T&& forward(remove_reference_t<T>& arg) noexcept
{
return static_cast<T&&>(arg);
}

template <typename T>
constexpr T&& forward(remove_reference_t<T>&& arg) noexcept
{
return static_cast<T&&>(arg);
}
}

#endif // __DF_STD_UTILITY_INTERNAL_H__

0 comments on commit 128c77e

Please sign in to comment.