summaryrefslogtreecommitdiff
path: root/src/emscripten-optimizer/istring.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/emscripten-optimizer/istring.h')
-rw-r--r--src/emscripten-optimizer/istring.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/emscripten-optimizer/istring.h b/src/emscripten-optimizer/istring.h
new file mode 100644
index 000000000..b77fec4e5
--- /dev/null
+++ b/src/emscripten-optimizer/istring.h
@@ -0,0 +1,161 @@
+// Interned String type, 100% interned on creation. Comparisons are always just a pointer comparison
+
+#ifndef __istring_h__
+#define __istring_h__
+
+#include <unordered_set>
+#include <unordered_map>
+#include <set>
+
+#include <string.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+
+namespace cashew {
+
+struct IString {
+ const char *str;
+
+ static size_t hash_c(const char *str) { // see http://www.cse.yorku.ca/~oz/hash.html
+ unsigned int hash = 5381;
+ int c;
+ while ((c = *str++)) {
+ hash = ((hash << 5) + hash) ^ c;
+ }
+ return (size_t)hash;
+ }
+
+ class CStringHash : public std::hash<const char *> {
+ public:
+ size_t operator()(const char *str) const {
+ return IString::hash_c(str);
+ }
+ };
+ class CStringEqual : public std::equal_to<const char *> {
+ public:
+ bool operator()(const char *x, const char *y) const {
+ return strcmp(x, y) == 0;
+ }
+ };
+
+ IString() : str(nullptr) {}
+ IString(const char *s, bool reuse=true) { // if reuse=true, then input is assumed to remain alive; not copied
+ assert(s);
+ set(s, reuse);
+ }
+
+ void set(const char *s, bool reuse=true) {
+ typedef std::unordered_set<const char *, CStringHash, CStringEqual> StringSet;
+ static StringSet* strings = new StringSet();
+
+ if (reuse) {
+ auto result = strings->insert(s); // if already present, does nothing
+ str = *(result.first);
+ } else {
+ auto existing = strings->find(s);
+ if (existing == strings->end()) {
+ char *copy = (char*)malloc(strlen(s)+1); // XXX leaked
+ strcpy(copy, s);
+ s = copy;
+ } else {
+ s = *existing;
+ }
+ strings->insert(s);
+ str = s;
+ }
+ }
+
+ void set(const IString &s) {
+ str = s.str;
+ }
+
+ void clear() {
+ str = nullptr;
+ }
+
+ bool operator==(const IString& other) const {
+ //assert((str == other.str) == !strcmp(str, other.str));
+ return str == other.str; // fast!
+ }
+ bool operator!=(const IString& other) const {
+ //assert((str == other.str) == !strcmp(str, other.str));
+ return str != other.str; // fast!
+ }
+ bool operator<(const IString& other) const {
+ return strcmp(str ? str : "", other.str ? other.str : "") < 0;
+ }
+
+ char operator[](int x) const {
+ return str[x];
+ }
+
+ bool operator!() const { // no string, or empty string
+ return !str || str[0] == 0;
+ }
+
+ const char *c_str() const { return str; }
+ bool equals(const char *other) const { return !strcmp(str, other); }
+
+ bool is() { return str != nullptr; }
+ bool isNull() { return str == nullptr; }
+};
+
+} // namespace cashew
+
+// Utilities for creating hashmaps/sets over IStrings
+
+namespace std {
+
+template <> struct hash<cashew::IString> : public unary_function<cashew::IString, size_t> {
+ size_t operator()(const cashew::IString& str) const {
+ size_t hash = size_t(str.str);
+ return hash = ((hash << 5) + hash) ^ 5381; /* (hash * 33) ^ c */
+ }
+};
+
+template <> struct equal_to<cashew::IString> : public binary_function<cashew::IString, cashew::IString, bool> {
+ bool operator()(const cashew::IString& x, const cashew::IString& y) const {
+ return x == y;
+ }
+};
+
+} // namespace std
+
+namespace cashew {
+
+// IStringSet
+
+class IStringSet : public std::unordered_set<IString> {
+public:
+ IStringSet() {}
+ IStringSet(const char *init) { // comma-delimited list
+ int size = strlen(init);
+ char *curr = new char[size+1]; // leaked!
+ strcpy(curr, init);
+ while (1) {
+ char *end = strchr(curr, ' ');
+ if (end) *end = 0;
+ insert(curr);
+ if (!end) break;
+ curr = end + 1;
+ }
+ }
+
+ bool has(const IString& str) {
+ return count(str) > 0;
+ }
+};
+
+class IOrderedStringSet : public std::set<IString> {
+public:
+ bool has(const IString& str) {
+ return count(str) > 0;
+ }
+};
+
+} // namespace cashew
+
+#endif // __istring_h__
+