utf-8-case.cpp revision 14380feae039b4eb5a70e053e186000c706ff358
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync/* $Id$ */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync/** @file
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * IPRT - UTF-8 Case Sensitivity and Folding.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync/*
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2006-2009 Oracle Corporation
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync *
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * available from http://www.virtualbox.org. This file is free software;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * General Public License (GPL) as published by the Free Software
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync *
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * The contents of this file may alternatively be used under the terms
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * of the Common Development and Distribution License Version 1.0
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * CDDL are applicable instead of those of the GPL.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync *
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * You may elect to license modified versions of this file under the
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * terms and conditions of either the GPL or the CDDL or both.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync/*******************************************************************************
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync* Header Files *
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync*******************************************************************************/
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync#include <iprt/string.h>
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync#include "internal/iprt.h"
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync#include <iprt/uni.h>
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync#include <iprt/alloc.h>
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync#include <iprt/assert.h>
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync#include <iprt/err.h>
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync#include "internal/string.h"
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync/**
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * Performs a case insensitive string compare between two UTF-8 strings.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync *
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * This is a simplified compare, as only the simplified lower/upper case folding
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * specified by the unicode specs are used. It does not consider character pairs
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * as they are used in some languages, just simple upper & lower case compares.
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync *
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * The result is the difference between the mismatching codepoints after they
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * both have been lower cased.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync *
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * If the string encoding is invalid the function will assert (strict builds)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * and use RTStrCmp for the remainder of the string.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync *
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * @returns < 0 if the first string less than the second string.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * @returns 0 if the first string identical to the second string.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * @returns > 0 if the first string greater than the second string.
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync * @param psz1 First UTF-8 string. Null is allowed.
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync * @param psz2 Second UTF-8 string. Null is allowed.
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync */
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsyncRTDECL(int) RTStrICmp(const char *psz1, const char *psz2)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync{
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (psz1 == psz2)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync return 0;
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (!psz1)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync return -1;
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (!psz2)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync return 1;
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync const char *pszStart1 = psz1;
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync for (;;)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync {
4e3469ac31db1401d787d60312d2179bc09757b9vboxsync /* Get the codepoints */
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync RTUNICP cp1;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync int rc = RTStrGetCpEx(&psz1, &cp1);
230bd8589bba39933ac5ec21482d6186d675e604vboxsync if (RT_FAILURE(rc))
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync {
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync AssertRC(rc);
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync psz1--;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync break;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync }
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync RTUNICP cp2;
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync rc = RTStrGetCpEx(&psz2, &cp2);
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (RT_FAILURE(rc))
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync {
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync AssertRC(rc);
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync psz2--;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync psz1 = RTStrPrevCp(pszStart1, psz1);
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync break;
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync }
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync /* compare */
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync int iDiff = cp1 - cp2;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (iDiff)
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync {
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync iDiff = RTUniCpToUpper(cp1) != RTUniCpToUpper(cp2);
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (iDiff)
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync {
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync iDiff = RTUniCpToLower(cp1) - RTUniCpToLower(cp2); /* lower case diff last! */
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (iDiff)
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync return iDiff;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync }
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync }
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync /* hit the terminator? */
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (!cp1)
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync return 0;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync }
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync /* Hit some bad encoding, continue in case sensitive mode. */
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync return RTStrCmp(psz1, psz2);
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync}
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsyncRT_EXPORT_SYMBOL(RTStrICmp);
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync/**
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * Performs a case insensitive string compare between two UTF-8 strings, given a
d1966fe9681e9a100f8c895f08e450fc32dafd48vboxsync * maximum string length.
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync *
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * This is a simplified compare, as only the simplified lower/upper case folding
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * specified by the unicode specs are used. It does not consider character pairs
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * as they are used in some languages, just simple upper & lower case compares.
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync *
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * The result is the difference between the mismatching codepoints after they
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * both have been lower cased.
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync *
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * If the string encoding is invalid the function will assert (strict builds)
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * and use RTStrCmp for the remainder of the string.
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync *
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * @returns < 0 if the first string less than the second string.
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * @returns 0 if the first string identical to the second string.
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync * @returns > 0 if the first string greater than the second string.
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * @param psz1 First UTF-8 string. Null is allowed.
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * @param psz2 Second UTF-8 string. Null is allowed.
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync * @param cchMax Maximum string length
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync */
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsyncRTDECL(int) RTStrNICmp(const char *psz1, const char *psz2, size_t cchMax)
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync{
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (cchMax == 0)
4e3469ac31db1401d787d60312d2179bc09757b9vboxsync return 0;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (psz1 == psz2)
4e3469ac31db1401d787d60312d2179bc09757b9vboxsync return 0;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (!psz1)
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync return -1;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (!psz2)
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync return 1;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync for (;;)
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync {
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync /* Get the codepoints */
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync RTUNICP cp1;
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync size_t cchMax2 = cchMax;
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync int rc = RTStrGetCpNEx(&psz1, &cchMax, &cp1);
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync if (RT_FAILURE(rc))
e6475eda5d15be9afba6cdbaca6d2d324d37bb05vboxsync {
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync AssertRC(rc);
8e03ddcc7e406ba01ce5adb465bc1bb034681b40vboxsync psz1--;
eb164f7d77f5b3bee0fe6fbdd46521550e3306c4vboxsync cchMax++;
343a0f715a7abe21308b4a564698ab9c93473fcavboxsync break;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync }
4e3469ac31db1401d787d60312d2179bc09757b9vboxsync
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync RTUNICP cp2;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync rc = RTStrGetCpNEx(&psz2, &cchMax2, &cp2);
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync if (RT_FAILURE(rc))
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync {
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync AssertRC(rc);
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync psz2--;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync psz1 -= (cchMax - cchMax2 + 1); /* This can't overflow, can it? */
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync cchMax = cchMax2 + 1;
468c2bcb36eb9a032f5dd0fcb34db10bd58e9996vboxsync break;
9ac9eda1e04d193f54339eaeffe1c8b2f8ea04b1vboxsync }
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync /* compare */
230bd8589bba39933ac5ec21482d6186d675e604vboxsync int iDiff = cp1 - cp2;
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (iDiff)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync {
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync iDiff = RTUniCpToUpper(cp1) != RTUniCpToUpper(cp2);
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (iDiff)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync {
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync iDiff = RTUniCpToLower(cp1) - RTUniCpToLower(cp2); /* lower case diff last! */
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (iDiff)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync return iDiff;
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync }
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync }
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync /* hit the terminator? */
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (!cp1 || cchMax == 0)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync return 0;
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync }
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync /* Hit some bad encoding, continue in case insensitive mode. */
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync return RTStrNCmp(psz1, psz2, cchMax);
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync}
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsyncRT_EXPORT_SYMBOL(RTStrNICmp);
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync
cd899b2444ca69566bd04cfac96828714d3bd1b0vboxsync
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsyncRTDECL(char *) RTStrIStr(const char *pszHaystack, const char *pszNeedle)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync{
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync /* Any NULL strings means NULL return. (In the RTStrCmp tradition.) */
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (!pszHaystack)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync return NULL;
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (!pszNeedle)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync return NULL;
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync /* The empty string matches everything. */
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync if (!*pszNeedle)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync return (char *)pszHaystack;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
230bd8589bba39933ac5ec21482d6186d675e604vboxsync /*
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * The search strategy is to pick out the first char of the needle, fold it,
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * and match it against the haystack code point by code point. When encountering
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * a matching code point we use RTStrNICmp for the remainder (if any) of the needle.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync const char * const pszNeedleStart = pszNeedle;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTUNICP Cp0;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTStrGetCpEx(&pszNeedle, &Cp0); /* pszNeedle is advanced one code point. */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync size_t const cchNeedle = strlen(pszNeedle);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync size_t const cchNeedleCp0= pszNeedle - pszNeedleStart;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTUNICP const Cp0Lower = RTUniCpToLower(Cp0);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTUNICP const Cp0Upper = RTUniCpToUpper(Cp0);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if ( Cp0Lower == Cp0Upper
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync && Cp0Lower == Cp0)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /* Cp0 is not a case sensitive char. */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync for (;;)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTUNICP Cp;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTStrGetCpEx(&pszHaystack, &Cp);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if (!Cp)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync break;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if ( Cp == Cp0
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync && !RTStrNICmp(pszHaystack, pszNeedle, cchNeedle))
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync return (char *)pszHaystack - cchNeedleCp0;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync else if ( Cp0Lower == Cp0
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync || Cp0Upper != Cp0)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
cd899b2444ca69566bd04cfac96828714d3bd1b0vboxsync /* Cp0 is case sensitive */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync for (;;)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTUNICP Cp;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTStrGetCpEx(&pszHaystack, &Cp);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if (!Cp)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync break;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if ( ( Cp == Cp0Upper
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync || Cp == Cp0Lower)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync && !RTStrNICmp(pszHaystack, pszNeedle, cchNeedle))
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync return (char *)pszHaystack - cchNeedleCp0;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync else
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /* Cp0 is case sensitive and folds to two difference chars. (paranoia) */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync for (;;)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTUNICP Cp;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTStrGetCpEx(&pszHaystack, &Cp);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if (!Cp)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync break;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync if ( ( Cp == Cp0
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync || Cp == Cp0Upper
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync || Cp == Cp0Lower)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync && !RTStrNICmp(pszHaystack, pszNeedle, cchNeedle))
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync return (char *)pszHaystack - cchNeedleCp0;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync return NULL;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync}
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsyncRT_EXPORT_SYMBOL(RTStrIStr);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsyncRTDECL(char *) RTStrToLower(char *psz)
4ee5a4cd660730c997785c6cbc12881a115079e8vboxsync{
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /*
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * Loop the code points in the string, converting them one by one.
230bd8589bba39933ac5ec21482d6186d675e604vboxsync * ASSUMES that the code points for upper and lower case are encoded
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * with the exact same length.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /** @todo Handled bad encodings correctly+quietly, remove assumption,
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * optimize. */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync char *pszCur = psz;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync while (*pszCur)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTUNICP cp = RTStrGetCp(pszCur);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync cp = RTUniCpToLower(cp);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync pszCur = RTStrPutCp(pszCur, cp);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync return psz;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync}
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsyncRT_EXPORT_SYMBOL(RTStrToLower);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsyncRTDECL(char *) RTStrToUpper(char *psz)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync{
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /*
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * Loop the code points in the string, converting them one by one.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * ASSUMES that the code points for upper and lower case are encoded
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * with the exact same length.
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync /** @todo Handled bad encodings correctly+quietly, remove assumption,
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync * optimize. */
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync char *pszCur = psz;
cd899b2444ca69566bd04cfac96828714d3bd1b0vboxsync while(*pszCur)
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync {
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync RTUNICP cp = RTStrGetCp(pszCur);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync cp = RTUniCpToUpper(cp);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync pszCur = RTStrPutCp(pszCur, cp);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync }
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync return psz;
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync}
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsyncRT_EXPORT_SYMBOL(RTStrToUpper);
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync
b1d7d513c459787311cd09c440524044fa7ff8a9vboxsync