PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/src/main/java/com/alibaba/fastjson/parser/SymbolTable.java

https://bitbucket.org/xiejuntao/xdesktop
Java | 165 lines | 105 code | 28 blank | 32 comment | 23 complexity | 7d6c572aaec076cc2173fa0afb80eb4a MD5 | raw file
  1. /*
  2. * Copyright 1999-2101 Alibaba Group.
  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. package com.alibaba.fastjson.parser;
  17. /**
  18. * @author wenshao<szujobs@hotmail.com>
  19. */
  20. public class SymbolTable {
  21. public static final int DEFAULT_TABLE_SIZE = 128;
  22. public static final int MAX_BUCKET_LENTH = 8;
  23. public static final int MAX_SIZE = 1024;
  24. private final Entry[] buckets;
  25. private final String[] symbols;
  26. private final char[][] symbols_char;
  27. private final int indexMask;
  28. private int size = 0;
  29. public SymbolTable(){
  30. this(DEFAULT_TABLE_SIZE);
  31. }
  32. public SymbolTable(int tableSize){
  33. this.indexMask = tableSize - 1;
  34. this.buckets = new Entry[tableSize];
  35. this.symbols = new String[tableSize];
  36. this.symbols_char = new char[tableSize][];
  37. }
  38. public String addSymbol(char[] buffer, int offset, int len) {
  39. // search for identical symbol
  40. int hash = hash(buffer, offset, len);
  41. return addSymbol(buffer, offset, len, hash);
  42. }
  43. /**
  44. * Adds the specified symbol to the symbol table and returns a reference to the unique symbol. If the symbol already
  45. * exists, the previous symbol reference is returned instead, in order guarantee that symbol references remain
  46. * unique.
  47. *
  48. * @param buffer The buffer containing the new symbol.
  49. * @param offset The offset into the buffer of the new symbol.
  50. * @param len The length of the new symbol in the buffer.
  51. */
  52. public String addSymbol(char[] buffer, int offset, int len, int hash) {
  53. // int bucket = indexFor(hash, tableSize);
  54. final int bucket = hash & indexMask;
  55. String sym = symbols[bucket];
  56. boolean match = true;
  57. if (sym != null) {
  58. if (sym.length() == len) {
  59. char[] characters = symbols_char[bucket];
  60. for (int i = 0; i < len; i++) {
  61. if (buffer[offset + i] != characters[i]) {
  62. match = false;
  63. break;
  64. }
  65. }
  66. if (match) {
  67. return sym;
  68. }
  69. } else {
  70. match = false;
  71. }
  72. }
  73. {
  74. int entryIndex = 0;
  75. for (Entry entry = buckets[bucket]; entry != null; entry = entry.next) {
  76. char[] characters = entry.characters;
  77. if (len == characters.length && hash == entry.hashCode) {
  78. boolean eq = true;
  79. for (int i = 0; i < len; i++) {
  80. if (buffer[offset + i] != characters[i]) {
  81. eq = false;
  82. break;
  83. }
  84. }
  85. if (!eq) {
  86. entryIndex++;
  87. continue;
  88. }
  89. return entry.symbol;
  90. }
  91. }
  92. if (entryIndex >= MAX_BUCKET_LENTH) {
  93. return new String(buffer, offset, len);
  94. }
  95. }
  96. if (size >= MAX_SIZE) {
  97. return new String(buffer, offset, len);
  98. }
  99. Entry entry = new Entry(buffer, offset, len, hash, buckets[bucket]);
  100. buckets[bucket] = entry; // 并发是处理时会导致缓存丢失,但不影响正确性
  101. if (match) {
  102. symbols[bucket] = entry.symbol;
  103. symbols_char[bucket] = entry.characters;
  104. }
  105. size++;
  106. return entry.symbol;
  107. }
  108. public int size() {
  109. return size;
  110. }
  111. public static final int hash(char[] buffer, int offset, int len) {
  112. int h = 0;
  113. int off = offset;
  114. for (int i = 0; i < len; i++) {
  115. h = 31 * h + buffer[off++];
  116. }
  117. return h;
  118. }
  119. protected static final class Entry {
  120. public final String symbol;
  121. public final int hashCode;
  122. public final char[] characters;
  123. public final byte[] bytes;
  124. public Entry next;
  125. /**
  126. * Constructs a new entry from the specified symbol information and next entry reference.
  127. */
  128. public Entry(char[] ch, int offset, int length, int hash, Entry next){
  129. characters = new char[length];
  130. System.arraycopy(ch, offset, characters, 0, length);
  131. symbol = new String(characters).intern();
  132. this.next = next;
  133. this.hashCode = hash;
  134. this.bytes = null;
  135. }
  136. }
  137. }