#include <stddef.h>
#include <stdio.h>
///
/// @brief Appends contents of array `from` to array `to`.
/// @pre `limit` != `0`
/// @note No operation is performed for a `limit` of `0`.
/// @remarks Resulting array is NUL-terminated.
/// @param [out] to String to be written to.
/// @param limit Maximum number of bytes that string `to` can store, including NUL.
/// @param [in] from String to be copied from.
/// @returns Size of resulting string (NUL not counted).
///
size_t strscat(char *to, size_t limit, const char *from)
{
size_t s=0;
if (limit != 0)
{
while (to[s] != '\0')
++s;
for (size_t i=0; from[i] != '\0' && s < limit - 1; ++i, ++s)
to[s] = from[i];
to[s] = '\0';
}
return s;
}
typedef struct
{
char *to;
size_t limit;
const char *from;
const char *result;
size_t retval;
} test_t;
static size_t tests_failed;
static void run_test(test_t *t)
{
size_t i=0;
if (t->retval != strscat(t->to, t->limit, t->from))
{
++tests_failed;
return;
}
while (t->result[i] != '\0' || t->to[i] != '\0')
if (t->result[i] != t->to[i])
{
++tests_failed;
break;
}
else
++i;
}
#define RUN_TEST(...) run_test(&(test_t){__VA_ARGS__})
int main(void)
{
RUN_TEST(
.to = (char[15]){"The Cutty"},
.limit = 15,
.from = " Sark is a ship dry-docked in London.",
.result = "The Cutty Sark",
.retval = 14
);
RUN_TEST(
.to = (char[15]){"The Cutty"},
.limit = 0,
.from = "this won't get appended",
.result = "The Cutty",
.retval = 0
);
RUN_TEST(
.to = (char[15]){"The Cutty"},
.limit = 15,
.from = "!",
.result = "The Cutty!",
.retval = 10
);
RUN_TEST(
.to = (char[]){"The Cutty Sark"},
.limit = 3,
.from = "this shouldn't get appended",
.result = "The Cutty Sark",
.retval = 14
);
RUN_TEST(
.to = (char[]){"The Cutty Sark"},
.limit = 1,
.from = "this shouldn't get appended, either",
.result = "The Cutty Sark",
.retval = 14
);
RUN_TEST(
.to = (char[]){""},
.limit = 1,
.from = "this had better not get appended!",
.result = "",
.retval = 0
);
(void)fprintf(stderr
, "Number of tests failed: %zu.\n", tests_failed
); }
I2luY2x1ZGUgPHN0ZGRlZi5oPgojaW5jbHVkZSA8c3RkaW8uaD4KCi8vLwovLy8gQGJyaWVmIEFwcGVuZHMgY29udGVudHMgb2YgYXJyYXkgYGZyb21gIHRvIGFycmF5IGB0b2AuCi8vLyBAcHJlIGBsaW1pdGAgIT0gYDBgCi8vLyBAbm90ZSBObyBvcGVyYXRpb24gaXMgcGVyZm9ybWVkIGZvciBhIGBsaW1pdGAgb2YgYDBgLgovLy8gQHJlbWFya3MgUmVzdWx0aW5nIGFycmF5IGlzIE5VTC10ZXJtaW5hdGVkLgovLy8gQHBhcmFtIFtvdXRdIHRvICAgICAgU3RyaW5nIHRvIGJlIHdyaXR0ZW4gdG8uCi8vLyBAcGFyYW0gbGltaXQgICAgICAgICBNYXhpbXVtIG51bWJlciBvZiBieXRlcyB0aGF0IHN0cmluZyBgdG9gIGNhbiBzdG9yZSwgaW5jbHVkaW5nIE5VTC4KLy8vIEBwYXJhbSBbaW5dIGZyb20gICAgIFN0cmluZyB0byBiZSBjb3BpZWQgZnJvbS4KLy8vIEByZXR1cm5zIFNpemUgb2YgcmVzdWx0aW5nIHN0cmluZyAoTlVMIG5vdCBjb3VudGVkKS4KLy8vCnNpemVfdCBzdHJzY2F0KGNoYXIgKnRvLCBzaXplX3QgbGltaXQsIGNvbnN0IGNoYXIgKmZyb20pCnsKICAgIHNpemVfdCBzPTA7CgogICAgaWYgKGxpbWl0ICE9IDApCiAgICB7CiAgICAgICAgd2hpbGUgKHRvW3NdICE9ICdcMCcpCiAgICAgICAgICAgICsrczsKCiAgICAgICAgZm9yIChzaXplX3QgaT0wOyBmcm9tW2ldICE9ICdcMCcgJiYgcyA8IGxpbWl0IC0gMTsgKytpLCArK3MpCiAgICAgICAgICAgIHRvW3NdID0gZnJvbVtpXTsKCiAgICAgICAgdG9bc10gPSAnXDAnOwogICAgfQoKICAgIHJldHVybiBzOwp9Cgp0eXBlZGVmIHN0cnVjdAp7CiAgICBjaGFyICAgICAgICAqdG87CiAgICBzaXplX3QgICAgICBsaW1pdDsKICAgIGNvbnN0IGNoYXIgICpmcm9tOwogICAgY29uc3QgY2hhciAgKnJlc3VsdDsKICAgIHNpemVfdCAgICAgIHJldHZhbDsKfSB0ZXN0X3Q7CgpzdGF0aWMgc2l6ZV90IHRlc3RzX2ZhaWxlZDsKCnN0YXRpYyB2b2lkIHJ1bl90ZXN0KHRlc3RfdCAqdCkKewogICAgc2l6ZV90IGk9MDsKCiAgICBpZiAodC0+cmV0dmFsICE9IHN0cnNjYXQodC0+dG8sIHQtPmxpbWl0LCB0LT5mcm9tKSkKICAgIHsKICAgICAgICArK3Rlc3RzX2ZhaWxlZDsKICAgICAgICByZXR1cm47CiAgICB9CgogICAgd2hpbGUgKHQtPnJlc3VsdFtpXSAhPSAnXDAnIHx8IHQtPnRvW2ldICE9ICdcMCcpCiAgICAgICAgaWYgKHQtPnJlc3VsdFtpXSAhPSB0LT50b1tpXSkKICAgICAgICB7CiAgICAgICAgICAgICsrdGVzdHNfZmFpbGVkOwogICAgICAgICAgICBicmVhazsKICAgICAgICB9CiAgICAgICAgZWxzZQogICAgICAgICAgICArK2k7Cn0KCiNkZWZpbmUgUlVOX1RFU1QoLi4uKSAgIHJ1bl90ZXN0KCYodGVzdF90KXtfX1ZBX0FSR1NfX30pCgppbnQgbWFpbih2b2lkKQp7CiAgICBSVU5fVEVTVCgKICAgICAgICAudG8gICAgID0gKGNoYXJbMTVdKXsiVGhlIEN1dHR5In0sCiAgICAgICAgLmxpbWl0ICA9IDE1LAogICAgICAgIC5mcm9tICAgPSAiIFNhcmsgaXMgYSBzaGlwIGRyeS1kb2NrZWQgaW4gTG9uZG9uLiIsCiAgICAgICAgLnJlc3VsdCA9ICJUaGUgQ3V0dHkgU2FyayIsCiAgICAgICAgLnJldHZhbCA9IDE0CiAgICApOwoKICAgIFJVTl9URVNUKAogICAgICAgIC50byAgICAgPSAoY2hhclsxNV0peyJUaGUgQ3V0dHkifSwKICAgICAgICAubGltaXQgID0gMCwKICAgICAgICAuZnJvbSAgID0gInRoaXMgd29uJ3QgZ2V0IGFwcGVuZGVkIiwKICAgICAgICAucmVzdWx0ID0gIlRoZSBDdXR0eSIsCiAgICAgICAgLnJldHZhbCA9IDAKICAgICk7CgogICAgUlVOX1RFU1QoCiAgICAgICAgLnRvICAgICA9IChjaGFyWzE1XSl7IlRoZSBDdXR0eSJ9LAogICAgICAgIC5saW1pdCAgPSAxNSwKICAgICAgICAuZnJvbSAgID0gIiEiLAogICAgICAgIC5yZXN1bHQgPSAiVGhlIEN1dHR5ISIsCiAgICAgICAgLnJldHZhbCA9IDEwCiAgICApOwoKICAgIFJVTl9URVNUKAogICAgICAgIC50byAgICAgPSAoY2hhcltdKXsiVGhlIEN1dHR5IFNhcmsifSwKICAgICAgICAubGltaXQgID0gMywKICAgICAgICAuZnJvbSAgID0gInRoaXMgc2hvdWxkbid0IGdldCBhcHBlbmRlZCIsCiAgICAgICAgLnJlc3VsdCA9ICJUaGUgQ3V0dHkgU2FyayIsCiAgICAgICAgLnJldHZhbCA9IDE0CiAgICApOwoKICAgIFJVTl9URVNUKAogICAgICAgIC50byAgICAgPSAoY2hhcltdKXsiVGhlIEN1dHR5IFNhcmsifSwKICAgICAgICAubGltaXQgID0gMSwKICAgICAgICAuZnJvbSAgID0gInRoaXMgc2hvdWxkbid0IGdldCBhcHBlbmRlZCwgZWl0aGVyIiwKICAgICAgICAucmVzdWx0ID0gIlRoZSBDdXR0eSBTYXJrIiwKICAgICAgICAucmV0dmFsID0gMTQKICAgICk7CgogICAgUlVOX1RFU1QoCiAgICAgICAgLnRvICAgICA9IChjaGFyW10peyIifSwKICAgICAgICAubGltaXQgID0gMSwKICAgICAgICAuZnJvbSAgID0gInRoaXMgaGFkIGJldHRlciBub3QgZ2V0IGFwcGVuZGVkISIsCiAgICAgICAgLnJlc3VsdCA9ICIiLAogICAgICAgIC5yZXR2YWwgPSAwCiAgICApOwoKICAgICh2b2lkKWZwcmludGYoc3RkZXJyLCAiTnVtYmVyIG9mIHRlc3RzIGZhaWxlZDogJXp1LlxuIiwgdGVzdHNfZmFpbGVkKTsKfQ==