}
}
- const Char_type* str = this->stringpool_.add_prefix(p, pl - p, NULL);
+ const Char_type* str = this->stringpool_.add_with_length(p, pl - p, true,
+ NULL);
section_size_type bytelen_with_null = ((pl - p) + 1) * sizeof(Char_type);
this->merged_strings_.push_back(Merged_string(object, shndx, i, str,
this->merged_strings_.begin();
p != this->merged_strings_.end();
++p)
- this->add_mapping(p->object, p->shndx, p->offset, p->length,
- this->stringpool_.get_offset(p->string));
+ {
+ size_t charlen_without_null = (p->length / sizeof(Char_type)) - 1;
+ section_offset_type offset =
+ this->stringpool_.get_offset_with_length(p->string,
+ charlen_without_null);
+ this->add_mapping(p->object, p->shndx, p->offset, p->length, offset);
+ }
// Save some memory.
this->merged_strings_.clear();
{
return (h1.hash_code == h2.hash_code
&& h1.length == h2.length
- && memcmp(h1.string, h2.string,
- h1.length * sizeof(Stringpool_char)) == 0);
+ && (h1.string == h2.string
+ || memcmp(h1.string, h2.string,
+ h1.length * sizeof(Stringpool_char)) == 0));
}
// Hash function. The length is in characters, not bytes.
const Stringpool_char*
Stringpool_template<Stringpool_char>::add(const Stringpool_char* s, bool copy,
Key* pkey)
+{
+ return this->add_with_length(s, string_length(s), copy, pkey);
+}
+
+template<typename Stringpool_char>
+const Stringpool_char*
+Stringpool_template<Stringpool_char>::add_with_length(const Stringpool_char* s,
+ size_t length,
+ bool copy,
+ Key* pkey)
{
typedef std::pair<typename String_set_type::iterator, bool> Insert_type;
const Key k = this->next_uncopied_key_;
const section_offset_type ozero = 0;
- std::pair<Hashkey, Hashval> element(Hashkey(s),
+ std::pair<Hashkey, Hashval> element(Hashkey(s, length),
std::make_pair(k, ozero));
Insert_type ins = this->string_set_.insert(element);
return p->first.string;
}
- return this->add_prefix(s, string_length(s), pkey);
-}
-
-// Add a prefix of a string to a string pool.
-
-template<typename Stringpool_char>
-const Stringpool_char*
-Stringpool_template<Stringpool_char>::add_prefix(const Stringpool_char* s,
- size_t len,
- Key* pkey)
-{
- // When adding an entry, this will look it up twice in the hash
+ // When we have to copy the string, we look it up twice in the hash
// table. The problem is that we can't insert S before we
// canonicalize it by copying it into the canonical list. The hash
- // code will only be computed once, so this isn't all that
- // expensive.
+ // code will only be computed once.
- Hashkey hk(s, len);
+ Hashkey hk(s, length);
typename String_set_type::const_iterator p = this->string_set_.find(hk);
if (p != this->string_set_.end())
{
}
Key k;
- hk.string = this->add_string(s, len, &k);
+ hk.string = this->add_string(s, length, &k);
// The contents of the string stay the same, so we don't need to
// adjust hk.hash_code or hk.length.
const section_offset_type ozero = 0;
std::pair<Hashkey, Hashval> element(hk, std::make_pair(k, ozero));
- typedef std::pair<typename String_set_type::iterator, bool> Insert_type;
Insert_type ins = this->string_set_.insert(element);
gold_assert(ins.second);
section_offset_type
Stringpool_template<Stringpool_char>::get_offset(const Stringpool_char* s)
const
+{
+ return this->get_offset_with_length(s, string_length(s));
+}
+
+template<typename Stringpool_char>
+section_offset_type
+Stringpool_template<Stringpool_char>::get_offset_with_length(
+ const Stringpool_char* s,
+ size_t length) const
{
gold_assert(this->strtab_size_ != 0);
- typename String_set_type::const_iterator p = this->string_set_.find(s);
+ Hashkey hk(s, length);
+ typename String_set_type::const_iterator p = this->string_set_.find(hk);
if (p != this->string_set_.end())
return p->second.second;
gold_unreachable();
const Stringpool_char*
add(const Stringpool_char* s, bool copy, Key* pkey);
- // Add the prefix of length LEN of string S to the pool.
+ // Add string S of length LEN characters to the pool. If COPY is
+ // true, S need not be null terminated.
const Stringpool_char*
- add_prefix(const Stringpool_char* s, size_t len, Key* pkey);
+ add_with_length(const Stringpool_char* s, size_t len, bool copy, Key* pkey);
// If the string S is present in the pool, return the canonical
// string pointer. Otherwise, return NULL. If PKEY is not NULL,
// Get the offset of the string S in the string table.
section_offset_type
get_offset(const std::basic_string<Stringpool_char>& s) const
- { return this->get_offset(s.c_str()); }
+ { return this->get_offset_with_length(s.c_str(), s.size()); }
+
+ // Get the offset of string S, with length LENGTH characters, in the
+ // string table.
+ section_offset_type
+ get_offset_with_length(const Stringpool_char* s, size_t length) const;
// Get the size of the string table. This returns the number of
// bytes, not in units of Stringpool_char.
// Note that these constructors are relatively expensive, because
// they compute the hash code.
- Hashkey(const Stringpool_char* s)
+ explicit Hashkey(const Stringpool_char* s)
: string(s), length(string_length(s)), hash_code(string_hash(s, length))
{ }