Skip to content

Instantly share code, notes, and snippets.

@platisd
Last active December 5, 2021 20:11
Show Gist options
  • Save platisd/b30f59fa0902dbda7a695bcef3f67300 to your computer and use it in GitHub Desktop.
Save platisd/b30f59fa0902dbda7a695bcef3f67300 to your computer and use it in GitHub Desktop.

You're given a DataHeader struct that represents a package comprised of two sets of bytes, a DataView that can be seen as a non-owning container of some data and a copyViewData function that copies the contents of a DataView to a buffer.

You also get a validateHeader function which determines whether a DataHeader is valid. Depending on the product variant, the function has different implementations but the signature always remains the same.

Your goal is to create a parseData function which receives two DataView objects, copies them into a DataHeader object and validates the DataHeader object. The DataView objects may be empty, which depending on the project can be fine. The validateHeader function will simply return false if the given header is not as expected.

Assuming no other constraints, which of the two parseData versions would you prefer and why?

struct DataView
{
std::uint8_t* data{ nullptr };
std::size_t size{ 0 };
};
struct DataHeader
{
std::array<std::uint8_t, kMaxHeaderSize> firstPart{};
std::array<std::uint8_t, kMaxHeaderSize> secondPart{};
};
bool copyViewData(DataView view, std::uint8_t* buffer, std::size_t buffer_size)
{
if (!view.data || buffer_size < view.size)
{
return false;
}
std::memcpy(buffer, view.data, view.size);
return true;
}
bool validateHeader(const DataHeader& header);
bool parseData1(DataView firstPart, DataView secondPart)
{
DataHeader header{};
const auto fistPartCopied
= copyViewData(firstPart, header.firstPart.data(), header.firstPart.size());
const auto secondPartCopied
= copyViewData(secondPart, header.secondPart.data(), header.secondPart.size());
const auto validHeader = validateHeader(header);
if (!validHeader)
{
std::cerr << "Failed to parse header" << std::endl;
std::cerr << "First part copied: " << fistPartCopied << std::endl;
std::cerr << "Second part copied: " << secondPartCopied << std::endl;
return false;
}
// Do stuff with the header
return true;
}
bool parseData2(std::optional<DataView> firstPart, std::optional<DataView> secondPart)
{
DataHeader header{};
if (firstPart)
{
const auto fistPartCopied
= copyViewData(firstPart.value(), header.firstPart.data(), header.firstPart.size());
if (!fistPartCopied)
{
std::cerr << "Failed to copy first part" << std::endl;
return false;
}
}
if (secondPart)
{
const auto secondPartCopied
= copyViewData(secondPart.value(), header.secondPart.data(), header.secondPart.size());
if (!secondPartCopied)
{
std::cerr << "Failed to copy second part" << std::endl;
return false;
}
}
const auto validHeader = validateHeader(header);
if (!validHeader)
{
std::cerr << "Failed to validate header" << std::endl;
return false;
}
// Do stuff with the header
return true;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment