language/duchain
indexedstring.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "indexedstring.h"
00015 #include "repositories/stringrepository.h"
00016
00017 #include <kurl.h>
00018 #include "referencecounting.h"
00019
00020 namespace KDevelop {
00021 namespace {
00022
00023 struct IndexedStringData {
00024 unsigned short length;
00025 unsigned int refCount;
00026 unsigned int itemSize() const {
00027 return sizeof(IndexedStringData) + length;
00028 }
00029 unsigned int hash() const {
00030 IndexedString::RunningHash running;
00031 const char* str = ((const char*)this) + sizeof(IndexedStringData);
00032 for(int a = length-1; a >= 0; --a) {
00033 running.append(*str);
00034 ++str;
00035 }
00036 return running.hash;
00037
00038 }
00039 };
00040
00041 inline void increase(uint& val) {
00042 ++val;
00043 }
00044
00045 inline void decrease(uint& val) {
00046 --val;
00047 }
00048
00049 struct IndexedStringRepositoryItemRequest {
00050
00051
00052 IndexedStringRepositoryItemRequest(const char* text, unsigned int hash, unsigned short length) : m_hash(hash), m_length(length), m_text(text) {
00053 }
00054
00055 enum {
00056 AverageSize = 10
00057 };
00058
00059 typedef unsigned int HashType;
00060
00061
00062 HashType hash() const {
00063 return m_hash;
00064 }
00065
00066
00067 size_t itemSize() const {
00068 return sizeof(IndexedStringData) + m_length;
00069 }
00070
00071
00072 void createItem(IndexedStringData* item) const {
00073 item->length = m_length;
00074 item->refCount = 0;
00075 ++item;
00076 memcpy(item, m_text, m_length);
00077 }
00078
00079 static void destroy(IndexedStringData* item, KDevelop::AbstractItemRepository&) {
00080 Q_UNUSED(item);
00081
00082 }
00083
00084 static bool persistent(const IndexedStringData* item) {
00085 return (bool)item->refCount;
00086 }
00087
00088
00089 bool equals(const IndexedStringData* item) const {
00090 return item->length == m_length && (memcmp(++item, m_text, m_length) == 0);
00091 }
00092 unsigned int m_hash;
00093 unsigned short m_length;
00094 const char* m_text;
00095 };
00096
00097 typedef ItemRepository<IndexedStringData, IndexedStringRepositoryItemRequest, false, true> IndexedStringRepository;
00098
00100 inline QString stringFromItem(const IndexedStringData* item) {
00101 const unsigned short* textPos = (unsigned short*)(item+1);
00102 return QString::fromUtf8((char*)textPos, item->length);
00103 }
00104
00105 inline QByteArray arrayFromItem(const IndexedStringData* item) {
00106 const unsigned short* textPos = (unsigned short*)(item+1);
00107 return QByteArray((char*)textPos, item->length);
00108 }
00109 }
00110
00111 namespace {
00112 RepositoryManager< IndexedStringRepository >& getGlobalIndexedStringRepository(){
00113 static RepositoryManager< IndexedStringRepository > globalIndexedStringRepository("String Index");
00114 return globalIndexedStringRepository;
00115 }
00116 }
00117
00118 IndexedString::IndexedString() : m_index(0) {
00119 }
00120
00123 IndexedString::IndexedString( const char* str, unsigned short length, unsigned int hash ) {
00124 if(!length)
00125 m_index = 0;
00126 else if(length == 1)
00127 m_index = 0xffff0000 | str[0];
00128 else {
00129 QMutexLocker lock(getGlobalIndexedStringRepository()->mutex());
00130
00131 m_index = getGlobalIndexedStringRepository()->index(IndexedStringRepositoryItemRequest(str, hash ? hash : hashString(str, length), length));
00132
00133 if(shouldDoDUChainReferenceCounting(this))
00134 increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount);
00135 }
00136 }
00137
00138 IndexedString::IndexedString( char c ) {
00139 m_index = 0xffff0000 | c;
00140 }
00141
00142 IndexedString::IndexedString( const KUrl& url ) {
00143 QByteArray array(url.pathOrUrl().toUtf8());
00144
00145 const char* str = array.constData();
00146
00147 int size = array.size();
00148
00149 if(!size)
00150 m_index = 0;
00151 else if(size == 1)
00152 m_index = 0xffff0000 | str[0];
00153 else {
00154 QMutexLocker lock(getGlobalIndexedStringRepository()->mutex());
00155 m_index = getGlobalIndexedStringRepository()->index(IndexedStringRepositoryItemRequest(str, hashString(str, size), size));
00156
00157 if(shouldDoDUChainReferenceCounting(this))
00158 increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount);
00159 }
00160 }
00161
00162 IndexedString::IndexedString( const QString& string ) {
00163 QByteArray array(string.toUtf8());
00164
00165 const char* str = array.constData();
00166
00167 int size = array.size();
00168
00169 if(!size)
00170 m_index = 0;
00171 else if(size == 1)
00172 m_index = 0xffff0000 | str[0];
00173 else {
00174 QMutexLocker lock(getGlobalIndexedStringRepository()->mutex());
00175 m_index = getGlobalIndexedStringRepository()->index(IndexedStringRepositoryItemRequest(str, hashString(str, size), size));
00176
00177 if(shouldDoDUChainReferenceCounting(this))
00178 increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount);
00179 }
00180 }
00181
00182 IndexedString::IndexedString( const char* str) {
00183 unsigned int length = strlen(str);
00184 if(!length)
00185 m_index = 0;
00186 else if(length == 1)
00187 m_index = 0xffff0000 | str[0];
00188 else {
00189 QMutexLocker lock(getGlobalIndexedStringRepository()->mutex());
00190 m_index = getGlobalIndexedStringRepository()->index(IndexedStringRepositoryItemRequest(str, hashString(str, length), length));
00191
00192 if(shouldDoDUChainReferenceCounting(this))
00193 increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount);
00194 }
00195 }
00196
00197 IndexedString::IndexedString( const QByteArray& str) {
00198 unsigned int length = str.length();
00199 if(!length)
00200 m_index = 0;
00201 else if(length == 1)
00202 m_index = 0xffff0000 | str[0];
00203 else {
00204 QMutexLocker lock(getGlobalIndexedStringRepository()->mutex());
00205 m_index = getGlobalIndexedStringRepository()->index(IndexedStringRepositoryItemRequest(str, hashString(str, length), length));
00206
00207 if(shouldDoDUChainReferenceCounting(this))
00208 increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount);
00209 }
00210 }
00211
00212 IndexedString::~IndexedString() {
00213 if(m_index && (m_index & 0xffff0000) != 0xffff0000) {
00214 if(shouldDoDUChainReferenceCounting(this)) {
00215 QMutexLocker lock(getGlobalIndexedStringRepository()->mutex());
00216
00217 decrease(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount);
00218 }
00219 }
00220 }
00221
00222 IndexedString::IndexedString( const IndexedString& rhs ) : m_index(rhs.m_index) {
00223 if(m_index && (m_index & 0xffff0000) != 0xffff0000) {
00224 if(shouldDoDUChainReferenceCounting(this)) {
00225 QMutexLocker lock(getGlobalIndexedStringRepository()->mutex());
00226 increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount);
00227 }
00228 }
00229 }
00230
00231 IndexedString& IndexedString::operator=(const IndexedString& rhs) {
00232 if(m_index == rhs.m_index)
00233 return *this;
00234 if(m_index && (m_index & 0xffff0000) != 0xffff0000) {
00235
00236 if(shouldDoDUChainReferenceCounting(this)) {
00237 QMutexLocker lock(getGlobalIndexedStringRepository()->mutex());
00238 decrease(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount);
00239 }
00240 }
00241
00242 m_index = rhs.m_index;
00243
00244 if(m_index && (m_index & 0xffff0000) != 0xffff0000) {
00245 if(shouldDoDUChainReferenceCounting(this)) {
00246 QMutexLocker lock(getGlobalIndexedStringRepository()->mutex());
00247 increase(getGlobalIndexedStringRepository()->dynamicItemFromIndexSimple(m_index)->refCount);
00248 }
00249 }
00250
00251 return *this;
00252 }
00253
00254
00255 KUrl IndexedString::toUrl() const {
00256 KUrl url( str() );
00257 return url;
00258 }
00259
00260 QString IndexedString::str() const {
00261 if(!m_index)
00262 return QString();
00263 else if((m_index & 0xffff0000) == 0xffff0000)
00264 return QString(QChar((char)m_index & 0xff));
00265 else
00266 return stringFromItem(getGlobalIndexedStringRepository()->itemFromIndex(m_index));
00267 }
00268
00269 int IndexedString::length() const {
00270 if(!m_index)
00271 return 0;
00272 else if((m_index & 0xffff0000) == 0xffff0000)
00273 return 1;
00274 else
00275 return getGlobalIndexedStringRepository()->itemFromIndex(m_index)->length;
00276 }
00277
00278 QByteArray IndexedString::byteArray() const {
00279 if(!m_index)
00280 return QByteArray();
00281 else if((m_index & 0xffff0000) == 0xffff0000)
00282 return QString(QChar((char)m_index & 0xff)).toUtf8();
00283 else
00284 return arrayFromItem(getGlobalIndexedStringRepository()->itemFromIndex(m_index));
00285 }
00286
00287 unsigned int IndexedString::hashString(const char* str, unsigned short length) {
00288 RunningHash running;
00289 for(int a = length-1; a >= 0; --a) {
00290 running.append(*str);
00291 ++str;
00292 }
00293 return running.hash;
00294 }
00295
00296
00297 }