2006-09-08 H.J. Lu <hongjiu.lu@intel.com>
[binutils.git] / gold / stringpool.cc
blob0368014eb268bc5015325d880700d51ecc61080b
1 // stringpool.cc -- a string pool for gold
3 #include "gold.h"
5 #include <cassert>
6 #include <cstring>
8 #include "stringpool.h"
10 namespace gold
13 Stringpool::Stringpool()
14 : string_set_(), strings_()
18 Stringpool::~Stringpool()
20 for (std::list<stringdata*>::iterator p = this->strings_.begin();
21 p != this->strings_.end();
22 ++p)
23 delete[] reinterpret_cast<char*>(*p);
26 // Hash function.
28 size_t
29 Stringpool::Stringpool_hash::operator()(const char* s) const
31 // Fowler/Noll/Vo (FNV) hash (type FNV-1a).
32 if (sizeof(size_t) == 8)
34 size_t result = 14695981039346656037ULL;
35 while (*s != '\0')
37 result &= (size_t) *s++;
38 result *= 1099511628211ULL;
40 return result;
42 else
44 size_t result = 2166136261UL;
45 while (*s != '\0')
47 result ^= (size_t) *s++;
48 result *= 16777619UL;
50 return result;
54 // Add a string to the list of canonical strings. Return a pointer to
55 // the canonical string.
57 const char*
58 Stringpool::add_string(const char* s)
60 const size_t buffer_size = 1000;
61 size_t len = strlen(s);
63 size_t alc;
64 bool front = true;
65 if (len >= buffer_size)
67 alc = sizeof(stringdata) + len;
68 front = false;
70 else if (this->strings_.empty())
71 alc = sizeof(stringdata) + buffer_size;
72 else
74 stringdata *psd = this->strings_.front();
75 if (len >= psd->alc - psd->len)
76 alc = sizeof(stringdata) + buffer_size;
77 else
79 char* ret = psd->data + psd->len;
80 memcpy(ret, s, len + 1);
81 psd->len += len + 1;
82 return ret;
86 stringdata *psd = reinterpret_cast<stringdata*>(new char[alc]);
87 psd->alc = alc;
88 memcpy(psd->data, s, len + 1);
89 psd->len = len + 1;
90 if (front)
91 this->strings_.push_front(psd);
92 else
93 this->strings_.push_back(psd);
94 return psd->data;
97 // Add a string to a string pool.
99 const char*
100 Stringpool::add(const char* s)
102 // FIXME: This will look up the entry twice in the hash table. The
103 // problem is that we can't insert S before we canonicalize it. I
104 // don't think there is a way to handle this correct with
105 // unordered_set, so this should be replaced with custom code to do
106 // what we need, which is to return the empty slot.
108 String_set_type::const_iterator p = this->string_set_.find(s);
109 if (p != this->string_set_.end())
110 return *p;
112 const char* ret = this->add_string(s);
113 std::pair<String_set_type::iterator, bool> ins =
114 this->string_set_.insert(ret);
115 assert(ins.second);
116 return ret;
119 // Add a prefix of a string to a string pool.
121 const char*
122 Stringpool::add(const char* s, size_t len)
124 // FIXME: This implementation should be rewritten when we rewrite
125 // the hash table to avoid copying.
126 std::string st(s, len);
127 return this->add(st);
130 } // End namespace gold.