Tokenizer.cpp 4.5 KB

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