blob: be3a239836b7c7f32ebb31fb9e6cfa8bb55be76c [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
18
19#include "Tokenizer.h"
20
21// ----------------------------------------------------------------------------
22
23namespace android {
24
25ANDROID_BASIC_TYPES_TRAITS(Tokenizer::run_t)
26
27Tokenizer::Tokenizer()
28{
29}
30
31Tokenizer::Tokenizer(const Tokenizer& other)
32 : mRanges(other.mRanges)
33{
34}
35
36Tokenizer::~Tokenizer()
37{
38}
39
40uint32_t Tokenizer::acquire()
41{
42 if (!mRanges.size() || mRanges[0].first) {
43 _insertTokenAt(0,0);
44 return 0;
45 }
46
47 // just extend the first run
48 const run_t& run = mRanges[0];
49 uint32_t token = run.first + run.length;
50 _insertTokenAt(token, 1);
51 return token;
52}
53
54bool Tokenizer::isAcquired(uint32_t token) const
55{
56 return (_indexOrderOf(token) >= 0);
57}
58
59status_t Tokenizer::reserve(uint32_t token)
60{
61 size_t o;
62 const ssize_t i = _indexOrderOf(token, &o);
63 if (i >= 0) {
64 return BAD_VALUE; // this token is already taken
65 }
66 ssize_t err = _insertTokenAt(token, o);
67 return (err<0) ? err : status_t(NO_ERROR);
68}
69
70status_t Tokenizer::release(uint32_t token)
71{
72 const ssize_t i = _indexOrderOf(token);
73 if (i >= 0) {
74 const run_t& run = mRanges[i];
75 if ((token >= run.first) && (token < run.first+run.length)) {
76 // token in this range, we need to split
77 run_t& run = mRanges.editItemAt(i);
78 if ((token == run.first) || (token == run.first+run.length-1)) {
79 if (token == run.first) {
80 run.first += 1;
81 }
82 run.length -= 1;
83 if (run.length == 0) {
84 // XXX: should we systematically remove a run that's empty?
85 mRanges.removeItemsAt(i);
86 }
87 } else {
88 // split the run
89 run_t new_run;
90 new_run.first = token+1;
91 new_run.length = run.first+run.length - new_run.first;
92 run.length = token - run.first;
93 mRanges.insertAt(new_run, i+1);
94 }
95 return NO_ERROR;
96 }
97 }
98 return NAME_NOT_FOUND;
99}
100
101ssize_t Tokenizer::_indexOrderOf(uint32_t token, size_t* order) const
102{
103 // binary search
104 ssize_t err = NAME_NOT_FOUND;
105 ssize_t l = 0;
106 ssize_t h = mRanges.size()-1;
107 ssize_t mid;
108 const run_t* a = mRanges.array();
109 while (l <= h) {
110 mid = l + (h - l)/2;
111 const run_t* const curr = a + mid;
112 int c = 0;
113 if (token < curr->first) c = 1;
114 else if (token >= curr->first+curr->length) c = -1;
115 if (c == 0) {
116 err = l = mid;
117 break;
118 } else if (c < 0) {
119 l = mid + 1;
120 } else {
121 h = mid - 1;
122 }
123 }
124 if (order) *order = l;
125 return err;
126}
127
128ssize_t Tokenizer::_insertTokenAt(uint32_t token, size_t index)
129{
130 const size_t c = mRanges.size();
131
132 if (index >= 1) {
133 // do we need to merge with the previous run?
134 run_t& p = mRanges.editItemAt(index-1);
135 if (p.first+p.length == token) {
136 p.length += 1;
137 if (index < c) {
138 const run_t& n = mRanges[index];
139 if (token+1 == n.first) {
140 p.length += n.length;
141 mRanges.removeItemsAt(index);
142 }
143 }
144 return index;
145 }
146 }
147
148 if (index < c) {
149 // do we need to merge with the next run?
150 run_t& n = mRanges.editItemAt(index);
151 if (token+1 == n.first) {
152 n.first -= 1;
153 n.length += 1;
154 return index;
155 }
156 }
157
158 return mRanges.insertAt(run_t(token,1), index);
159}
160
161void Tokenizer::dump() const
162{
163 const run_t* ranges = mRanges.array();
164 const size_t c = mRanges.size();
Mathias Agopian1473f462009-04-10 14:24:30 -0700165 printf("Tokenizer (%p, size = %d)\n", this, int(c));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 for (size_t i=0 ; i<c ; i++) {
Mathias Agopian1473f462009-04-10 14:24:30 -0700167 printf("%u: (%u, %u)\n", i,
168 uint32_t(ranges[i].first), uint32_t(ranges[i].length));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 }
170}
171
172}; // namespace android
173