058fc6ceca
X-SVN-Rev: 6532
121 lines
3.1 KiB
C++
121 lines
3.1 KiB
C++
/*
|
|
**********************************************************************
|
|
* Copyright (C) 1999, International Business Machines
|
|
* Corporation and others. All Rights Reserved.
|
|
**********************************************************************
|
|
* Date Name Description
|
|
* 11/17/99 aliu Creation.
|
|
**********************************************************************
|
|
*/
|
|
#include "unirange.h"
|
|
#include "uvector.h"
|
|
#include "unicode/unistr.h"
|
|
|
|
// For UVector of UnicodeRange* objects
|
|
U_CDECL_BEGIN
|
|
static void U_CALLCONV
|
|
UnicodeRange_deleter(void* e) {
|
|
delete (UnicodeRange*) e;
|
|
}
|
|
U_CDECL_END
|
|
|
|
U_NAMESPACE_BEGIN
|
|
|
|
UnicodeRange::UnicodeRange(UChar theStart, int32_t theLength) {
|
|
start = theStart;
|
|
length = theLength;
|
|
}
|
|
|
|
UnicodeRange* UnicodeRange::clone() const {
|
|
return new UnicodeRange(start, length);
|
|
}
|
|
|
|
/**
|
|
* CALLER OWNS RESULT.
|
|
*/
|
|
UBool UnicodeRange::contains(UChar c) const {
|
|
return c >= start && (c - start) < length;
|
|
}
|
|
|
|
/**
|
|
* Assume that contains(c) is true. Split this range into two new
|
|
* ranges around the character c. Make this range one of the new ranges
|
|
* (modify it in place) and return the other new range. The character
|
|
* itself is not included in either range. If the split results in an
|
|
* empty range (that is, if c == start or c == start + length - 1) then
|
|
* return null.
|
|
*
|
|
* MODIFIES THIS RANGE IN PLACE.
|
|
*
|
|
* CALLER OWNS RESULT.
|
|
*/
|
|
UnicodeRange* UnicodeRange::split(UChar c) {
|
|
if (c == start) {
|
|
++start;
|
|
--length;
|
|
return 0;
|
|
} else if (c - start == length - 1) {
|
|
--length;
|
|
return 0;
|
|
} else {
|
|
++c;
|
|
UnicodeRange* r = new UnicodeRange(c, start + length - c);
|
|
length = --c - start;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Finds the largest unused subrange by the given string. A
|
|
* subrange is unused by a string if the string contains no
|
|
* characters in that range. If the given string contains no
|
|
* characters in this range, then this range itself is
|
|
* returned.
|
|
*
|
|
* CALLER OWNS RESULT.
|
|
*/
|
|
UnicodeRange*
|
|
UnicodeRange::largestUnusedSubrange(const UnicodeString& str, UErrorCode &status) const {
|
|
int32_t n = str.length();
|
|
|
|
UVector v(status);
|
|
if (U_FAILURE(status)) {
|
|
return NULL;
|
|
}
|
|
v.setDeleter(UnicodeRange_deleter);
|
|
v.addElement(clone(), status);
|
|
for (int32_t i=0; i<n; ++i) {
|
|
UChar c = str.charAt(i);
|
|
if (contains(c)) {
|
|
for (int32_t j=0; j<v.size(); ++j) {
|
|
UnicodeRange* r = (UnicodeRange*) v.elementAt(j);
|
|
if (r->contains(c)) {
|
|
r = r->split(c);
|
|
if (r != 0) {
|
|
v.addElement(r, status);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
UnicodeRange* bestRange = 0;
|
|
int32_t ibest = -1;
|
|
for (int32_t j=0; j<v.size(); ++j) {
|
|
UnicodeRange* r = (UnicodeRange*) v.elementAt(j);
|
|
if (bestRange == 0 || r->length > bestRange->length) {
|
|
bestRange = r;
|
|
ibest = j;
|
|
}
|
|
}
|
|
|
|
v.orphanElementAt(ibest); // So bestRange doesn't get deleted
|
|
|
|
return bestRange;
|
|
}
|
|
|
|
|
|
U_NAMESPACE_END
|
|
|