diff options
| -rw-r--r-- | FL/Fl_String.H | 114 | ||||
| -rw-r--r-- | src/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/Fl_String.cxx | 159 | ||||
| -rw-r--r-- | src/Makefile | 1 |
4 files changed, 275 insertions, 0 deletions
diff --git a/FL/Fl_String.H b/FL/Fl_String.H new file mode 100644 index 000000000..471178cd6 --- /dev/null +++ b/FL/Fl_String.H @@ -0,0 +1,114 @@ +// +// Basic Fl_String header for the Fast Light Tool Kit (FLTK). +// +// Copyright 2021 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#ifndef _FL_FL_STRING_H_ +#define _FL_FL_STRING_H_ + +/** \file FL/Fl_String.H + Basic Fl_String class for FLTK. +*/ + +/** + Fl_String is the basic string class for FLTK. + + In this version Fl_String can be used to store strings, copy strings, + and move strings. There are no string manipulation methods yet. + + Fl_String can hold the value of an Fl_Input widget including \e nul bytes + if the constructor Fl_String(const char *str, int size) is used. + + Assignment and copy constructors \b copy the string value such that the + source string can be freed immediately after the assignment. + + The string value() can be an empty string \c "" or \c NULL. + + If value() is not \c NULL it is guaranteed that the string is terminated by + a trailing \c nul byte even if the string contains embedded \c nul bytes. + + The method size() returns the full string size, whether the string contains + embedded \c nul bytes or not. The special method slen() returns 0 if value() + is \c NULL, otherwise the same as \c strlen() would do. + + Examples: + \code + Fl_String np(NULL); + printf(" np : value = %p, size = %d, slen = %d\n", np.value(), np.size(), np.slen()); + Fl_String empty(""); + printf(" empty : value = %p, size = %d\n", empty.value(), empty.size()); + Fl_String fltk("FLTK"); + Fl_Input i(0, 0, 0, 0); + i.value("abc\0def", 7); + Fl_String str(i.value(), i.size()); + printf(" str : strlen = %lu, size = %d, capacity = %d\n", + strlen(str.value()), str.size(), str.capacity()); + + Output: + + np : value = (nil), size = 0, slen = 0 + empty : value = 0x562840befbf0, size = 0 + str : strlen = 3, size = 7, capacity = 15 + \endcode + + \since 1.4.0 + + \todo Complete documentation of class Fl_String +*/ + +class Fl_String { +private: + int size_; + char *value_; + int capacity_; + +public: + Fl_String(); + Fl_String(const char *str); + Fl_String(const char *str, int size); + + // copy constructor + Fl_String(const Fl_String &in); + + // copy assignment operator + Fl_String& operator=(const Fl_String &in); + + // assignment operator for 'const char *' + Fl_String& operator=(const char *in); + + virtual ~Fl_String(); + +private: + void init(); + void alloc_buf(int size); + void release(); + +public: + void value(const char *str); + void value(const char *str, int slen); + + const char *value() const { return value_; } + int size() const { return size_; } + + int slen() const; + int capacity() const; + + // ================================== DEBUG ================================== + + void debug(const char *info) const; // output string info + void hexdump(const char *info) const; // output info + hexdump + +}; // class Fl_String + +#endif // _FL_FL_STRING_H_ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3c00f0da9..aa74b6c7d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -78,6 +78,7 @@ set (CPPFILES Fl_Single_Window.cxx Fl_Slider.cxx Fl_Spinner.cxx + Fl_String.cxx Fl_Sys_Menu_Bar.cxx Fl_System_Driver.cxx Fl_Table.cxx diff --git a/src/Fl_String.cxx b/src/Fl_String.cxx new file mode 100644 index 000000000..c4417523c --- /dev/null +++ b/src/Fl_String.cxx @@ -0,0 +1,159 @@ +// +// Basic Fl_String class for the Fast Light Tool Kit (FLTK). +// +// Copyright 2021 by Bill Spitzak and others. +// +// This library is free software. Distribution and use rights are outlined in +// the file "COPYING" which should have been included with this file. If this +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +#include <FL/Fl_String.H> + +#include <stdio.h> +#include <string.h> + +/** \file src/Fl_String.cxx + Basic Fl_String class for FLTK. +*/ + +static int string_count; + +Fl_String::Fl_String() { + string_count++; + init(); + // debug("created ()"); +} + +Fl_String::Fl_String(const char *str) { + string_count++; + init(); + value(str); + // debug("created (str)"); +} + +Fl_String::Fl_String(const char *str, int size) { + string_count++; + init(); + value(str, size); + // debug("created (str, size)"); +} + +void Fl_String::init() { + size_ = 0; + value_ = 0; + capacity_ = 0; +} + +// copy constructor +Fl_String::Fl_String(const Fl_String &in) { + string_count++; + init(); + value(in.value(), in.size()); + // debug("copied (c'tor)"); +} + +// copy assignment operator +Fl_String& Fl_String::operator=(const Fl_String &in) { + if (this == &in) + return *this; + value(in.value(), in.size()); + // debug("copy assigned"); + return *this; +} + +// assignment operator for 'const char *' +Fl_String& Fl_String::operator=(const char *in) { + value(in); + // debug("*STRING* assigned"); + return *this; +} + +Fl_String::~Fl_String() { + string_count--; + // debug("~Fl_String()"); + delete[] value_; +} + +void Fl_String::alloc_buf(int size) { + if (size < 0) + return; + if (size > 0 && size <= capacity_) + return; + if (capacity_ > 0) + return; + + int new_size = (size + 1 + 15) & (~15); // round upwards + char *new_value = new char[new_size]; + capacity_ = new_size - 1; + + size_ = 0; + delete[] value_; + value_ = new_value; +} + +void Fl_String::value(const char *str) { + value(str, str ? strlen(str) : 0); +} + +int Fl_String::slen() const { + if (!value_) return 0; + return (int)strlen(value_); +} + +void Fl_String::value(const char *str, int len) { + if (str) { + alloc_buf(len); + size_ = len; + memcpy(value_, str, size_); + value_[size_] = '\0'; + } else { // str == NULL + size_ = 0; // ignore len ! + delete[] value_; // free buffer + value_ = NULL; // set null pointer (!) + capacity_ = 0; // reset capacity + } +} + +int Fl_String::capacity() const { + return capacity_; // > 0 ? capacity_ - 1 : capacity_; +} + +void Fl_String::release() { + delete[] value_; + value_ = 0; + size_ = 0; + capacity_ = 0; +} + +// ============================= DEBUG ============================= + +static const char fl_string_debug = 0; + +void Fl_String::debug(const char *info) const { + if (fl_string_debug) { + printf("Fl_String[%2d] '%-20s': %p, value = %p (%d/%d): '%s'.\n", + string_count, info, this, value_, size_, capacity_, value_); + } +} + +void Fl_String::hexdump(const char *info) const { + if (fl_string_debug) { + debug(info); + for (int i = 0; i < size_; i++) { + if ((i & 15) == 0) { + if (i > 0) printf("\n"); + printf(" [%04x %4d] ", i, i); + } else if ((i & 3) == 0) + printf(" "); + printf(" %02x", (unsigned char)value_[i]); + } + printf("\n"); + } +} diff --git a/src/Makefile b/src/Makefile index 0d27e8c61..a31788929 100644 --- a/src/Makefile +++ b/src/Makefile @@ -80,6 +80,7 @@ CPPFILES = \ Fl_Single_Window.cxx \ Fl_Slider.cxx \ Fl_Spinner.cxx \ + Fl_String.cxx \ Fl_Sys_Menu_Bar.cxx \ Fl_System_Driver.cxx \ Fl_Table.cxx \ |
