sen data via radio to other microbits accept command via radio bufixes
Dependencies: BLE_API nRF51822 mbed-dev-bin
source/types/ManagedString.cpp@52:3db7b4d64316, 2016-07-13 (annotated)
- Committer:
- LancasterUniversity
- Date:
- Wed Jul 13 12:18:31 2016 +0100
- Revision:
- 52:3db7b4d64316
- Parent:
- 51:9198e7bb83dc
- Child:
- 69:b62f231e51ce
Synchronized with git rev 8468823e
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Jonathan Austin |
1:8aa5cdb4ab67 | 1 | /* |
Jonathan Austin |
1:8aa5cdb4ab67 | 2 | The MIT License (MIT) |
Jonathan Austin |
1:8aa5cdb4ab67 | 3 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 4 | Copyright (c) 2016 British Broadcasting Corporation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 5 | This software is provided by Lancaster University by arrangement with the BBC. |
Jonathan Austin |
1:8aa5cdb4ab67 | 6 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 7 | Permission is hereby granted, free of charge, to any person obtaining a |
Jonathan Austin |
1:8aa5cdb4ab67 | 8 | copy of this software and associated documentation files (the "Software"), |
Jonathan Austin |
1:8aa5cdb4ab67 | 9 | to deal in the Software without restriction, including without limitation |
Jonathan Austin |
1:8aa5cdb4ab67 | 10 | the rights to use, copy, modify, merge, publish, distribute, sublicense, |
Jonathan Austin |
1:8aa5cdb4ab67 | 11 | and/or sell copies of the Software, and to permit persons to whom the |
Jonathan Austin |
1:8aa5cdb4ab67 | 12 | Software is furnished to do so, subject to the following conditions: |
Jonathan Austin |
1:8aa5cdb4ab67 | 13 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 14 | The above copyright notice and this permission notice shall be included in |
Jonathan Austin |
1:8aa5cdb4ab67 | 15 | all copies or substantial portions of the Software. |
Jonathan Austin |
1:8aa5cdb4ab67 | 16 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
Jonathan Austin |
1:8aa5cdb4ab67 | 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
Jonathan Austin |
1:8aa5cdb4ab67 | 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
Jonathan Austin |
1:8aa5cdb4ab67 | 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
Jonathan Austin |
1:8aa5cdb4ab67 | 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
Jonathan Austin |
1:8aa5cdb4ab67 | 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
Jonathan Austin |
1:8aa5cdb4ab67 | 23 | DEALINGS IN THE SOFTWARE. |
Jonathan Austin |
1:8aa5cdb4ab67 | 24 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 25 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 26 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 27 | * Class definition for a ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 28 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 29 | * Uses basic reference counting to implement a copy-assignable, immutable string. |
Jonathan Austin |
1:8aa5cdb4ab67 | 30 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 31 | * This maps closely to the constructs found in many high level application languages, |
Jonathan Austin |
1:8aa5cdb4ab67 | 32 | * such as Touch Develop. |
Jonathan Austin |
1:8aa5cdb4ab67 | 33 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 34 | * Written from first principles here, for several reasons: |
Jonathan Austin |
1:8aa5cdb4ab67 | 35 | * 1) std::shared_ptr is not yet availiable on the ARMCC compiler |
Jonathan Austin |
1:8aa5cdb4ab67 | 36 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 37 | * 2) to reduce memory footprint - we don't need many of the other features in the std library |
Jonathan Austin |
1:8aa5cdb4ab67 | 38 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 39 | * 3) it makes an interesting case study for anyone interested in seeing how it works! |
Jonathan Austin |
1:8aa5cdb4ab67 | 40 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 41 | * 4) we need explicit reference counting to inter-op with low-level application langauge runtimes. |
Jonathan Austin |
1:8aa5cdb4ab67 | 42 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 43 | * 5) the reference counting needs to also work for read-only, flash-resident strings |
Jonathan Austin |
1:8aa5cdb4ab67 | 44 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 45 | #include <string.h> |
Jonathan Austin |
1:8aa5cdb4ab67 | 46 | #include <stdlib.h> |
Jonathan Austin |
1:8aa5cdb4ab67 | 47 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 48 | #include "mbed.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 49 | #include "MicroBitConfig.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 50 | #include "ManagedString.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 51 | #include "MicroBitCompat.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 52 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 53 | static const char empty[] __attribute__ ((aligned (4))) = "\xff\xff\0\0\0"; |
Jonathan Austin |
1:8aa5cdb4ab67 | 54 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 55 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 56 | * Internal constructor helper. |
Jonathan Austin |
1:8aa5cdb4ab67 | 57 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 58 | * Configures this ManagedString to refer to the static EmptyString |
Jonathan Austin |
1:8aa5cdb4ab67 | 59 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 60 | void ManagedString::initEmpty() |
Jonathan Austin |
1:8aa5cdb4ab67 | 61 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 62 | ptr = (StringData*)(void*)empty; |
Jonathan Austin |
1:8aa5cdb4ab67 | 63 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 64 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 65 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 66 | * Internal constructor helper. |
Jonathan Austin |
1:8aa5cdb4ab67 | 67 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 68 | * Creates this ManagedString based on a given null terminated char array. |
Jonathan Austin |
1:8aa5cdb4ab67 | 69 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 70 | void ManagedString::initString(const char *str) |
Jonathan Austin |
1:8aa5cdb4ab67 | 71 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 72 | // Initialise this ManagedString as a new string, using the data provided. |
Jonathan Austin |
1:8aa5cdb4ab67 | 73 | // We assume the string is sane, and null terminated. |
Jonathan Austin |
1:8aa5cdb4ab67 | 74 | int len = strlen(str); |
Jonathan Austin |
1:8aa5cdb4ab67 | 75 | ptr = (StringData *) malloc(4+len+1); |
Jonathan Austin |
1:8aa5cdb4ab67 | 76 | ptr->init(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 77 | ptr->len = len; |
Jonathan Austin |
1:8aa5cdb4ab67 | 78 | memcpy(ptr->data, str, len+1); |
Jonathan Austin |
1:8aa5cdb4ab67 | 79 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 80 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 81 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 82 | * Constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 83 | * Create a managed string from a specially prepared string literal. |
Jonathan Austin |
1:8aa5cdb4ab67 | 84 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 85 | * @param ptr The literal - first two bytes should be 0xff, then the length in little endian, then the literal. The literal has to be 4-byte aligned. |
Jonathan Austin |
1:8aa5cdb4ab67 | 86 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 87 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 88 | * static const char hello[] __attribute__ ((aligned (4))) = "\xff\xff\x05\x00" "Hello"; |
Jonathan Austin |
1:8aa5cdb4ab67 | 89 | * ManagedString s((StringData*)(void*)hello); |
Jonathan Austin |
1:8aa5cdb4ab67 | 90 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 91 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 92 | ManagedString::ManagedString(StringData *p) |
Jonathan Austin |
1:8aa5cdb4ab67 | 93 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 94 | ptr = p; |
Jonathan Austin |
1:8aa5cdb4ab67 | 95 | ptr->incr(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 96 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 97 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 98 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 99 | * Get current ptr, do not decr() it, and set the current instance to empty string. |
Jonathan Austin |
1:8aa5cdb4ab67 | 100 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 101 | * This is to be used by specialized runtimes which pass StringData around. |
Jonathan Austin |
1:8aa5cdb4ab67 | 102 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 103 | StringData* ManagedString::leakData() |
Jonathan Austin |
1:8aa5cdb4ab67 | 104 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 105 | StringData *res = ptr; |
Jonathan Austin |
1:8aa5cdb4ab67 | 106 | initEmpty(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 107 | return res; |
Jonathan Austin |
1:8aa5cdb4ab67 | 108 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 109 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 110 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 111 | * Constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 112 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 113 | * Create a managed string from a given integer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 114 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 115 | * @param value The integer from which to create the ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 116 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 117 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 118 | * ManagedString s(20); |
Jonathan Austin |
1:8aa5cdb4ab67 | 119 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 120 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 121 | ManagedString::ManagedString(const int value) |
Jonathan Austin |
1:8aa5cdb4ab67 | 122 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 123 | char str[12]; |
Jonathan Austin |
1:8aa5cdb4ab67 | 124 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 125 | itoa(value, str); |
Jonathan Austin |
1:8aa5cdb4ab67 | 126 | initString(str); |
Jonathan Austin |
1:8aa5cdb4ab67 | 127 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 128 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 129 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 130 | * Constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 131 | * Create a managed string from a given char. |
Jonathan Austin |
1:8aa5cdb4ab67 | 132 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 133 | * @param value The character from which to create the ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 134 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 135 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 136 | * ManagedString s('a'); |
Jonathan Austin |
1:8aa5cdb4ab67 | 137 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 138 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 139 | ManagedString::ManagedString(const char value) |
Jonathan Austin |
1:8aa5cdb4ab67 | 140 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 141 | char str[2] = {value, 0}; |
Jonathan Austin |
1:8aa5cdb4ab67 | 142 | initString(str); |
Jonathan Austin |
1:8aa5cdb4ab67 | 143 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 144 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 145 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 146 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 147 | * Constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 148 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 149 | * Create a managed string from a pointer to an 8-bit character buffer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 150 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 151 | * The buffer is copied to ensure safe memory management (the supplied |
Jonathan Austin |
1:8aa5cdb4ab67 | 152 | * character buffer may be declared on the stack for instance). |
Jonathan Austin |
1:8aa5cdb4ab67 | 153 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 154 | * @param str The character array on which to base the new ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 155 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 156 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 157 | * ManagedString s("abcdefg"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 158 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 159 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 160 | ManagedString::ManagedString(const char *str) |
Jonathan Austin |
1:8aa5cdb4ab67 | 161 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 162 | // Sanity check. Return EmptyString for anything distasteful |
Jonathan Austin |
1:8aa5cdb4ab67 | 163 | if (str == NULL || *str == 0) |
Jonathan Austin |
1:8aa5cdb4ab67 | 164 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 165 | initEmpty(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 166 | return; |
Jonathan Austin |
1:8aa5cdb4ab67 | 167 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 168 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 169 | initString(str); |
Jonathan Austin |
1:8aa5cdb4ab67 | 170 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 171 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 172 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 173 | * Private Constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 174 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 175 | * Create a managed string based on a concat of two strings. |
Jonathan Austin |
1:8aa5cdb4ab67 | 176 | * The buffer is copied to ensure sane memory management (the supplied |
Jonathan Austin |
1:8aa5cdb4ab67 | 177 | * character buffer may be declared on the stack for instance). |
Jonathan Austin |
1:8aa5cdb4ab67 | 178 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 179 | * @param str1 The first string on which to base the new ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 180 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 181 | * @param str2 The second string on which to base the new ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 182 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 183 | ManagedString::ManagedString(const ManagedString &s1, const ManagedString &s2) |
Jonathan Austin |
1:8aa5cdb4ab67 | 184 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 185 | // Calculate length of new string. |
Jonathan Austin |
1:8aa5cdb4ab67 | 186 | int len = s1.length() + s2.length(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 187 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 188 | // Create a new buffer for holding the new string data. |
Jonathan Austin |
1:8aa5cdb4ab67 | 189 | ptr = (StringData*) malloc(4+len+1); |
Jonathan Austin |
1:8aa5cdb4ab67 | 190 | ptr->init(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 191 | ptr->len = len; |
Jonathan Austin |
1:8aa5cdb4ab67 | 192 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 193 | // Enter the data, and terminate the string. |
Jonathan Austin |
1:8aa5cdb4ab67 | 194 | memcpy(ptr->data, s1.toCharArray(), s1.length()); |
Jonathan Austin |
1:8aa5cdb4ab67 | 195 | memcpy(ptr->data + s1.length(), s2.toCharArray(), s2.length()); |
Jonathan Austin |
1:8aa5cdb4ab67 | 196 | ptr->data[len] = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 197 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 198 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 199 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 200 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 201 | * Constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 202 | * Create a ManagedString from a PacketBuffer. All bytes in the |
Jonathan Austin |
1:8aa5cdb4ab67 | 203 | * PacketBuffer are added to the ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 204 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 205 | * @param buffer The PacktBuffer from which to create the ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 206 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 207 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 208 | * ManagedString s = radio.datagram.recv(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 209 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 210 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 211 | ManagedString::ManagedString(PacketBuffer buffer) |
Jonathan Austin |
1:8aa5cdb4ab67 | 212 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 213 | // Allocate a new buffer ( just in case the data is not NULL terminated). |
Jonathan Austin |
1:8aa5cdb4ab67 | 214 | ptr = (StringData*) malloc(4+buffer.length()+1); |
Jonathan Austin |
1:8aa5cdb4ab67 | 215 | ptr->init(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 216 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 217 | // Store the length of the new string |
Jonathan Austin |
1:8aa5cdb4ab67 | 218 | ptr->len = buffer.length(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 219 | memcpy(ptr->data, buffer.getBytes(), buffer.length()); |
Jonathan Austin |
1:8aa5cdb4ab67 | 220 | ptr->data[buffer.length()] = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 221 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 222 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 223 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 224 | * Constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 225 | * Create a ManagedString from a pointer to an 8-bit character buffer of a given length. |
Jonathan Austin |
1:8aa5cdb4ab67 | 226 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 227 | * The buffer is copied to ensure sane memory management (the supplied |
Jonathan Austin |
1:8aa5cdb4ab67 | 228 | * character buffer may be declared on the stack for instance). |
Jonathan Austin |
1:8aa5cdb4ab67 | 229 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 230 | * @param str The character array on which to base the new ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 231 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 232 | * @param length The length of the character array |
Jonathan Austin |
1:8aa5cdb4ab67 | 233 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 234 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 235 | * ManagedString s("abcdefg",7); |
Jonathan Austin |
1:8aa5cdb4ab67 | 236 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 237 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 238 | ManagedString::ManagedString(const char *str, const int16_t length) |
Jonathan Austin |
1:8aa5cdb4ab67 | 239 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 240 | // Sanity check. Return EmptyString for anything distasteful |
Jonathan Austin |
1:8aa5cdb4ab67 | 241 | if (str == NULL || *str == 0 || (uint16_t)length > strlen(str)) // XXX length should be unsigned on the interface |
Jonathan Austin |
1:8aa5cdb4ab67 | 242 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 243 | initEmpty(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 244 | return; |
Jonathan Austin |
1:8aa5cdb4ab67 | 245 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 246 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 247 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 248 | // Allocate a new buffer, and create a NULL terminated string. |
Jonathan Austin |
1:8aa5cdb4ab67 | 249 | ptr = (StringData*) malloc(4+length+1); |
Jonathan Austin |
1:8aa5cdb4ab67 | 250 | ptr->init(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 251 | // Store the length of the new string |
Jonathan Austin |
1:8aa5cdb4ab67 | 252 | ptr->len = length; |
Jonathan Austin |
1:8aa5cdb4ab67 | 253 | memcpy(ptr->data, str, length); |
Jonathan Austin |
1:8aa5cdb4ab67 | 254 | ptr->data[length] = 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 255 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 256 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 257 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 258 | * Copy constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 259 | * Makes a new ManagedString identical to the one supplied. |
Jonathan Austin |
1:8aa5cdb4ab67 | 260 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 261 | * Shares the character buffer and reference count with the supplied ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 262 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 263 | * @param s The ManagedString to copy. |
Jonathan Austin |
1:8aa5cdb4ab67 | 264 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 265 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 266 | * ManagedString s("abcdefg"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 267 | * ManagedString p(s); |
Jonathan Austin |
1:8aa5cdb4ab67 | 268 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 269 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 270 | ManagedString::ManagedString(const ManagedString &s) |
Jonathan Austin |
1:8aa5cdb4ab67 | 271 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 272 | ptr = s.ptr; |
Jonathan Austin |
1:8aa5cdb4ab67 | 273 | ptr->incr(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 274 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 275 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 276 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 277 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 278 | * Default constructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 279 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 280 | * Create an empty ManagedString. |
Jonathan Austin |
1:8aa5cdb4ab67 | 281 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 282 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 283 | * ManagedString s(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 284 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 285 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 286 | ManagedString::ManagedString() |
Jonathan Austin |
1:8aa5cdb4ab67 | 287 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 288 | initEmpty(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 289 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 290 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 291 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 292 | * Destructor. |
Jonathan Austin |
1:8aa5cdb4ab67 | 293 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 294 | * Free this ManagedString, and decrement the reference count to the |
Jonathan Austin |
1:8aa5cdb4ab67 | 295 | * internal character buffer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 296 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 297 | * If we're holding the last reference, also free the character buffer. |
Jonathan Austin |
1:8aa5cdb4ab67 | 298 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 299 | ManagedString::~ManagedString() |
Jonathan Austin |
1:8aa5cdb4ab67 | 300 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 301 | ptr->decr(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 302 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 303 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 304 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 305 | * Copy assign operation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 306 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 307 | * Called when one ManagedString is assigned the value of another. |
Jonathan Austin |
1:8aa5cdb4ab67 | 308 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 309 | * If the ManagedString being assigned is already refering to a character buffer, |
Jonathan Austin |
1:8aa5cdb4ab67 | 310 | * decrement the reference count and free up the buffer as necessary. |
Jonathan Austin |
1:8aa5cdb4ab67 | 311 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 312 | * Then, update our character buffer to refer to that of the supplied ManagedString, |
Jonathan Austin |
1:8aa5cdb4ab67 | 313 | * and increase its reference count. |
Jonathan Austin |
1:8aa5cdb4ab67 | 314 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 315 | * @param s The ManagedString to copy. |
Jonathan Austin |
1:8aa5cdb4ab67 | 316 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 317 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 318 | * ManagedString s("abcd"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 319 | * ManagedString p("efgh"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 320 | * p = s // p now points to s, s' ref is incremented |
Jonathan Austin |
1:8aa5cdb4ab67 | 321 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 322 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 323 | ManagedString& ManagedString::operator = (const ManagedString& s) |
Jonathan Austin |
1:8aa5cdb4ab67 | 324 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 325 | if (this->ptr == s.ptr) |
Jonathan Austin |
1:8aa5cdb4ab67 | 326 | return *this; |
Jonathan Austin |
1:8aa5cdb4ab67 | 327 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 328 | ptr->decr(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 329 | ptr = s.ptr; |
Jonathan Austin |
1:8aa5cdb4ab67 | 330 | ptr->incr(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 331 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 332 | return *this; |
Jonathan Austin |
1:8aa5cdb4ab67 | 333 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 334 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 335 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 336 | * Equality operation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 337 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 338 | * Called when one ManagedString is tested to be equal to another using the '==' operator. |
Jonathan Austin |
1:8aa5cdb4ab67 | 339 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 340 | * @param s The ManagedString to test ourselves against. |
Jonathan Austin |
1:8aa5cdb4ab67 | 341 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 342 | * @return true if this ManagedString is identical to the one supplied, false otherwise. |
Jonathan Austin |
1:8aa5cdb4ab67 | 343 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 344 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 345 | * MicroBitDisplay display; |
Jonathan Austin |
1:8aa5cdb4ab67 | 346 | * ManagedString s("abcd"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 347 | * ManagedString p("efgh"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 348 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 349 | * if(p == s) |
Jonathan Austin |
1:8aa5cdb4ab67 | 350 | * display.scroll("We are the same!"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 351 | * else |
Jonathan Austin |
1:8aa5cdb4ab67 | 352 | * display.scroll("We are different!"); //p is not equal to s - this will be called |
Jonathan Austin |
1:8aa5cdb4ab67 | 353 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 354 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 355 | bool ManagedString::operator== (const ManagedString& s) |
Jonathan Austin |
1:8aa5cdb4ab67 | 356 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 357 | return ((length() == s.length()) && (strcmp(toCharArray(),s.toCharArray())==0)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 358 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 359 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 360 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 361 | * Inequality operation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 362 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 363 | * Called when one ManagedString is tested to be less than another using the '<' operator. |
Jonathan Austin |
1:8aa5cdb4ab67 | 364 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 365 | * @param s The ManagedString to test ourselves against. |
Jonathan Austin |
1:8aa5cdb4ab67 | 366 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 367 | * @return true if this ManagedString is alphabetically less than to the one supplied, false otherwise. |
Jonathan Austin |
1:8aa5cdb4ab67 | 368 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 369 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 370 | * MicroBitDisplay display; |
Jonathan Austin |
1:8aa5cdb4ab67 | 371 | * ManagedString s("a"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 372 | * ManagedString p("b"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 373 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 374 | * if(s < p) |
Jonathan Austin |
1:8aa5cdb4ab67 | 375 | * display.scroll("a is before b!"); //a is before b |
Jonathan Austin |
1:8aa5cdb4ab67 | 376 | * else |
Jonathan Austin |
1:8aa5cdb4ab67 | 377 | * display.scroll("b is before a!"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 378 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 379 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 380 | bool ManagedString::operator< (const ManagedString& s) |
Jonathan Austin |
1:8aa5cdb4ab67 | 381 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 382 | return (strcmp(toCharArray(), s.toCharArray())<0); |
Jonathan Austin |
1:8aa5cdb4ab67 | 383 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 384 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 385 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 386 | * Inequality operation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 387 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 388 | * Called when one ManagedString is tested to be greater than another using the '>' operator. |
Jonathan Austin |
1:8aa5cdb4ab67 | 389 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 390 | * @param s The ManagedString to test ourselves against. |
Jonathan Austin |
1:8aa5cdb4ab67 | 391 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 392 | * @return true if this ManagedString is alphabetically greater than to the one supplied, false otherwise. |
Jonathan Austin |
1:8aa5cdb4ab67 | 393 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 394 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 395 | * MicroBitDisplay display; |
Jonathan Austin |
1:8aa5cdb4ab67 | 396 | * ManagedString s("a"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 397 | * ManagedString p("b"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 398 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 399 | * if(p>a) |
Jonathan Austin |
1:8aa5cdb4ab67 | 400 | * display.scroll("b is after a!"); //b is after a |
Jonathan Austin |
1:8aa5cdb4ab67 | 401 | * else |
Jonathan Austin |
1:8aa5cdb4ab67 | 402 | * display.scroll("a is after b!"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 403 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 404 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 405 | bool ManagedString::operator> (const ManagedString& s) |
Jonathan Austin |
1:8aa5cdb4ab67 | 406 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 407 | return (strcmp(toCharArray(), s.toCharArray())>0); |
Jonathan Austin |
1:8aa5cdb4ab67 | 408 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 409 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 410 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 411 | * Extracts a ManagedString from this string, at the position provided. |
Jonathan Austin |
1:8aa5cdb4ab67 | 412 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 413 | * @param start The index of the first character to extract, indexed from zero. |
Jonathan Austin |
1:8aa5cdb4ab67 | 414 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 415 | * @param length The number of characters to extract from the start position |
Jonathan Austin |
1:8aa5cdb4ab67 | 416 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 417 | * @return a ManagedString representing the requested substring. |
Jonathan Austin |
1:8aa5cdb4ab67 | 418 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 419 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 420 | * MicroBitDisplay display; |
Jonathan Austin |
1:8aa5cdb4ab67 | 421 | * ManagedString s("abcdefg"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 422 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 423 | * display.scroll(s.substring(0,2)) // displays "ab" |
Jonathan Austin |
1:8aa5cdb4ab67 | 424 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 425 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 426 | ManagedString ManagedString::substring(int16_t start, int16_t length) |
Jonathan Austin |
1:8aa5cdb4ab67 | 427 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 428 | // If the parameters are illegal, just return a reference to the empty string. |
Jonathan Austin |
1:8aa5cdb4ab67 | 429 | if (start >= this->length()) |
Jonathan Austin |
1:8aa5cdb4ab67 | 430 | return ManagedString(ManagedString::EmptyString); |
Jonathan Austin |
1:8aa5cdb4ab67 | 431 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 432 | // Compute a safe copy length; |
Jonathan Austin |
1:8aa5cdb4ab67 | 433 | length = min(this->length()-start, length); |
Jonathan Austin |
1:8aa5cdb4ab67 | 434 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 435 | // Build a ManagedString from this. |
Jonathan Austin |
1:8aa5cdb4ab67 | 436 | return ManagedString(toCharArray()+start, length); |
Jonathan Austin |
1:8aa5cdb4ab67 | 437 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 438 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 439 | /** |
LancasterUniversity | 52:3db7b4d64316 | 440 | * Concatenates two strings. |
Jonathan Austin |
1:8aa5cdb4ab67 | 441 | * |
LancasterUniversity | 52:3db7b4d64316 | 442 | * @param lhs The first ManagedString to concatenate. |
LancasterUniversity | 52:3db7b4d64316 | 443 | * @param rhs The second ManagedString to concatenate. |
Jonathan Austin |
1:8aa5cdb4ab67 | 444 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 445 | * @return a new ManagedString representing the joined strings. |
Jonathan Austin |
1:8aa5cdb4ab67 | 446 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 447 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 448 | * MicroBitDisplay display; |
Jonathan Austin |
1:8aa5cdb4ab67 | 449 | * ManagedString s("abcd"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 450 | * ManagedString p("efgh") |
Jonathan Austin |
1:8aa5cdb4ab67 | 451 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 452 | * display.scroll(s + p) // scrolls "abcdefgh" |
Jonathan Austin |
1:8aa5cdb4ab67 | 453 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 454 | */ |
LancasterUniversity | 52:3db7b4d64316 | 455 | ManagedString operator+ (const ManagedString& lhs, const ManagedString& rhs) |
Jonathan Austin |
1:8aa5cdb4ab67 | 456 | { |
LancasterUniversity | 52:3db7b4d64316 | 457 | |
LancasterUniversity | 52:3db7b4d64316 | 458 | // If the either string is empty, nothing to do! |
LancasterUniversity | 52:3db7b4d64316 | 459 | if (rhs.length() == 0) |
LancasterUniversity | 52:3db7b4d64316 | 460 | return lhs; |
Jonathan Austin |
1:8aa5cdb4ab67 | 461 | |
LancasterUniversity | 52:3db7b4d64316 | 462 | if (lhs.length() == 0) |
LancasterUniversity | 52:3db7b4d64316 | 463 | return rhs; |
Jonathan Austin |
1:8aa5cdb4ab67 | 464 | |
LancasterUniversity | 52:3db7b4d64316 | 465 | return ManagedString(lhs, rhs); |
Jonathan Austin |
1:8aa5cdb4ab67 | 466 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 467 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 468 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 469 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 470 | * Provides a character value at a given position in the string, indexed from zero. |
Jonathan Austin |
1:8aa5cdb4ab67 | 471 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 472 | * @param index The position of the character to return. |
Jonathan Austin |
1:8aa5cdb4ab67 | 473 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 474 | * @return the character at posisiton index, zero if index is invalid. |
Jonathan Austin |
1:8aa5cdb4ab67 | 475 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 476 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 477 | * MicroBitDisplay display; |
Jonathan Austin |
1:8aa5cdb4ab67 | 478 | * ManagedString s("abcd"); |
Jonathan Austin |
1:8aa5cdb4ab67 | 479 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 480 | * display.scroll(s.charAt(1)) // scrolls "b" |
Jonathan Austin |
1:8aa5cdb4ab67 | 481 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 482 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 483 | char ManagedString::charAt(int16_t index) |
Jonathan Austin |
1:8aa5cdb4ab67 | 484 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 485 | return (index >=0 && index < length()) ? ptr->data[index] : 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 486 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 487 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 488 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 489 | * Empty string constant literal |
Jonathan Austin |
1:8aa5cdb4ab67 | 490 | */ |
LancasterUniversity | 51:9198e7bb83dc | 491 | ManagedString ManagedString::EmptyString((StringData*)(void*)empty); |