#ifndef MANAGED_STRING_H #define MANAGED_STRING_H #include "mbed.h" /** * Class definition for a ManagedString. * * Uses basic reference counting to implement a copy-assignable, immutable string. * This maps closely to the constructs found in many high level application languages, * such as Touch Develop. * * Written from first principles here, for several reasons: * 1) std::shared_ptr is not yet availiable on the ARMCC compiler * 2) to reduce memory footprint - we don't need many of the other features in the std library * 3) it makes an interestin case study for anyone interested in seeing how it works! */ class ManagedString { // Internally we record the string as a char *, but control access to this to proide immutability // and reference counting. char *data; int16_t *ref; int16_t len; public: /** * Constructor. * Create a managed string from a pointer to an 8-bit character buffer. * The buffer is copied to ensure sage memory management (the supplied * character buffer may be decalred on the stack for instance). * * @param str The character array on which to base the new ManagedString. * * Example: * @code * ManagedString s("abcdefg"); * @endcode */ ManagedString(const char *str); /** * Constructor. * Create a managed string from a given integer. * * @param value The integer from which to create the ManagedString * * Example: * @code * ManagedString s(20); * @endcode */ ManagedString(const int value); /** * Constructor. * Create a managed string from a given char. * * @param value The char from which to create the ManagedString * * Example: * @code * ManagedString s('a'); * @endcode */ ManagedString(const char value); /** * Constructor. * Create a managed string from a pointer to an 8-bit character buffer of a given length. * The buffer is copied to ensure sane memory management (the supplied * character buffer may be declared on the stack for instance). * * @param str The character array on which to base the new ManagedString. * @param length The length of the character array * * Example: * @code * ManagedString s("abcdefg",7); // this is generally used for substring... why not use a normal char * constructor? * @endcode */ ManagedString(const char *str, const int16_t length); /** * Copy constructor. * Makes a new ManagedString identical to the one supplied. * Shares the character buffer and reference count with the supplied ManagedString. * * @param s The ManagedString to copy. * * Example: * @code * ManagedString s("abcdefg"); * ManagedString p(s); * @endcode */ ManagedString(const ManagedString &s); /** * Default constructor. * * Create an empty ManagedString. * * Example: * @code * ManagedString s(); * @endcode */ ManagedString(); /** * Destructor. * * Free this ManagedString, and decrement the reference count to the * internal character buffer. If we're holding the last reference, * also free the character buffer and reference counter. */ ~ManagedString(); /** * Copy assign operation. * * Called when one ManagedString is assigned the value of another. * If the ManagedString being assigned is already refering to a character buffer, * decrement the reference count and free up the buffer as necessary. * Then, update our character buffer to refer to that of the supplied ManagedString, * and increase its reference count. * * @param s The ManagedString to copy. * * Example: * @code * ManagedString s("abcd"); * ManagedString p("efgh"); * p = s // p now points to s, s' ref is incremented * @endcode */ ManagedString& operator = (const ManagedString& s); /** * Equality operation. * * Called when one ManagedString is tested to be equal to another using the '==' operator. * * @param s The ManagedString to test ourselves against. * @return true if this ManagedString is identical to the one supplied, false otherwise. * * Example: * @code * ManagedString s("abcd"); * ManagedString p("efgh"); * * if(p==s) * print("We are the same!"); * else * print("We are different!"); //p is not equal to s - this will be called * @endcode */ bool operator== (const ManagedString& s); /** * Inequality operation. * * Called when one ManagedString is tested to be less than another using the '<' operator. * * @param s The ManagedString to test ourselves against. * @return true if this ManagedString is alphabetically less than to the one supplied, false otherwise. * * Example: * @code * ManagedString s("a"); * ManagedString p("b"); * * if(s' operator. * * @param s The ManagedString to test ourselves against. * @return true if this ManagedString is alphabetically greater than to the one supplied, false otherwise. * * Example: * @code * ManagedString s("a"); * ManagedString p("b"); * * if(p>a) * print("b is after a!"); //b is after a * else * print("a is after b!"); * @endcode */ bool operator> (const ManagedString& s); /** * Extracts a ManagedString from this string, at the position provided. * * @param start The index of the first character to extract, indexed from zero. * @param length The number of characters to extract from the start position * @return a ManagedString representing the requested substring. * * Example: * @code * ManagedString s("abcdefg"); * * print(s.substring(0,2)) // prints "ab" * @endcode */ ManagedString substring(int16_t start, int16_t length); /** * Concatenates this string with the one provided. * * @param s The ManagedString to concatenate. * @return a new ManagedString representing the joined strings. * * Example: * @code * ManagedString s("abcd"); * ManagedString p("efgh") * * print(s + p) // prints "abcdefgh" * @endcode */ ManagedString operator+ (ManagedString& s); /** * Provides a character value at a given position in the string, indexed from zero. * * @param index The position of the character to return. * @return the character at posisiton index, zero if index is invalid. * * Example: * @code * ManagedString s("abcd"); * * print(s.charAt(1)) // prints "b" * @endcode */ char charAt(int16_t index); /** * Provides an immutable 8 bit wide haracter buffer representing this string. * * @return a pointer to the character buffer. */ const char *toCharArray(); /** * Determines the length of this ManagedString in characters. * * @return the length of the string in characters. * * Example: * @code * ManagedString s("abcd"); * * print(s.length()) // prints "4" * @endcode */ int16_t length(); /** * Empty String constant */ static ManagedString EmptyString; private: /** * Internal constructor helper. * Configures this ManagedString to refer to the static EmptyString */ void initEmpty(); /** * Internal constructor helper. * creates this ManagedString based on a given null terminated char array. */ void initString(const char *str); /** * Private Constructor. * Create a managed string based on a concat of two strings. * The buffer is copied to ensure sane memory management (the supplied * character buffer may be decalred on the stack for instance). * * @param str1 The first string on which to base the new ManagedString * @param str2 The second string on which to base the new ManagedString */ ManagedString(const ManagedString &s1, const ManagedString &s2); }; #endif