Dependencies:   MMA7660 LM75B

Committer:
MACRUM
Date:
Sat Jun 30 01:40:30 2018 +0000
Revision:
0:119624335925
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MACRUM 0:119624335925 1 /*
MACRUM 0:119624335925 2 * Copyright (c) 2015 ARM Limited. All rights reserved.
MACRUM 0:119624335925 3 * SPDX-License-Identifier: Apache-2.0
MACRUM 0:119624335925 4 * Licensed under the Apache License, Version 2.0 (the License); you may
MACRUM 0:119624335925 5 * not use this file except in compliance with the License.
MACRUM 0:119624335925 6 * You may obtain a copy of the License at
MACRUM 0:119624335925 7 *
MACRUM 0:119624335925 8 * http://www.apache.org/licenses/LICENSE-2.0
MACRUM 0:119624335925 9 *
MACRUM 0:119624335925 10 * Unless required by applicable law or agreed to in writing, software
MACRUM 0:119624335925 11 * distributed under the License is distributed on an AS IS BASIS, WITHOUT
MACRUM 0:119624335925 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
MACRUM 0:119624335925 13 * See the License for the specific language governing permissions and
MACRUM 0:119624335925 14 * limitations under the License.
MACRUM 0:119624335925 15 */
MACRUM 0:119624335925 16 #include "mbed-client/m2mstring.h"
MACRUM 0:119624335925 17 #include <string.h> // strlen
MACRUM 0:119624335925 18 #include <stdlib.h> // malloc, realloc
MACRUM 0:119624335925 19 #include <assert.h>
MACRUM 0:119624335925 20 #include <algorithm> // min
MACRUM 0:119624335925 21
MACRUM 0:119624335925 22 namespace m2m {
MACRUM 0:119624335925 23
MACRUM 0:119624335925 24 const String::size_type String::npos = static_cast<size_t>(-1);
MACRUM 0:119624335925 25
MACRUM 0:119624335925 26 char* String::strdup(const char* s)
MACRUM 0:119624335925 27 {
MACRUM 0:119624335925 28 const size_t len = strlen(s)+1;
MACRUM 0:119624335925 29 char *p2 = static_cast<char*>(malloc(len));
MACRUM 0:119624335925 30 if (p2) {
MACRUM 0:119624335925 31 memcpy(p2, s, len);
MACRUM 0:119624335925 32 allocated_ = len;
MACRUM 0:119624335925 33 size_ = len-1;
MACRUM 0:119624335925 34 }
MACRUM 0:119624335925 35 return p2;
MACRUM 0:119624335925 36 }
MACRUM 0:119624335925 37
MACRUM 0:119624335925 38 String::String()
MACRUM 0:119624335925 39 : p( strdup("") )
MACRUM 0:119624335925 40 {
MACRUM 0:119624335925 41 }
MACRUM 0:119624335925 42
MACRUM 0:119624335925 43 String::~String()
MACRUM 0:119624335925 44 {
MACRUM 0:119624335925 45 free(p);
MACRUM 0:119624335925 46 p = 0;
MACRUM 0:119624335925 47 }
MACRUM 0:119624335925 48
MACRUM 0:119624335925 49 String::String(const String& s)
MACRUM 0:119624335925 50 : p(0)
MACRUM 0:119624335925 51 {
MACRUM 0:119624335925 52 p = static_cast<char*>(malloc(s.size_ + 1));
MACRUM 0:119624335925 53
MACRUM 0:119624335925 54 allocated_ = s.size_ + 1;
MACRUM 0:119624335925 55 size_ = s.size_;
MACRUM 0:119624335925 56 memcpy(p, s.p, size_ + 1);
MACRUM 0:119624335925 57 }
MACRUM 0:119624335925 58
MACRUM 0:119624335925 59 String::String(const char* s)
MACRUM 0:119624335925 60 : p(strdup(s))
MACRUM 0:119624335925 61 {
MACRUM 0:119624335925 62 }
MACRUM 0:119624335925 63
MACRUM 0:119624335925 64 String::String(const char* str, size_t n)
MACRUM 0:119624335925 65 {
MACRUM 0:119624335925 66 p = static_cast<char*>(malloc(n + 1));
MACRUM 0:119624335925 67
MACRUM 0:119624335925 68 allocated_ = n + 1;
MACRUM 0:119624335925 69 size_ = n;
MACRUM 0:119624335925 70 memcpy(p, str, n);
MACRUM 0:119624335925 71 p[n] = 0;
MACRUM 0:119624335925 72 }
MACRUM 0:119624335925 73
MACRUM 0:119624335925 74 String& String::operator=(const char* s)
MACRUM 0:119624335925 75 {
MACRUM 0:119624335925 76 if ( p != s ) {
MACRUM 0:119624335925 77 // s could point into our own string, so we have to allocate a new string
MACRUM 0:119624335925 78 const size_t len = strlen(s);
MACRUM 0:119624335925 79 char* copy = (char*) malloc( len + 1);
MACRUM 0:119624335925 80 memmove(copy, s, len+1); // trailing 0
MACRUM 0:119624335925 81 free( p );
MACRUM 0:119624335925 82 p = copy;
MACRUM 0:119624335925 83 size_ = len;
MACRUM 0:119624335925 84 allocated_ = len+1;
MACRUM 0:119624335925 85 }
MACRUM 0:119624335925 86 return *this;
MACRUM 0:119624335925 87 }
MACRUM 0:119624335925 88
MACRUM 0:119624335925 89 String& String::operator=(const String& s)
MACRUM 0:119624335925 90 {
MACRUM 0:119624335925 91 return operator=(s.p);
MACRUM 0:119624335925 92 }
MACRUM 0:119624335925 93
MACRUM 0:119624335925 94 String& String::operator+=(const String& s)
MACRUM 0:119624335925 95 {
MACRUM 0:119624335925 96 if (s.size_ > 0) {
MACRUM 0:119624335925 97 this->reserve(size_ + s.size_);
MACRUM 0:119624335925 98 memmove(p+size_, s.p, s.size_+1); // trailing 0
MACRUM 0:119624335925 99 size_ += s.size_;
MACRUM 0:119624335925 100 }
MACRUM 0:119624335925 101 return *this;
MACRUM 0:119624335925 102 }
MACRUM 0:119624335925 103
MACRUM 0:119624335925 104 // since p and s may overlap, we have to copy our own string first
MACRUM 0:119624335925 105 String& String::operator+=(const char* s)
MACRUM 0:119624335925 106 {
MACRUM 0:119624335925 107 const size_type lens = strlen(s);
MACRUM 0:119624335925 108 if (lens > 0) {
MACRUM 0:119624335925 109 if (size_ + lens + 1 <= allocated_) {
MACRUM 0:119624335925 110 memmove(p+size_, s, lens+1); // trailing 0
MACRUM 0:119624335925 111 size_ += lens;
MACRUM 0:119624335925 112 } else {
MACRUM 0:119624335925 113 String s2( *this ); // copy own data
MACRUM 0:119624335925 114 s2.reserve(size_ + lens);
MACRUM 0:119624335925 115 memmove(s2.p+size_, s, lens+1); // trailing 0
MACRUM 0:119624335925 116 s2.size_ = size_ + lens;
MACRUM 0:119624335925 117 this->swap( s2 );
MACRUM 0:119624335925 118 }
MACRUM 0:119624335925 119 }
MACRUM 0:119624335925 120 return *this;
MACRUM 0:119624335925 121 }
MACRUM 0:119624335925 122
MACRUM 0:119624335925 123 String& String::operator+=(const char c)
MACRUM 0:119624335925 124 {
MACRUM 0:119624335925 125 push_back(c);
MACRUM 0:119624335925 126 return *this;
MACRUM 0:119624335925 127 }
MACRUM 0:119624335925 128
MACRUM 0:119624335925 129 void String::push_back(const char c) {
MACRUM 0:119624335925 130
MACRUM 0:119624335925 131 if (size_ == allocated_ - 1) {
MACRUM 0:119624335925 132 size_t more = (allocated_* 3) / 2; // factor 1.5
MACRUM 0:119624335925 133 if ( more < 4 ) more = 4;
MACRUM 0:119624335925 134 reserve( size_ + more );
MACRUM 0:119624335925 135 }
MACRUM 0:119624335925 136
MACRUM 0:119624335925 137 p[size_] = c;
MACRUM 0:119624335925 138 size_++;
MACRUM 0:119624335925 139 p[size_] = 0;
MACRUM 0:119624335925 140 }
MACRUM 0:119624335925 141
MACRUM 0:119624335925 142 bool String::operator==(const char* s) const
MACRUM 0:119624335925 143 {
MACRUM 0:119624335925 144 if( s == NULL ) {
MACRUM 0:119624335925 145 if( p == NULL ) {
MACRUM 0:119624335925 146 return true;
MACRUM 0:119624335925 147 }
MACRUM 0:119624335925 148 return false;
MACRUM 0:119624335925 149 }
MACRUM 0:119624335925 150 bool ret = strcmp(p, s);
MACRUM 0:119624335925 151 return !ret;
MACRUM 0:119624335925 152 }
MACRUM 0:119624335925 153
MACRUM 0:119624335925 154 bool String::operator==(const String& s) const
MACRUM 0:119624335925 155 {
MACRUM 0:119624335925 156 bool ret = strcmp(p, s.p);
MACRUM 0:119624335925 157 return !ret;
MACRUM 0:119624335925 158 }
MACRUM 0:119624335925 159
MACRUM 0:119624335925 160 void String::clear()
MACRUM 0:119624335925 161 {
MACRUM 0:119624335925 162 size_ = 0;
MACRUM 0:119624335925 163 p[0] = 0;
MACRUM 0:119624335925 164 }
MACRUM 0:119624335925 165
MACRUM 0:119624335925 166 String String::substr(const size_type pos, size_type length) const
MACRUM 0:119624335925 167 {
MACRUM 0:119624335925 168 String s;
MACRUM 0:119624335925 169 const size_type len = size_;
MACRUM 0:119624335925 170
MACRUM 0:119624335925 171 if ( pos <= len ) {
MACRUM 0:119624335925 172
MACRUM 0:119624335925 173 size_type remain = len - pos;
MACRUM 0:119624335925 174
MACRUM 0:119624335925 175 if ( length > remain )
MACRUM 0:119624335925 176 length = remain;
MACRUM 0:119624335925 177
MACRUM 0:119624335925 178 s.reserve( length );
MACRUM 0:119624335925 179
MACRUM 0:119624335925 180 memcpy(s.p, p + pos, length);
MACRUM 0:119624335925 181 s.p[length] = '\0';
MACRUM 0:119624335925 182 s.size_ = length;
MACRUM 0:119624335925 183 }
MACRUM 0:119624335925 184 return s;
MACRUM 0:119624335925 185 }
MACRUM 0:119624335925 186
MACRUM 0:119624335925 187
MACRUM 0:119624335925 188 // checked access, accessing the NUL at end is allowed
MACRUM 0:119624335925 189 char String::at(const size_type i) const
MACRUM 0:119624335925 190 {
MACRUM 0:119624335925 191 if ( i <= strlen(p) ) {
MACRUM 0:119624335925 192 return p[i];
MACRUM 0:119624335925 193 } else {
MACRUM 0:119624335925 194 return '\0';
MACRUM 0:119624335925 195 }
MACRUM 0:119624335925 196 }
MACRUM 0:119624335925 197
MACRUM 0:119624335925 198 String& String::erase(size_type pos, size_type len)
MACRUM 0:119624335925 199 {
MACRUM 0:119624335925 200 if (len > 0) {
MACRUM 0:119624335925 201
MACRUM 0:119624335925 202 if ( pos < size_ ) { // user must not remove trailing 0
MACRUM 0:119624335925 203
MACRUM 0:119624335925 204 size_type s2 = size_;
MACRUM 0:119624335925 205 size_type remain = s2 - pos - len;
MACRUM 0:119624335925 206
MACRUM 0:119624335925 207 if (remain > 0) {
MACRUM 0:119624335925 208 // erase by overwriting
MACRUM 0:119624335925 209 memmove(p + pos, p + pos + len, remain);
MACRUM 0:119624335925 210 }
MACRUM 0:119624335925 211
MACRUM 0:119624335925 212 //if ( remain < 0 ) remain = 0;
MACRUM 0:119624335925 213
MACRUM 0:119624335925 214 // remove unused space
MACRUM 0:119624335925 215 this->resize( pos+remain );
MACRUM 0:119624335925 216
MACRUM 0:119624335925 217 }
MACRUM 0:119624335925 218 }
MACRUM 0:119624335925 219 return *this;
MACRUM 0:119624335925 220 }
MACRUM 0:119624335925 221
MACRUM 0:119624335925 222 String& String::append( const char* str, size_type n) {
MACRUM 0:119624335925 223 if (str && n > 0) {
MACRUM 0:119624335925 224 size_t lens = strlen(str);
MACRUM 0:119624335925 225 if (n > lens)
MACRUM 0:119624335925 226 n = lens;
MACRUM 0:119624335925 227 size_t newlen = size_ + n;
MACRUM 0:119624335925 228 this->reserve( newlen );
MACRUM 0:119624335925 229 memmove(p+size_, str, n); // p and s.p MAY overlap
MACRUM 0:119624335925 230 p[newlen] = 0; // add NUL termination
MACRUM 0:119624335925 231 size_ = newlen;
MACRUM 0:119624335925 232 }
MACRUM 0:119624335925 233 return *this;
MACRUM 0:119624335925 234 }
MACRUM 0:119624335925 235
MACRUM 0:119624335925 236 String& String::append_raw( const char* str, size_type n) {
MACRUM 0:119624335925 237 if (str && n > 0) {
MACRUM 0:119624335925 238 size_t newlen = size_ + n;
MACRUM 0:119624335925 239 this->reserve( newlen );
MACRUM 0:119624335925 240 memmove(p+size_, str, n); // p and s.p MAY overlap
MACRUM 0:119624335925 241 p[newlen] = 0; // add NUL termination
MACRUM 0:119624335925 242 size_ = newlen;
MACRUM 0:119624335925 243 }
MACRUM 0:119624335925 244 return *this;
MACRUM 0:119624335925 245 }
MACRUM 0:119624335925 246
MACRUM 0:119624335925 247 void String::append_int(int param) {
MACRUM 0:119624335925 248
MACRUM 0:119624335925 249 // max len of "-9223372036854775808" plus zero termination
MACRUM 0:119624335925 250 char conv_buff[20+1];
MACRUM 0:119624335925 251
MACRUM 0:119624335925 252 int len = itoa_c(param, conv_buff);
MACRUM 0:119624335925 253 append_raw(conv_buff, len);
MACRUM 0:119624335925 254 }
MACRUM 0:119624335925 255
MACRUM 0:119624335925 256 int String::compare( size_type pos, size_type len, const String& str ) const {
MACRUM 0:119624335925 257 int r = -1;
MACRUM 0:119624335925 258 if (pos <= size_) {
MACRUM 0:119624335925 259 if ( len > size_ - pos)
MACRUM 0:119624335925 260 len = size_ - pos; // limit len to available length
MACRUM 0:119624335925 261
MACRUM 0:119624335925 262 const size_type osize = str.size();
MACRUM 0:119624335925 263 const size_type len2 = std::min(len, osize);
MACRUM 0:119624335925 264 r = strncmp( p + pos, str.p, len2);
MACRUM 0:119624335925 265 if (r==0) // equal so far, now compare sizes
MACRUM 0:119624335925 266 r = len < osize ? -1 : ( len == osize ? 0 : +1 );
MACRUM 0:119624335925 267 }
MACRUM 0:119624335925 268 return r;
MACRUM 0:119624335925 269 }
MACRUM 0:119624335925 270
MACRUM 0:119624335925 271 int String::compare( size_type pos, size_type len, const char* str ) const {
MACRUM 0:119624335925 272 int r = -1;
MACRUM 0:119624335925 273 if (pos <= size_) {
MACRUM 0:119624335925 274
MACRUM 0:119624335925 275 if ( len > size_ - pos)
MACRUM 0:119624335925 276 len = size_ - pos; // limit len to available length
MACRUM 0:119624335925 277
MACRUM 0:119624335925 278 const size_type osize = strlen(str);
MACRUM 0:119624335925 279 const size_type len2 = std::min(len, osize);
MACRUM 0:119624335925 280 r = strncmp( p + pos, str, len2);
MACRUM 0:119624335925 281 if (r==0) // equal so far, now compare sizes
MACRUM 0:119624335925 282 r = len < osize ? -1 : ( len == osize ? 0 : +1 );
MACRUM 0:119624335925 283 }
MACRUM 0:119624335925 284 return r;
MACRUM 0:119624335925 285 }
MACRUM 0:119624335925 286
MACRUM 0:119624335925 287 int String::find_last_of(char c) const {
MACRUM 0:119624335925 288 int r = -1;
MACRUM 0:119624335925 289 char *v;
MACRUM 0:119624335925 290 v = strrchr(p,c);
MACRUM 0:119624335925 291 if (v != NULL) {
MACRUM 0:119624335925 292 r = 0;
MACRUM 0:119624335925 293 char* i = p;
MACRUM 0:119624335925 294 while (v != i) {
MACRUM 0:119624335925 295 i++;
MACRUM 0:119624335925 296 r++;
MACRUM 0:119624335925 297 }
MACRUM 0:119624335925 298 }
MACRUM 0:119624335925 299 return r;
MACRUM 0:119624335925 300 }
MACRUM 0:119624335925 301
MACRUM 0:119624335925 302 void String::new_realloc( size_type n) {
MACRUM 0:119624335925 303 if (n > 0 ) {
MACRUM 0:119624335925 304 char* pnew = static_cast<char*>(realloc(p, n)); // could return NULL
MACRUM 0:119624335925 305 if (pnew)
MACRUM 0:119624335925 306 p = pnew;
MACRUM 0:119624335925 307 }
MACRUM 0:119624335925 308 }
MACRUM 0:119624335925 309
MACRUM 0:119624335925 310 void String::reserve( const size_type n) {
MACRUM 0:119624335925 311 if (n >= allocated_ ) {
MACRUM 0:119624335925 312 this->new_realloc(n + 1);
MACRUM 0:119624335925 313 allocated_ = n + 1;
MACRUM 0:119624335925 314 }
MACRUM 0:119624335925 315 }
MACRUM 0:119624335925 316
MACRUM 0:119624335925 317 void String::resize( const size_type n) {
MACRUM 0:119624335925 318 this->resize( n, 0 );
MACRUM 0:119624335925 319 }
MACRUM 0:119624335925 320
MACRUM 0:119624335925 321 void String::resize( const size_type n, const char c) {
MACRUM 0:119624335925 322 if (n < size_ ) {
MACRUM 0:119624335925 323 p[n] = 0;
MACRUM 0:119624335925 324 size_ = n;
MACRUM 0:119624335925 325 }
MACRUM 0:119624335925 326 else if (n > size_ ) {
MACRUM 0:119624335925 327 this->reserve( n );
MACRUM 0:119624335925 328 for (size_type i=size_; i < n; ++i )
MACRUM 0:119624335925 329 p[i] = c;
MACRUM 0:119624335925 330 p[n] = 0;
MACRUM 0:119624335925 331 size_ = n;
MACRUM 0:119624335925 332 }
MACRUM 0:119624335925 333 }
MACRUM 0:119624335925 334
MACRUM 0:119624335925 335 void String::swap( String& s ) {
MACRUM 0:119624335925 336 std::swap( allocated_, s.allocated_ );
MACRUM 0:119624335925 337 std::swap( size_, s.size_ );
MACRUM 0:119624335925 338 std::swap( p, s.p );
MACRUM 0:119624335925 339 }
MACRUM 0:119624335925 340
MACRUM 0:119624335925 341
MACRUM 0:119624335925 342 // Comparison
MACRUM 0:119624335925 343 bool operator<( const String& s1, const String& s2 ) {
MACRUM 0:119624335925 344 return strcmp( s1.c_str(), s2.c_str() ) < 0;
MACRUM 0:119624335925 345 }
MACRUM 0:119624335925 346
MACRUM 0:119624335925 347 void reverse(char s[], uint32_t length)
MACRUM 0:119624335925 348 {
MACRUM 0:119624335925 349 uint32_t i, j;
MACRUM 0:119624335925 350 char c;
MACRUM 0:119624335925 351
MACRUM 0:119624335925 352 for (i = 0, j = length-1; i<j; i++, j--) {
MACRUM 0:119624335925 353 c = s[i];
MACRUM 0:119624335925 354 s[i] = s[j];
MACRUM 0:119624335925 355 s[j] = c;
MACRUM 0:119624335925 356 }
MACRUM 0:119624335925 357 }
MACRUM 0:119624335925 358
MACRUM 0:119624335925 359 uint32_t itoa_c (int64_t n, char s[])
MACRUM 0:119624335925 360 {
MACRUM 0:119624335925 361 int64_t sign;
MACRUM 0:119624335925 362 uint32_t i;
MACRUM 0:119624335925 363
MACRUM 0:119624335925 364 if ((sign = n) < 0)
MACRUM 0:119624335925 365 n = -n;
MACRUM 0:119624335925 366
MACRUM 0:119624335925 367 i = 0;
MACRUM 0:119624335925 368
MACRUM 0:119624335925 369 do {
MACRUM 0:119624335925 370 s[i++] = n % 10 + '0';
MACRUM 0:119624335925 371 }
MACRUM 0:119624335925 372 while ((n /= 10) > 0);
MACRUM 0:119624335925 373
MACRUM 0:119624335925 374 if (sign < 0)
MACRUM 0:119624335925 375 s[i++] = '-';
MACRUM 0:119624335925 376
MACRUM 0:119624335925 377 s[i] = '\0';
MACRUM 0:119624335925 378
MACRUM 0:119624335925 379 m2m::reverse(s, i);
MACRUM 0:119624335925 380 return i;
MACRUM 0:119624335925 381 }
MACRUM 0:119624335925 382
MACRUM 0:119624335925 383 uint8_t* String::convert_integer_to_array(int64_t value, uint8_t &size, const uint8_t *array, const uint32_t array_size)
MACRUM 0:119624335925 384 {
MACRUM 0:119624335925 385 uint8_t* buffer = NULL;
MACRUM 0:119624335925 386 size = 0;
MACRUM 0:119624335925 387 if (array) {
MACRUM 0:119624335925 388 value = String::convert_array_to_integer(array, array_size);
MACRUM 0:119624335925 389 }
MACRUM 0:119624335925 390
MACRUM 0:119624335925 391 if(value < 0xFF) {
MACRUM 0:119624335925 392 size = 1;
MACRUM 0:119624335925 393 } else if(value < 0xFFFF) {
MACRUM 0:119624335925 394 size = 2;
MACRUM 0:119624335925 395 } else if(value < 0xFFFFFF) {
MACRUM 0:119624335925 396 size = 3;
MACRUM 0:119624335925 397 } else if(value < 0xFFFFFFFF) {
MACRUM 0:119624335925 398 size = 4;
MACRUM 0:119624335925 399 } else if(value < 0xFFFFFFFFFF) {
MACRUM 0:119624335925 400 size = 5;
MACRUM 0:119624335925 401 } else if(value < 0xFFFFFFFFFFFF) {
MACRUM 0:119624335925 402 size = 6;
MACRUM 0:119624335925 403 } else if(value < 0xFFFFFFFFFFFFFF) {
MACRUM 0:119624335925 404 size = 7;
MACRUM 0:119624335925 405 } else {
MACRUM 0:119624335925 406 size = 8;
MACRUM 0:119624335925 407 }
MACRUM 0:119624335925 408
MACRUM 0:119624335925 409 buffer = (uint8_t*)malloc(size);
MACRUM 0:119624335925 410 if (buffer) {
MACRUM 0:119624335925 411 for (int i = 0; i < size; i++) {
MACRUM 0:119624335925 412 buffer[i] = (value >> ((size - i - 1) * 8));
MACRUM 0:119624335925 413 }
MACRUM 0:119624335925 414 } else {
MACRUM 0:119624335925 415 size = 0;
MACRUM 0:119624335925 416 }
MACRUM 0:119624335925 417 return buffer;
MACRUM 0:119624335925 418 }
MACRUM 0:119624335925 419
MACRUM 0:119624335925 420 int64_t String::convert_array_to_integer(const uint8_t *value, const uint32_t size)
MACRUM 0:119624335925 421 {
MACRUM 0:119624335925 422 int64_t temp_64 = 0;
MACRUM 0:119624335925 423 for (int i = size - 1; i >= 0; i--) {
MACRUM 0:119624335925 424 temp_64 += (uint64_t)(*value++) << i * 8;
MACRUM 0:119624335925 425 }
MACRUM 0:119624335925 426 return temp_64;
MACRUM 0:119624335925 427 }
MACRUM 0:119624335925 428
MACRUM 0:119624335925 429 } // namespace