1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 #include <string.h> 21 22 #include <osl/interlck.h> 23 #include <osl/diagnose.h> 24 #include <rtl/character.hxx> 25 #include <rtl/ustrbuf.hxx> 26 #include "strimp.hxx" 27 28 #if USE_SDT_PROBES 29 #define RTL_LOG_STRING_BITS 16 30 #endif 31 32 void SAL_CALL rtl_uStringbuffer_newFromStr_WithLength( rtl_uString ** newStr, 33 const sal_Unicode * value, 34 sal_Int32 count) 35 { 36 assert(newStr); 37 assert(count >= 0); 38 if (!value) 39 { 40 rtl_uString_new_WithLength( newStr, 16 ); 41 return; 42 } 43 44 rtl_uString_new_WithLength( newStr, count + 16 ); 45 (*newStr)->length = count; 46 memcpy( (*newStr)->buffer, value, count * sizeof(sal_Unicode)); 47 RTL_LOG_STRING_NEW( *newStr ); 48 } 49 50 rtl_uString * SAL_CALL rtl_uStringBuffer_refReturn( rtl_uString * pThis ) 51 { 52 RTL_LOG_STRING_NEW( pThis ); 53 rtl_uString_acquire( pThis ); 54 return pThis; 55 } 56 57 rtl_uString * SAL_CALL rtl_uStringBuffer_makeStringAndClear( rtl_uString ** ppThis, 58 sal_Int32 *nCapacity ) 59 { 60 assert(ppThis); 61 assert(nCapacity); 62 // avoid an un-necessary atomic ref/unref pair 63 rtl_uString *pStr = *ppThis; 64 *ppThis = nullptr; 65 66 rtl_uString_new (ppThis); 67 *nCapacity = 0; 68 69 RTL_LOG_STRING_NEW( pStr ); 70 71 return pStr; 72 } 73 74 sal_Int32 SAL_CALL rtl_uStringbuffer_newFromStringBuffer( rtl_uString ** newStr, 75 sal_Int32 capacity, 76 rtl_uString * oldStr ) 77 { 78 assert(newStr); 79 assert(capacity >= 0); 80 assert(oldStr); 81 sal_Int32 newCapacity = capacity; 82 83 if (newCapacity < oldStr->length) 84 newCapacity = oldStr->length; 85 86 rtl_uString_new_WithLength( newStr, newCapacity ); 87 88 if (oldStr->length > 0) { 89 (*newStr)->length = oldStr->length; 90 memcpy( (*newStr)->buffer, oldStr->buffer, oldStr->length * sizeof(sal_Unicode)); 91 } 92 RTL_LOG_STRING_NEW( *newStr ); 93 return newCapacity; 94 } 95 96 void SAL_CALL rtl_uStringbuffer_ensureCapacity 97 (rtl_uString ** This, sal_Int32* capacity, sal_Int32 minimumCapacity) 98 { 99 assert(This); 100 assert(capacity && *capacity >= 0); 101 assert(minimumCapacity >= 0); 102 if (minimumCapacity > *capacity) 103 { 104 rtl_uString * pTmp = *This; 105 rtl_uString * pNew = nullptr; 106 *capacity = ((*This)->length + 1) * 2; 107 if (minimumCapacity > *capacity) 108 /* still lower, set to the minimum capacity */ 109 *capacity = minimumCapacity; 110 111 rtl_uString_new_WithLength(&pNew, *capacity); 112 pNew->length = (*This)->length; 113 *This = pNew; 114 115 memcpy( (*This)->buffer, pTmp->buffer, pTmp->length * sizeof(sal_Unicode) ); 116 117 RTL_LOG_STRING_NEW( pTmp ); // with accurate contents 118 rtl_uString_release( pTmp ); 119 } 120 } 121 122 void SAL_CALL rtl_uStringbuffer_insert( rtl_uString ** This, 123 sal_Int32 * capacity, 124 sal_Int32 offset, 125 const sal_Unicode * str, 126 sal_Int32 len) 127 { 128 assert(This); 129 assert(capacity && *capacity >= 0); 130 assert(offset >= 0 && offset <= (**This).length); 131 assert(len >= 0); 132 sal_Int32 nOldLen; 133 sal_Unicode * pBuf; 134 sal_Int32 n; 135 if( len != 0 ) 136 { 137 if (*capacity < (*This)->length + len) 138 rtl_uStringbuffer_ensureCapacity( This, capacity, (*This)->length + len ); 139 140 nOldLen = (*This)->length; 141 pBuf = (*This)->buffer; 142 143 /* copy the tail */ 144 n = (nOldLen - offset); 145 if( n == 1 ) 146 /* optimized for 1 character */ 147 pBuf[offset + len] = pBuf[offset]; 148 else if( n > 1 ) 149 memmove( pBuf + offset + len, pBuf + offset, n * sizeof(sal_Unicode) ); 150 151 /* insert the new characters */ 152 if( str != nullptr ) 153 { 154 if( len == 1 ) 155 /* optimized for 1 character */ 156 pBuf[offset] = *str; 157 else 158 memcpy( pBuf + offset, str, len * sizeof(sal_Unicode) ); 159 } 160 (*This)->length = nOldLen + len; 161 pBuf[ nOldLen + len ] = 0; 162 } 163 } 164 165 void rtl_uStringbuffer_insertUtf32( 166 rtl_uString ** pThis, sal_Int32 * capacity, sal_Int32 offset, sal_uInt32 c) 167 SAL_THROW_EXTERN_C() 168 { 169 sal_Unicode buf[2]; 170 sal_Int32 len; 171 OSL_ASSERT(rtl::isUnicodeScalarValue(c)); 172 if (c <= 0xFFFF) { 173 buf[0] = static_cast<sal_Unicode>(c); 174 len = 1; 175 } else { 176 c -= 0x10000; 177 buf[0] = static_cast<sal_Unicode>((c >> 10) | 0xD800); 178 buf[1] = static_cast<sal_Unicode>((c & 0x3FF) | 0xDC00); 179 len = 2; 180 } 181 rtl_uStringbuffer_insert(pThis, capacity, offset, buf, len); 182 } 183 184 void SAL_CALL rtl_uStringbuffer_insert_ascii( /*inout*/rtl_uString ** This, 185 /*inout*/sal_Int32 * capacity, 186 sal_Int32 offset, 187 const sal_Char * str, 188 sal_Int32 len) 189 { 190 assert(This); 191 assert(capacity && *capacity >= 0); 192 assert(offset >= 0 && offset <= (**This).length); 193 assert(len == 0 || str != nullptr); 194 assert(len >= 0); 195 sal_Int32 nOldLen; 196 sal_Unicode * pBuf; 197 sal_Int32 n; 198 if( len != 0 ) 199 { 200 if (*capacity < (*This)->length + len) 201 rtl_uStringbuffer_ensureCapacity( This, capacity, (*This)->length + len ); 202 203 nOldLen = (*This)->length; 204 pBuf = (*This)->buffer; 205 206 /* copy the tail */ 207 n = (nOldLen - offset); 208 if( n == 1 ) 209 /* optimized for 1 character */ 210 pBuf[offset + len] = pBuf[offset]; 211 else if( n > 1 ) 212 memmove( pBuf + offset + len, pBuf + offset, n * sizeof(sal_Unicode) ); 213 214 /* insert the new characters */ 215 for( n = 0; n < len; n++ ) 216 { 217 /* Check ASCII range */ 218 OSL_ENSURE( (*str & 0x80) == 0, "Found ASCII char > 127"); 219 220 pBuf[offset + n] = static_cast<sal_Unicode>(*(str++)); 221 } 222 223 (*This)->length = nOldLen + len; 224 pBuf[ nOldLen + len ] = 0; 225 } 226 } 227 228 /************************************************************************* 229 * rtl_uStringbuffer_remove 230 */ 231 void SAL_CALL rtl_uStringbuffer_remove( rtl_uString ** This, 232 sal_Int32 start, 233 sal_Int32 len ) 234 { 235 assert(This); 236 assert(start >= 0 && start <= (**This).length); 237 assert(len >= 0); 238 sal_Int32 nTailLen; 239 sal_Unicode * pBuf; 240 241 if (len > (*This)->length - start) 242 len = (*This)->length - start; 243 244 //remove nothing 245 if (!len) 246 return; 247 248 pBuf = (*This)->buffer; 249 nTailLen = (*This)->length - ( start + len ); 250 251 if (nTailLen) 252 { 253 /* move the tail */ 254 memmove(pBuf + start, pBuf + start + len, nTailLen * sizeof(sal_Unicode)); 255 } 256 257 (*This)->length-=len; 258 pBuf[ (*This)->length ] = 0; 259 } 260 261 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 262
