Bug Summary

File:comphelper/source/misc/string.cxx
Location:line 351, column 5
Description:Called C++ object pointer is null

Annotated Source Code

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 "sal/config.h"
21
22#include <cstddef>
23#include <string.h>
24#include <vector>
25#include <algorithm>
26
27#include <rtl/ustring.hxx>
28#include <rtl/ustrbuf.hxx>
29#include <rtl/string.hxx>
30#include <rtl/strbuf.hxx>
31#include <sal/types.h>
32
33#include <comphelper/string.hxx>
34#include <comphelper/stlunosequence.hxx>
35#include <comphelper/stl_types.hxx>
36
37#include <com/sun/star/i18n/CharType.hpp>
38
39
40namespace comphelper { namespace string {
41
42namespace
43{
44 template <typename T, typename C> T tmpl_stripStart(const T &rIn,
45 const C cRemove)
46 {
47 if (rIn.isEmpty())
48 return rIn;
49
50 sal_Int32 i = 0;
51
52 while (i < rIn.getLength())
53 {
54 if (rIn[i] != cRemove)
55 break;
56 ++i;
57 }
58
59 return rIn.copy(i);
60 }
61}
62
63rtl::OString stripStart(const rtl::OString &rIn, sal_Char c)
64{
65 return tmpl_stripStart<rtl::OString, sal_Char>(rIn, c);
66}
67
68rtl::OUString stripStart(const rtl::OUString &rIn, sal_Unicode c)
69{
70 return tmpl_stripStart<rtl::OUString, sal_Unicode>(rIn, c);
71}
72
73namespace
74{
75 template <typename T, typename C> T tmpl_stripEnd(const T &rIn,
76 const C cRemove)
77 {
78 if (rIn.isEmpty())
79 return rIn;
80
81 sal_Int32 i = rIn.getLength();
82
83 while (i > 0)
84 {
85 if (rIn[i-1] != cRemove)
86 break;
87 --i;
88 }
89
90 return rIn.copy(0, i);
91 }
92}
93
94rtl::OString stripEnd(const rtl::OString &rIn, sal_Char c)
95{
96 return tmpl_stripEnd<rtl::OString, sal_Char>(rIn, c);
97}
98
99rtl::OUString stripEnd(const rtl::OUString &rIn, sal_Unicode c)
100{
101 return tmpl_stripEnd<rtl::OUString, sal_Unicode>(rIn, c);
102}
103
104rtl::OString strip(const rtl::OString &rIn, sal_Char c)
105{
106 return stripEnd(stripStart(rIn, c), c);
107}
108
109rtl::OUString strip(const rtl::OUString &rIn, sal_Unicode c)
110{
111 return stripEnd(stripStart(rIn, c), c);
112}
113
114namespace
115{
116 template <typename T, typename C> sal_Int32 tmpl_getTokenCount(const T &rIn,
117 C cTok)
118 {
119 // Empty String: TokenCount by Definition is 0
120 if (rIn.isEmpty())
121 return 0;
122
123 sal_Int32 nTokCount = 1;
124 for (sal_Int32 i = 0; i < rIn.getLength(); ++i)
125 {
126 if (rIn[i] == cTok)
127 ++nTokCount;
128 }
129 return nTokCount;
130 }
131}
132
133sal_Int32 getTokenCount(const rtl::OString &rIn, sal_Char cTok)
134{
135 return tmpl_getTokenCount<rtl::OString, sal_Char>(rIn, cTok);
136}
137
138sal_Int32 getTokenCount(const rtl::OUString &rIn, sal_Unicode cTok)
139{
140 return tmpl_getTokenCount<rtl::OUString, sal_Unicode>(rIn, cTok);
141}
142
143sal_uInt32 decimalStringToNumber(
144 ::rtl::OUString const & str )
145{
146 sal_uInt32 result = 0;
147 for( sal_Int32 i = 0 ; i < str.getLength() ; )
148 {
149 sal_uInt32 c = str.iterateCodePoints(&i);
150 sal_uInt32 value = 0;
151 if( c <= 0x0039) // ASCII decimal digits, most common
152 value = c - 0x0030;
153 else if( c >= 0x1D7F6 ) // mathematical monospace digits
154 value = c - 0x1D7F6;
155 else if( c >= 0x1D7EC ) // mathematical sans-serif bold digits
156 value = c - 0x1D7EC;
157 else if( c >= 0x1D7E2 ) // mathematical sans-serif digits
158 value = c - 0x1D7E2;
159 else if( c >= 0x1D7D8 ) // mathematical double-struck digits
160 value = c - 0x1D7D8;
161 else if( c >= 0x1D7CE ) // mathematical bold digits
162 value = c - 0x1D7CE;
163 else if( c >= 0x11066 ) // brahmi digits
164 value = c - 0x11066;
165 else if( c >= 0x104A0 ) // osmanya digits
166 value = c - 0x104A0;
167 else if( c >= 0xFF10 ) // fullwidth digits
168 value = c - 0xFF10;
169 else if( c >= 0xABF0 ) // meetei mayek digits
170 value = c - 0xABF0;
171 else if( c >= 0xAA50 ) // cham digits
172 value = c - 0xAA50;
173 else if( c >= 0xA9D0 ) // javanese digits
174 value = c - 0xA9D0;
175 else if( c >= 0xA900 ) // kayah li digits
176 value = c - 0xA900;
177 else if( c >= 0xA8D0 ) // saurashtra digits
178 value = c - 0xA8D0;
179 else if( c >= 0xA620 ) // vai digits
180 value = c - 0xA620;
181 else if( c >= 0x1C50 ) // ol chiki digits
182 value = c - 0x1C50;
183 else if( c >= 0x1C40 ) // lepcha digits
184 value = c - 0x1C40;
185 else if( c >= 0x1BB0 ) // sundanese digits
186 value = c - 0x1BB0;
187 else if( c >= 0x1B50 ) // balinese digits
188 value = c - 0x1B50;
189 else if( c >= 0x1A90 ) // tai tham tham digits
190 value = c - 0x1A90;
191 else if( c >= 0x1A80 ) // tai tham hora digits
192 value = c - 0x1A80;
193 else if( c >= 0x19D0 ) // new tai lue digits
194 value = c - 0x19D0;
195 else if( c >= 0x1946 ) // limbu digits
196 value = c - 0x1946;
197 else if( c >= 0x1810 ) // mongolian digits
198 value = c - 0x1810;
199 else if( c >= 0x17E0 ) // khmer digits
200 value = c - 0x17E0;
201 else if( c >= 0x1090 ) // myanmar shan digits
202 value = c - 0x1090;
203 else if( c >= 0x1040 ) // myanmar digits
204 value = c - 0x1040;
205 else if( c >= 0x0F20 ) // tibetan digits
206 value = c - 0x0F20;
207 else if( c >= 0x0ED0 ) // lao digits
208 value = c - 0x0ED0;
209 else if( c >= 0x0E50 ) // thai digits
210 value = c - 0x0E50;
211 else if( c >= 0x0D66 ) // malayalam digits
212 value = c - 0x0D66;
213 else if( c >= 0x0CE6 ) // kannada digits
214 value = c - 0x0CE6;
215 else if( c >= 0x0C66 ) // telugu digits
216 value = c - 0x0C66;
217 else if( c >= 0x0BE6 ) // tamil digits
218 value = c - 0x0BE6;
219 else if( c >= 0x0B66 ) // oriya digits
220 value = c - 0x0B66;
221 else if( c >= 0x0AE6 ) // gujarati digits
222 value = c - 0x0AE6;
223 else if( c >= 0x0A66 ) // gurmukhi digits
224 value = c - 0x0A66;
225 else if( c >= 0x09E6 ) // bengali digits
226 value = c - 0x09E6;
227 else if( c >= 0x0966 ) // devanagari digit
228 value = c - 0x0966;
229 else if( c >= 0x07C0 ) // nko digits
230 value = c - 0x07C0;
231 else if( c >= 0x06F0 ) // extended arabic-indic digits
232 value = c - 0x06F0;
233 else if( c >= 0x0660 ) // arabic-indic digits
234 value = c - 0x0660;
235 result = result * 10 + value;
236 }
237 return result;
238}
239
240using namespace ::com::sun::star;
241
242// convert between sequence of string and comma separated string
243
244::rtl::OUString convertCommaSeparated(
245 uno::Sequence< ::rtl::OUString > const& i_rSeq)
246{
247 ::rtl::OUStringBuffer buf;
248 ::comphelper::intersperse(
249 ::comphelper::stl_begin(i_rSeq), ::comphelper::stl_end(i_rSeq),
250 ::comphelper::OUStringBufferAppender(buf),
251 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ", " )(&(", ")[0]), ((sal_Int32)((sizeof (", ") / sizeof ((", "
)[0]))-1)), (((rtl_TextEncoding) 11))
));
252 return buf.makeStringAndClear();
253}
254
255uno::Sequence< ::rtl::OUString >
256 convertCommaSeparated( ::rtl::OUString const& i_rString )
257{
258 std::vector< ::rtl::OUString > vec;
259 sal_Int32 idx = 0;
260 do {
261 ::rtl::OUString kw =
262 i_rString.getToken(0, static_cast<sal_Unicode> (','), idx);
263 kw = kw.trim();
264 if (!kw.isEmpty()) {
265 vec.push_back(kw);
266 }
267 } while (idx >= 0);
268 uno::Sequence< ::rtl::OUString > kws(vec.size());
269 std::copy(vec.begin(), vec.end(), stl_begin(kws));
270 return kws;
271}
272
273
274sal_Int32 compareNatural( const ::rtl::OUString & rLHS, const ::rtl::OUString & rRHS,
275 const uno::Reference< i18n::XCollator > &rCollator,
276 const uno::Reference< i18n::XBreakIterator > &rBI,
277 const lang::Locale &rLocale )
278{
279 sal_Int32 nRet = 0;
280
281 sal_Int32 nLHSLastNonDigitPos = 0;
282 sal_Int32 nRHSLastNonDigitPos = 0;
283 sal_Int32 nLHSFirstDigitPos = 0;
284 sal_Int32 nRHSFirstDigitPos = 0;
285
286 while (nLHSFirstDigitPos < rLHS.getLength() || nRHSFirstDigitPos < rRHS.getLength())
287 {
288 sal_Int32 nLHSChunkLen;
289 sal_Int32 nRHSChunkLen;
290
291 //Compare non digit block as normal strings
292 nLHSFirstDigitPos = rBI->nextCharBlock(rLHS, nLHSLastNonDigitPos,
293 rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER);
294 nRHSFirstDigitPos = rBI->nextCharBlock(rRHS, nRHSLastNonDigitPos,
295 rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER);
296 if (nLHSFirstDigitPos == -1)
297 nLHSFirstDigitPos = rLHS.getLength();
298 if (nRHSFirstDigitPos == -1)
299 nRHSFirstDigitPos = rRHS.getLength();
300 nLHSChunkLen = nLHSFirstDigitPos - nLHSLastNonDigitPos;
301 nRHSChunkLen = nRHSFirstDigitPos - nRHSLastNonDigitPos;
302
303 nRet = rCollator->compareSubstring(rLHS, nLHSLastNonDigitPos,
304 nLHSChunkLen, rRHS, nRHSLastNonDigitPos, nRHSChunkLen);
305 if (nRet != 0)
306 break;
307
308 //Compare digit block as one number vs another
309 nLHSLastNonDigitPos = rBI->endOfCharBlock(rLHS, nLHSFirstDigitPos,
310 rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER);
311 nRHSLastNonDigitPos = rBI->endOfCharBlock(rRHS, nRHSFirstDigitPos,
312 rLocale, i18n::CharType::DECIMAL_DIGIT_NUMBER);
313 if (nLHSLastNonDigitPos == -1)
314 nLHSLastNonDigitPos = rLHS.getLength();
315 if (nRHSLastNonDigitPos == -1)
316 nRHSLastNonDigitPos = rRHS.getLength();
317 nLHSChunkLen = nLHSLastNonDigitPos - nLHSFirstDigitPos;
318 nRHSChunkLen = nRHSLastNonDigitPos - nRHSFirstDigitPos;
319
320 //To-Do: Possibly scale down those unicode codepoints that relate to
321 //numbers outside of the normal 0-9 range, e.g. see GetLocalizedChar in
322 //vcl
323
324 sal_uInt32 nLHS = comphelper::string::decimalStringToNumber(rLHS.copy(nLHSFirstDigitPos, nLHSChunkLen));
325 sal_uInt32 nRHS = comphelper::string::decimalStringToNumber(rRHS.copy(nRHSFirstDigitPos, nRHSChunkLen));
326
327 nRet = nLHS-nRHS;
328 if (nRet != 0)
329 break;
330 }
331
332 //Squeeze these down to -1, 0, 1 in case it gets casted to a StringCompare
333 if (nRet > 0)
334 nRet = 1;
335 else if (nRet < 0)
336 nRet = -1;
337
338 return nRet;
339}
340
341NaturalStringSorter::NaturalStringSorter(
342 const uno::Reference< uno::XComponentContext > &rContext,
343 const lang::Locale &rLocale) : m_aLocale(rLocale)
344{
345 uno::Reference< lang::XMultiComponentFactory > xFactory(rContext->getServiceManager(),
346 uno::UNO_SET_THROW);
347
348 m_xCollator = uno::Reference< i18n::XCollator >(xFactory->createInstanceWithContext(
349 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.i18n.Collator")(&("com.sun.star.i18n.Collator")[0]), ((sal_Int32)((sizeof
("com.sun.star.i18n.Collator") / sizeof (("com.sun.star.i18n.Collator"
)[0]))-1)), (((rtl_TextEncoding) 11))
), rContext),
350 uno::UNO_QUERY_THROW);
351 m_xCollator->loadDefaultCollator(m_aLocale, 0);
Called C++ object pointer is null
352 m_xBI = uno::Reference< i18n::XBreakIterator >(xFactory->createInstanceWithContext(
353 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.i18n.BreakIterator")(&("com.sun.star.i18n.BreakIterator")[0]), ((sal_Int32)((
sizeof ("com.sun.star.i18n.BreakIterator") / sizeof (("com.sun.star.i18n.BreakIterator"
)[0]))-1)), (((rtl_TextEncoding) 11))
), rContext),
354 uno::UNO_QUERY_THROW);
355}
356
357namespace
358{
359 //do OPER on each element of the string, return false
360 //if any OPER is false, true otherwise
361 template <bool (*OPER)(sal_Unicode), typename T>
362 bool tmpl_is_OPER_AsciiString(const T &rString)
363 {
364 for (sal_Int32 i = 0; i < rString.getLength(); ++i)
365 {
366 if (!OPER(rString[i]))
367 return false;
368 }
369 return true;
370 }
371}
372
373bool isdigitAsciiString(const rtl::OString &rString)
374{
375 return tmpl_is_OPER_AsciiString<isdigitAscii>(rString);
376}
377
378bool isdigitAsciiString(const rtl::OUString &rString)
379{
380 return tmpl_is_OPER_AsciiString<isdigitAscii>(rString);
381}
382
383namespace
384{
385 template <typename T, typename U> T* string_alloc(sal_Int32 nLen)
386 {
387 //Clearly this is somewhat cosy with the sal implmentation
388
389 //rtl_[u]String contains U buffer[1], so an input of nLen
390 //allocates a buffer of nLen + 1 and we'll ensure a null termination
391
392 T* newStr =
393 (sal::static_int_cast< sal_uInt32 >(nLen)
394 <= ((SAL_MAX_UINT32((sal_uInt32) 0xFFFFFFFF) - sizeof (T))
395 / sizeof (U)))
396 ? (T*) rtl_allocateMemory(
397 sizeof (T) + nLen * sizeof (U))
398 : NULL__null;
399
400 if (!newStr)
401 throw std::bad_alloc();
402
403 newStr->refCount = 1;
404 newStr->length = nLen;
405 newStr->buffer[nLen] = 0;
406 return newStr;
407 }
408}
409
410rtl_uString * SAL_CALL rtl_uString_alloc(sal_Int32 nLen)
411{
412 return string_alloc<rtl_uString, sal_Unicode>(nLen);
413}
414
415rtl_String * SAL_CALL rtl_string_alloc(sal_Int32 nLen)
416{
417 return string_alloc<rtl_String, sal_Char>(nLen);
418}
419
420namespace
421{
422 template <typename T, typename O> T tmpl_reverseString(const T &rIn)
423 {
424 if (rIn.isEmpty())
425 return rIn;
426
427 sal_Int32 i = rIn.getLength();
428 O sBuf(i);
429 while (i)
430 sBuf.append(rIn[--i]);
431 return sBuf.makeStringAndClear();
432 }
433}
434
435rtl::OUString reverseString(const rtl::OUString &rStr)
436{
437 return tmpl_reverseString<rtl::OUString, rtl::OUStringBuffer>(rStr);
438}
439
440rtl::OString reverseString(const rtl::OString &rStr)
441{
442 return tmpl_reverseString<rtl::OString, rtl::OStringBuffer>(rStr);
443}
444
445
446} }
447
448/* vim:set shiftwidth=4 softtabstop=4 expandtab: */