Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
pmuller committed Feb 1, 2024
1 parent 85a20a1 commit f2a453b
Show file tree
Hide file tree
Showing 5 changed files with 199 additions and 28 deletions.
69 changes: 69 additions & 0 deletions src/ArduinoNDEF/field/text_payload.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#include "text_payload.hpp"

namespace ArduinoNDEF
{
namespace Field
{

TextPayload *TextPayload::from_text(const char *text, const char *language_code)
{
if (text == nullptr || language_code == nullptr)
return nullptr;

uint32_t language_code_length = strlen(language_code);

if (language_code_length != 2 && language_code_length != 5)
return nullptr;
if (language_code_length == 5 && language_code[2] != '-')
return nullptr;

uint32_t header_length = 1 + language_code_length;
uint8_t header[header_length];
header[0] = language_code_length;
memcpy(header + 1, language_code, language_code_length);

uint32_t text_length = strlen(text);
uint32_t payload_length = header_length + text_length;

auto payload_data = new uint8_t[payload_length];
if (payload_data == nullptr)
return nullptr;

memcpy(payload_data, header, header_length);
memcpy(payload_data + header_length, text, text_length);

return new TextPayload(payload_data, payload_length);
}

const char *TextPayload::to_text() const
{
auto language_code_length = _data[0];
auto header_length = /* language_length */ 1 + /* language */ language_code_length;
auto text_length = _length - header_length;
auto text = new char[text_length + 1];

if (text == nullptr)
return nullptr;

memcpy(text, _data + header_length, text_length);
text[text_length] = '\0';

return text;
}

const char *TextPayload::to_language_code() const
{
auto language_code_length = _data[0];
auto language_code = new char[language_code_length + 1];

if (language_code == nullptr)
return nullptr;

memcpy(language_code, _data + 1, language_code_length);
language_code[language_code_length] = '\0';

return language_code;
}

} // namespace Field
} // namespace ArduinoNDEF
45 changes: 45 additions & 0 deletions src/ArduinoNDEF/field/text_payload.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include "payload.hpp"

namespace ArduinoNDEF
{
namespace Field
{

class TextPayload : public Payload
{
public:
/**
* @brief Create a NDEF text payload
* @param text The text
* @param language_code The language
* @return A pointer to a new NDEF text payload object
*/
static TextPayload *from_text(const char *text, const char *language_code);

/**
* @brief Get the text
* @return The text C-string
* @note Memory is allocated for the text string and it is the responsibility of the
* caller to free it
*/
const char *to_text() const;

/**
* @brief Get the language code
* @return The language code C-string
* @note Memory is allocated for the language code string and it is the
* responsibility of the caller to free it
*/
const char *to_language_code() const;

private:
TextPayload(const uint8_t *data, uint8_t length) :
Payload(data, length, OwnershipUnique)
{
}
};

} // namespace Field
} // namespace ArduinoNDEF
35 changes: 8 additions & 27 deletions src/ArduinoNDEF/record/text.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,18 @@ Text *Text::create(
const Field::Id &id
)
{
// 1. Prepare header
uint32_t language_code_length = strlen(language_code);

if (language_code_length != 2 && language_code_length != 5)
return nullptr;
if (language_code_length == 5 && language_code[2] != '-')
auto type_field = new Field::Type(Field::Type::RTD_TEXT);
if (type_field == nullptr)
return nullptr;

uint32_t header_length = 1 + language_code_length;
uint8_t header[header_length];
header[0] = language_code_length;
memcpy(header + 1, language_code, language_code_length);

// 2. Prepare payload
uint32_t text_length = strlen(text);
uint32_t payload_length = header_length + text_length;

auto payload_data = new uint8_t[payload_length];
if (payload_data == nullptr)
return nullptr;

memcpy(payload_data, header, header_length);
memcpy(payload_data + header_length, text, text_length);

auto type = new Field::Type(Field::Type::RTD_TEXT);
auto payload =
new Field::Payload(payload_data, payload_length, Field::Payload::OwnershipUnique);
if (type == nullptr || payload == nullptr)
auto payload_field = Field::TextPayload::from_text(text, language_code);
if (payload_field == nullptr)
{
delete type_field;
return nullptr;
}

return new Text(*type, *payload, is_message_begin, is_message_end, id);
return new Text(*type_field, *payload_field, is_message_begin, is_message_end, id);
}

Text *Text::create(const char *text, const char *language_code)
Expand Down
3 changes: 2 additions & 1 deletion src/ArduinoNDEF/record/text.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include "../field/text_payload.hpp"
#include "../record.hpp"

