summaryrefslogtreecommitdiff
path: root/src/md/ceefilegen/ceesectionstring.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/md/ceefilegen/ceesectionstring.cpp')
-rw-r--r--src/md/ceefilegen/ceesectionstring.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/md/ceefilegen/ceesectionstring.cpp b/src/md/ceefilegen/ceesectionstring.cpp
new file mode 100644
index 0000000000..a1a9e7f17f
--- /dev/null
+++ b/src/md/ceefilegen/ceesectionstring.cpp
@@ -0,0 +1,133 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ===========================================================================
+// File: CeeSectionString.cpp
+//
+
+//
+// ===========================================================================
+#include "stdafx.h"
+
+struct StringTableEntry {
+ ULONG m_hashId;
+ int m_offset;
+ StringTableEntry *m_next;
+};
+
+CeeSectionString::CeeSectionString(CCeeGen &ceeFile, CeeSectionImpl &impl)
+ : CeeSection(ceeFile, impl)
+{
+ memset(stringTable, 0, sizeof(stringTable));
+}
+
+void CeeSectionString::deleteEntries(StringTableEntry *e)
+{
+ if (!e)
+ return;
+ deleteEntries(e->m_next);
+ delete e;
+}
+
+#ifdef RDATA_STATS
+int CeeSectionString::dumpEntries(StringTableEntry *e)
+{
+ if (!e)
+ return 0;
+ else {
+ printf(" HashId: %d, value: %S\n", e->m_hashId, computOffset(e->m_offset));
+ return dumpEntries(e->m_next) + 1;
+ }
+}
+
+void CeeSectionString::dumpTable()
+{
+ int sum = 0, count = 0;
+ for (int i=0; i < MaxRealEntries; i++) {
+ if (stringTable[i]) {
+ printf("Bucket %d\n", i);
+ printf("Total size: %d\n\n",
+ count = dumpEntries(stringTable[i]));
+ sum += count;
+ }
+ }
+ printf("Total number strings: %d\n\n", sum);
+}
+#endif
+
+CeeSectionString::~CeeSectionString()
+{
+#ifdef RDATA_STATS
+ dumpTable();
+#endif
+ for (int i=0; i < MaxRealEntries; i++)
+ deleteEntries(stringTable[i]);
+}
+
+StringTableEntry* CeeSectionString::createEntry(__in_z LPWSTR target, ULONG hashId)
+{
+ StringTableEntry *entry = new StringTableEntry;
+ if (!entry)
+ return NULL;
+ entry->m_next = NULL;
+ entry->m_hashId = hashId;
+ entry->m_offset = dataLen();
+ size_t len = (wcslen(target)+1) * sizeof(wchar_t);
+ if (len > ULONG_MAX) {
+ delete entry;
+ return NULL;
+ }
+ void *buf = getBlock((ULONG)len);
+ if (!buf) {
+ delete entry;
+ return NULL;
+ }
+ memcpy(buf, target, len);
+ return entry;
+}
+
+// Searches through the linked list looking for a match on hashID. If
+// multiple elements hash to the same value, a strcmp must be done to
+// check for match. The goal is to have very large hashId space so that
+// string compares are minimized
+StringTableEntry *CeeSectionString::findStringInsert(
+ StringTableEntry *&head, __in_z LPWSTR target, ULONG hashId)
+{
+ StringTableEntry *cur, *prev;
+ cur = prev = head;
+ while (cur && cur->m_hashId < hashId) {
+ prev = cur;
+ cur = cur->m_next;
+ }
+ while (cur && cur->m_hashId == hashId) {
+ if (wcscmp(target, (LPWSTR)(computePointer(cur->m_offset))) == 0)
+ return cur;
+ prev = cur;
+ cur = cur->m_next;
+ }
+ // didn't find in chain so insert at prev
+ StringTableEntry *entry = createEntry(target, hashId);
+ if (cur == head) {
+ head = entry;
+ entry->m_next = prev;
+ } else {
+ prev->m_next = entry;
+ entry->m_next = cur;
+ }
+ return entry;
+}
+
+HRESULT CeeSectionString::getEmittedStringRef(__in_z LPWSTR target, StringRef *ref)
+{
+ TESTANDRETURN(ref!=NULL, E_POINTER);
+ ULONG hashId = HashString(target) % MaxVirtualEntries;
+ ULONG bucketIndex = hashId / MaxRealEntries;
+
+ StringTableEntry *entry;
+ entry = findStringInsert(stringTable[bucketIndex], target, hashId);
+
+ if (! entry)
+ return E_OUTOFMEMORY;
+ *ref = entry->m_offset;
+ return S_OK;
+}