13ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Copyright (c) 2007, Google Inc.
23ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// All rights reserved.
33ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
43ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Redistribution and use in source and binary forms, with or without
53ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// modification, are permitted provided that the following conditions are
63ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// met:
73ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
83ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//     * Redistributions of source code must retain the above copyright
93ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// notice, this list of conditions and the following disclaimer.
103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//     * Redistributions in binary form must reproduce the above
113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// copyright notice, this list of conditions and the following disclaimer
123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// in the documentation and/or other materials provided with the
133ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// distribution.
143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//     * Neither the name of Google Inc. nor the names of its
153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// contributors may be used to endorse or promote products derived from
163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// this software without specific prior written permission.
173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
223ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
233ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
30303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org#ifndef COMMON_SIMPLE_STRING_DICTIONARY_H_
31303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org#define COMMON_SIMPLE_STRING_DICTIONARY_H_
323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
33c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org#include <assert.h>
34504de264483fcb260fd21dce75f69e9d3b8dfe1crsesek@chromium.org#include <string.h>
353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
36c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org#include "common/basictypes.h"
37c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidnamespace google_breakpad {
393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
40c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// Opaque type for the serialized representation of a NonAllocatingMap. One is
41c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// created in NonAllocatingMap::Serialize and can be deserialized using one of
42c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// the constructors.
43c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.orgstruct SerializedNonAllocatingMap;
443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
45c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// NonAllocatingMap is an implementation of a map/dictionary collection that
46c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// uses a fixed amount of storage, so that it does not perform any dynamic
47c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// allocations for its operations.
483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
49c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// The actual map storage (the Entry) is guaranteed to be POD, so that it can
50c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// be transmitted over various IPC mechanisms.
513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
52c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// The template parameters control the amount of storage used for the key,
53c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// value, and map. The KeySize and ValueSize are measured in bytes, not glyphs,
54c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// and includes space for a \0 byte. This gives space for KeySize-1 and
55c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// ValueSize-1 characters in an entry. NumEntries is the total number of
56c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// entries that will fit in the map.
57c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.orgtemplate <size_t KeySize, size_t ValueSize, size_t NumEntries>
58c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.orgclass NonAllocatingMap {
593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
60c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // Constant and publicly accessible versions of the template parameters.
61c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  static const size_t key_size = KeySize;
62c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  static const size_t value_size = ValueSize;
63c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  static const size_t num_entries = NumEntries;
64c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
65c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // An Entry object is a single entry in the map. If the key is a 0-length
66c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // NUL-terminated string, the entry is empty.
67c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  struct Entry {
68c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    char key[KeySize];
69c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    char value[ValueSize];
70c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
71c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    bool is_active() const {
72c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      return key[0] != '\0';
73c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    }
74c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  };
75c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
76c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // An Iterator can be used to iterate over all the active entries in a
77c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // NonAllocatingMap.
78c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  class Iterator {
79c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org   public:
80c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    explicit Iterator(const NonAllocatingMap& map)
81c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        : map_(map),
82c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org          current_(0) {
83c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    }
84c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
85c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    // Returns the next entry in the map, or NULL if at the end of the
86c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    // collection.
87c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    const Entry* Next() {
88c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      while (current_ < map_.num_entries) {
89c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        const Entry* entry = &map_.entries_[current_++];
90c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        if (entry->is_active()) {
91c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org          return entry;
92c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        }
93c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      }
94c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      return NULL;
95c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    }
96c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
97c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org   private:
98c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    const NonAllocatingMap& map_;
99c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    size_t current_;
100c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
101c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    DISALLOW_COPY_AND_ASSIGN(Iterator);
102c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  };
103c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
104c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  NonAllocatingMap() : entries_() {
1053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
106303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
107c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  NonAllocatingMap(const NonAllocatingMap& other) {
108c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    *this = other;
1093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
111c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  NonAllocatingMap& operator=(const NonAllocatingMap& other) {
112c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(other.key_size == key_size);
113c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(other.value_size == value_size);
114c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(other.num_entries == num_entries);
115c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (other.key_size == key_size && other.value_size == value_size &&
116c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        other.num_entries == num_entries) {
117c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      memcpy(entries_, other.entries_, sizeof(entries_));
1183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
119c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    return *this;
120c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  }
121303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
122c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // Constructs a map from its serialized form. |map| should be the out
123c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // parameter from Serialize() and |size| should be its return value.
124c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  NonAllocatingMap(const SerializedNonAllocatingMap* map, size_t size) {
125c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(size == sizeof(entries_));
126c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (size == sizeof(entries_)) {
127c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      memcpy(entries_, map, size);
128c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    }
129303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org  }
1303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
131c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // Returns the number of active key/value pairs. The upper limit for this
132c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // is NumEntries.
133c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  size_t GetCount() const {
134c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    size_t count = 0;
135c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    for (size_t i = 0; i < num_entries; ++i) {
136c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      if (entries_[i].is_active()) {
137c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        ++count;
138c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      }
1393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
140c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    return count;
141c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  }
142c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
143c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // Given |key|, returns its corresponding |value|. |key| must not be NULL. If
144c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // the key is not found, NULL is returned.
145c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  const char* GetValueForKey(const char* key) const {
146c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(key);
147c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (!key)
148c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      return NULL;
149c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
150c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    const Entry* entry = GetConstEntryForKey(key);
151c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (!entry)
152c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      return NULL;
153303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
154c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    return entry->value;
1553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
1563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
157c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // Stores |value| into |key|, replacing the existing value if |key| is
158c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // already present. |key| must not be NULL. If |value| is NULL, the key is
1598160f86c54596ed816378bbd07fb83acbe8154farsesek@chromium.org  // removed from the map. If there is no more space in the map, then the
1608160f86c54596ed816378bbd07fb83acbe8154farsesek@chromium.org  // operation silently fails.
161c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  void SetKeyValue(const char* key, const char* value) {
162c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (!value) {
163c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      RemoveKey(key);
164c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      return;
165c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    }
1663ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
167c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(key);
168c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (!key)
169c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      return;
170303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
171c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    // Key must not be an empty string.
172c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(key[0] != '\0');
173c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (key[0] == '\0')
174c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      return;
1753ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
176c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    Entry* entry = GetEntryForKey(key);
177303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
178c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    // If it does not yet exist, attempt to insert it.
179c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (!entry) {
180c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      for (size_t i = 0; i < num_entries; ++i) {
181c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        if (!entries_[i].is_active()) {
182c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org          entry = &entries_[i];
1833ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
184c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org          strncpy(entry->key, key, key_size);
185c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org          entry->key[key_size - 1] = '\0';
186303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
187c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org          break;
188c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        }
189c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      }
190c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    }
1913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
192c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    // If the map is out of space, entry will be NULL.
1938160f86c54596ed816378bbd07fb83acbe8154farsesek@chromium.org    if (!entry)
1948160f86c54596ed816378bbd07fb83acbe8154farsesek@chromium.org      return;
1953ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
196c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org#ifndef NDEBUG
197c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    // Sanity check that the key only appears once.
198c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    int count = 0;
199c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    for (size_t i = 0; i < num_entries; ++i) {
200c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      if (strncmp(entries_[i].key, key, key_size) == 0)
201c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        ++count;
202c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    }
203c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(count == 1);
204c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org#endif
2053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
206c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    strncpy(entry->value, value, value_size);
207c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    entry->value[value_size - 1] = '\0';
208c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  }
2093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
210c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // Given |key|, removes any associated value. |key| must not be NULL. If
211c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // the key is not found, this is a noop.
212c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  void RemoveKey(const char* key) {
213c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(key);
214c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (!key)
215c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      return;
2163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
217c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    Entry* entry = GetEntryForKey(key);
218c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    if (entry) {
219c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      entry->key[0] = '\0';
220c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      entry->value[0] = '\0';
2213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
2223ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
223c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org#ifndef NDEBUG
224c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    assert(GetEntryForKey(key) == NULL);
225c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org#endif
2263ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
227303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
228c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // Places a serialized version of the map into |map| and returns the size.
229c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // Both of these should be passed to the deserializing constructor. Note that
230c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // the serialized |map| is scoped to the lifetime of the non-serialized
231c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  // instance of this class. The |map| can be copied across IPC boundaries.
232c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  size_t Serialize(const SerializedNonAllocatingMap** map) const {
233c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    *map = reinterpret_cast<const SerializedNonAllocatingMap*>(entries_);
234c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    return sizeof(entries_);
235c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  }
236c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
237c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org private:
238c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  const Entry* GetConstEntryForKey(const char* key) const {
239c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    for (size_t i = 0; i < num_entries; ++i) {
240c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org      if (strncmp(key, entries_[i].key, key_size) == 0) {
241c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org        return &entries_[i];
2423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid      }
2433ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
244c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    return NULL;
245c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  }
2463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
247c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  Entry* GetEntryForKey(const char* key) {
248c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org    return const_cast<Entry*>(GetConstEntryForKey(key));
2493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
250303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
251c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org  Entry entries_[NumEntries];
2523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
2533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
254c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// For historical reasons this specialized version is available with the same
255c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org// size factors as a previous implementation.
256c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.orgtypedef NonAllocatingMap<256, 256, 64> SimpleStringDictionary;
257c36fcd7f534887b5f8e83dca2ef445cb05e09463rsesek@chromium.org
2583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid}  // namespace google_breakpad
2593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
260303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org#endif  // COMMON_SIMPLE_STRING_DICTIONARY_H_
261