1 /*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9 #include "src/core/SkTSearch.h"
10
11 #include "include/private/SkMalloc.h"
12
13 #include <ctype.h>
14
index_into_base(const char * const * base,int index,size_t elemSize)15 static inline const char* index_into_base(const char*const* base, int index,
16 size_t elemSize)
17 {
18 return *(const char*const*)((const char*)base + index * elemSize);
19 }
20
SkStrSearch(const char * const * base,int count,const char target[],size_t target_len,size_t elemSize)21 int SkStrSearch(const char*const* base, int count, const char target[],
22 size_t target_len, size_t elemSize)
23 {
24 if (count <= 0)
25 return ~0;
26
27 SkASSERT(base != nullptr);
28
29 int lo = 0;
30 int hi = count - 1;
31
32 while (lo < hi)
33 {
34 int mid = (hi + lo) >> 1;
35 const char* elem = index_into_base(base, mid, elemSize);
36
37 int cmp = strncmp(elem, target, target_len);
38 if (cmp < 0)
39 lo = mid + 1;
40 else if (cmp > 0 || strlen(elem) > target_len)
41 hi = mid;
42 else
43 return mid;
44 }
45
46 const char* elem = index_into_base(base, hi, elemSize);
47 int cmp = strncmp(elem, target, target_len);
48 if (cmp || strlen(elem) > target_len)
49 {
50 if (cmp < 0)
51 hi += 1;
52 hi = ~hi;
53 }
54 return hi;
55 }
56
SkStrSearch(const char * const * base,int count,const char target[],size_t elemSize)57 int SkStrSearch(const char*const* base, int count, const char target[],
58 size_t elemSize)
59 {
60 return SkStrSearch(base, count, target, strlen(target), elemSize);
61 }
62
SkStrLCSearch(const char * const * base,int count,const char target[],size_t len,size_t elemSize)63 int SkStrLCSearch(const char*const* base, int count, const char target[],
64 size_t len, size_t elemSize)
65 {
66 SkASSERT(target);
67
68 SkAutoAsciiToLC tolc(target, len);
69
70 return SkStrSearch(base, count, tolc.lc(), len, elemSize);
71 }
72
SkStrLCSearch(const char * const * base,int count,const char target[],size_t elemSize)73 int SkStrLCSearch(const char*const* base, int count, const char target[],
74 size_t elemSize)
75 {
76 return SkStrLCSearch(base, count, target, strlen(target), elemSize);
77 }
78
79 //////////////////////////////////////////////////////////////////////////////
80
SkAutoAsciiToLC(const char str[],size_t len)81 SkAutoAsciiToLC::SkAutoAsciiToLC(const char str[], size_t len)
82 {
83 // see if we need to compute the length
84 if ((long)len < 0) {
85 len = strlen(str);
86 }
87 fLength = len;
88
89 // assign lc to our preallocated storage if len is small enough, or allocate
90 // it on the heap
91 char* lc;
92 if (len <= STORAGE) {
93 lc = fStorage;
94 } else {
95 lc = (char*)sk_malloc_throw(len + 1);
96 }
97 fLC = lc;
98
99 // convert any asii to lower-case. we let non-ascii (utf8) chars pass
100 // through unchanged
101 for (int i = (int)(len - 1); i >= 0; --i) {
102 int c = str[i];
103 if ((c & 0x80) == 0) { // is just ascii
104 c = tolower(c);
105 }
106 lc[i] = c;
107 }
108 lc[len] = 0;
109 }
110
~SkAutoAsciiToLC()111 SkAutoAsciiToLC::~SkAutoAsciiToLC()
112 {
113 if (fLC != fStorage) {
114 sk_free(fLC);
115 }
116 }
117