Skip to content

Instantly share code, notes, and snippets.

@ancarda
Last active October 1, 2019 16:59
Show Gist options
  • Save ancarda/3787c17a3b3ba9236c62097f8315d6cc to your computer and use it in GitHub Desktop.
Save ancarda/3787c17a3b3ba9236c62097f8315d6cc to your computer and use it in GitHub Desktop.
/**
* This script implements a very simple string copy that is the same length
* or less bytes. The copied string only contains printable characters.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
// Duplicate the string src without any non-printable characters.
char* strcpy_pc(const char* src)
{
assert(src != NULL);
char* dst = NULL;
int src_offset = 0;
int dst_offset = 0;
// To clean the string, we'll first allocate all the required memory:
dst = malloc(sizeof(char) * strlen(src) + 1);
assert(dst != NULL);
// Next, loop over each character and if it's permitted, add it:
while (true)
{
// If we run over a null byte - copy it and exit.
if (src[src_offset] == 0)
{
dst[dst_offset] = 0;
// We can now resize to the memory that's needed.
dst = realloc(dst, sizeof(char) * (strlen(dst) + 1));
assert(dst != NULL);
return dst;
}
// Skip DEL byte (0x7F) and anything below 31 (0x1F).
if (src[src_offset] < 32 || src[src_offset] == 127)
{
src_offset++;
continue;
}
// For all remaining bytes, copy them.
dst[dst_offset] = src[src_offset];
dst_offset++;
src_offset++;
}
}
//
// Tests
//
#include "../picotest/lib/framework.h"
IT_SHOULD(do_nothing_with_an_empty_string, {
char* dst = strcpy_pc("");
ASSERT_STR_EQ("", dst);
})
IT_SHOULD(return_identical_string_with_no_printable_characters, {
char* src = "hello";
char* dst = strcpy_pc(src);
ASSERT_STR_EQ(src, dst);
})
IT_SHOULD(remove_non_printable_characters_at_the_end, {
char* src = "hello\x01";
char* dst = strcpy_pc(src);
ASSERT_STR_EQ("hello", dst);
})
IT_SHOULD(remove_non_printable_characters_anywhere_in_the_string, {
char* src = "h\ae\x01llo\x01";
char* dst = strcpy_pc(src);
ASSERT_STR_EQ("hello", dst);
})
int main()
{
BEGIN_TESTING;
RUN_TEST(do_nothing_with_an_empty_string);
RUN_TEST(return_identical_string_with_no_printable_characters);
RUN_TEST(remove_non_printable_characters_at_the_end);
RUN_TEST(remove_non_printable_characters_anywhere_in_the_string);
CONCLUDE_TESTING;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment