From f27c3fbc7008351bd624f7bbb4d2132541ad89fa Mon Sep 17 00:00:00 2001 From: Martin Read Date: Sat, 5 Apr 2014 01:52:08 +0100 Subject: [PATCH] Added new string-handling file --- text.cc | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ text.hh | 39 ++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 text.cc create mode 100644 text.hh diff --git a/text.cc b/text.cc new file mode 100644 index 0000000..33c8939 --- /dev/null +++ b/text.cc @@ -0,0 +1,138 @@ +/* \file text.cc + * \brief Various text-processing functions + */ + +/* Copyright © 2014 Martin Read + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include "text.hh" + +// This module has no dependencies on the rest of the code and provides a +// unit test which needs a little more work for solidity. +#undef UNIT_TEST +//#define UNIT_TEST + +static inline void append_word_with_spaces(std::string& dest, std::string& spaces, std::string& word) +{ + dest += spaces; + dest += word; +} + +static inline void append_word_with_newline(std::string& dest, std::string& word) +{ + dest += '\n'; + dest += word; +} + +static inline size_t test_word_wrap_and_append(std::string& dest, std::string& spaces, std::string& word, size_t cur_col, size_t columns) +{ + if (spaces.size() + word.size() + cur_col >= columns) + { + append_word_with_newline(dest, word); + return word.size(); + } + else + { + append_word_with_spaces(dest, spaces, word); + return cur_col + word.size() + spaces.size(); + } +} + +#define CLEANUP() (word.clear(), spaces.clear()) +char *cstr_line_format(char const *input, size_t columns, size_t *output_len) +{ + /* Let our caller, rather than us, get the segfault. */ + if (input == nullptr) + { + return nullptr; + } + /* Sanity checks to avoid doing any real work if we don't have to */ + if (*input == '\0') + { + return strdup(""); + } + if (columns == 0) + { + return strdup(input); + } + /* OK. Do the work. */ + std::string output; + std::string word; + std::string spaces; + size_t cur_col = 0; + for (size_t inpos = 0; input[inpos]; ++inpos) + { + unsigned char uc = (unsigned char) input[inpos]; + switch (uc) + { + case '\n': + test_word_wrap_and_append(output, spaces, word, cur_col, columns); + output += '\n'; + cur_col = 0; + CLEANUP(); + break; + case ' ': + if (word.size() > 0) + { + cur_col = test_word_wrap_and_append(output, spaces, word, cur_col, columns); + CLEANUP(); + if (cur_col != 0) + { + spaces += ' '; + } + } + else + { + spaces += ' '; + } + break; + default: + word += (char) uc; + break; + } + } + return strdup(output.c_str()); +} + +#ifdef UNIT_TEST +int main(int argc, char *argv[]) +{ + char s[512]; + fgets(s, 512, stdin); + fputs(s, stdout); + fputs(cstr_line_format(s, 25, nullptr), stdout); + return 0; +} +#endif + +/* + * vim:ts=8:sts=4:sw=4:expandtab:cindent + */ +/* text.cc */ diff --git a/text.hh b/text.hh new file mode 100644 index 0000000..5567d16 --- /dev/null +++ b/text.hh @@ -0,0 +1,39 @@ +/* \file text.hh + * \brief Header for text-processing utility functions + */ + +/* Copyright 2014 Martin Read + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef TEXT_HH +#define TEXT_HH + +char *cstr_line_format(char const *input, size_t columns, size_t *output_len); + +#endif + +/* + * vim:ts=8:sts=4:sw=4:expandtab:cindent + */ +/* util.h */ -- 2.11.0