namespace ArduinoNDEF
Expand Down Expand Up @@ -65,7 +66,7 @@ class Text : public Record
private:
Text(
const Field::Type &type,
const Field::Payload &payload,
const Field::TextPayload &payload,
bool is_message_begin,
bool is_message_end,
const Field::Id &id
Expand Down
75 changes: 75 additions & 0 deletions tests/FieldTest/FieldTest.ino
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,81 @@ test(uri_payload__no_abbreviation)
delete payload;
}

test(text_payload__language_code_2_characters)
{
auto payload = ArduinoNDEF::Field::TextPayload::from_text("Hello, world!", "en");
assertEqual(payload->length(), static_cast<uint32_t>(16));
assertEqual(payload->data()[0], 0x02);
assertEqual(payload->data()[1], static_cast<uint8_t>('e'));
assertEqual(payload->data()[2], static_cast<uint8_t>('n'));
assertEqual(payload->data()[3], static_cast<uint8_t>('H'));
assertEqual(payload->data()[4], static_cast<uint8_t>('e'));
assertEqual(payload->data()[5], static_cast<uint8_t>('l'));
assertEqual(payload->data()[6], static_cast<uint8_t>('l'));
assertEqual(payload->data()[7], static_cast<uint8_t>('o'));
assertEqual(payload->data()[8], static_cast<uint8_t>(','));
assertEqual(payload->data()[9], static_cast<uint8_t>(' '));
assertEqual(payload->data()[10], static_cast<uint8_t>('w'));
assertEqual(payload->data()[11], static_cast<uint8_t>('o'));
assertEqual(payload->data()[12], static_cast<uint8_t>('r'));
assertEqual(payload->data()[13], static_cast<uint8_t>('l'));
assertEqual(payload->data()[14], static_cast<uint8_t>('d'));
assertEqual(payload->data()[15], static_cast<uint8_t>('!'));
auto text = payload->to_text();
assertEqual(text, "Hello, world!");
delete[] text;
auto language_code = payload->to_language_code();
assertEqual(language_code, "en");
delete[] language_code;
delete payload;
}

test(text_payload__language_code_5_characters)
{
auto payload = ArduinoNDEF::Field::TextPayload::from_text("Hello, world!", "en-US");
assertEqual(payload->length(), static_cast<uint32_t>(19));
assertEqual(payload->data()[0], 0x05);
assertEqual(payload->data()[1], static_cast<uint8_t>('e'));
assertEqual(payload->data()[2], static_cast<uint8_t>('n'));
assertEqual(payload->data()[3], static_cast<uint8_t>('-'));
assertEqual(payload->data()[4], static_cast<uint8_t>('U'));
assertEqual(payload->data()[5], static_cast<uint8_t>('S'));
assertEqual(payload->data()[6], static_cast<uint8_t>('H'));
assertEqual(payload->data()[7], static_cast<uint8_t>('e'));
assertEqual(payload->data()[8], static_cast<uint8_t>('l'));
assertEqual(payload->data()[9], static_cast<uint8_t>('l'));
assertEqual(payload->data()[10], static_cast<uint8_t>('o'));
assertEqual(payload->data()[11], static_cast<uint8_t>(','));
assertEqual(payload->data()[12], static_cast<uint8_t>(' '));
assertEqual(payload->data()[13], static_cast<uint8_t>('w'));
assertEqual(payload->data()[14], static_cast<uint8_t>('o'));
assertEqual(payload->data()[15], static_cast<uint8_t>('r'));
assertEqual(payload->data()[16], static_cast<uint8_t>('l'));
assertEqual(payload->data()[17], static_cast<uint8_t>('d'));
assertEqual(payload->data()[18], static_cast<uint8_t>('!'));
auto text = payload->to_text();
assertEqual(text, "Hello, world!");
delete[] text;
auto language_code = payload->to_language_code();
assertEqual(language_code, "en-US");
delete[] language_code;
delete payload;
}

test(text_payload__errors)
{
assertEqual(
ArduinoNDEF::Field::TextPayload::from_text("Hello", "invalid language code"),
nullptr
);
assertEqual(ArduinoNDEF::Field::TextPayload::from_text("Hello", "abcde"), nullptr);
assertEqual(ArduinoNDEF::Field::TextPayload::from_text(nullptr, "en"), nullptr);
assertEqual(
ArduinoNDEF::Field::TextPayload::from_text("Hello, world!", nullptr),
nullptr
);
}

void setup()
{
#if !defined(EPOXY_DUINO)
Expand Down

0 comments on commit f2a453b

Please sign in to comment.