Added new string-handling file
authorMartin Read <mpread@chiark.greenend.org.uk>
Sat, 5 Apr 2014 00:52:08 +0000 (01:52 +0100)
committerMartin Read <mpread@chiark.greenend.org.uk>
Sat, 5 Apr 2014 00:52:08 +0000 (01:52 +0100)
text.cc [new file with mode: 0644]
text.hh [new file with mode: 0644]

diff --git a/text.cc b/text.cc
new file mode 100644 (file)
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 <string>
+#include <string.h>
+#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 (file)
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 */