aboutsummaryrefslogtreecommitdiff
path: root/src/common/simple_string_dictionary.h
blob: dbeaabc0b19ce7827d3cdafb37e281f789a93fa6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
// Copyright (c) 2007, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef COMMON_SIMPLE_STRING_DICTIONARY_H_
#define COMMON_SIMPLE_STRING_DICTIONARY_H_

#import <string>
#import <vector>

namespace google_breakpad {

//==============================================================================
// SimpleStringDictionary (and associated class KeyValueEntry) implement a very
// basic dictionary container class.  It has the property of not making any
// memory allocations when getting and setting values.  But it is not very
// efficient, with calls to get and set values operating in linear time.
// It has the additional limitation of having a fairly small fixed capacity of
// SimpleStringDictionary::MAX_NUM_ENTRIES entries.  An assert() will fire if
// the client attempts to set more than this number of key/value pairs.
// Ordinarilly a C++ programmer would use something like the std::map template
// class, or on the Macintosh would often choose CFDictionary or NSDictionary.
// But these dictionary classes may call malloc() during get and set operations.
// Google Breakpad requires that no memory allocations be made in code running
// in its exception handling thread, so it uses SimpleStringDictionary as the
// underlying implementation for the GoogleBreakpad.framework APIs:
// GoogleBreakpadSetKeyValue(),  GoogleBreakpadKeyValue(), and
// GoogleBreakpadRemoveKeyValue()
//

//==============================================================================
// KeyValueEntry
//
// A helper class used by SimpleStringDictionary representing a single
// storage cell for a key/value pair.  Each key and value string are
// limited to MAX_STRING_STORAGE_SIZE-1 bytes (not glyphs).  This class
// performs no memory allocations.  It has methods for setting  and getting
// key and value strings.
//
class KeyValueEntry {
 public:
  KeyValueEntry() {
    Clear();
  }

  KeyValueEntry(const char *key, const char *value) {
    SetKeyValue(key, value);
  }

  void SetKeyValue(const char *key, const char *value) {
    if (!key) {
      key = "";
    }
    if (!value) {
      value = "";
    }

    strlcpy(key_, key, sizeof(key_));
    strlcpy(value_, value, sizeof(value_));
  }

  void SetValue(const char *value) {
    if (!value) {
      value = "";
    }
    strlcpy(value_, value, sizeof(value_));
  };

  // Removes the key/value
  void Clear() {
    memset(key_, 0, sizeof(key_));
    memset(value_, 0, sizeof(value_));
  }

  bool IsActive() const { return key_[0] != '\0'; }
  const char *GetKey() const { return key_; }
  const char *GetValue() const { return value_; }

  // Don't change this without considering the fixed size
  // of MachMessage (in MachIPC.h)
  // (see also struct KeyValueMessageData in Inspector.h)
  enum {MAX_STRING_STORAGE_SIZE = 256};

 private:
  char key_[MAX_STRING_STORAGE_SIZE];
  char value_[MAX_STRING_STORAGE_SIZE];
};

//==============================================================================
// This class is not an efficient dictionary, but for the purposes of breakpad
// will be just fine.  We're just dealing with ten or so distinct
// key/value pairs.  The idea is to avoid any malloc() or free() calls
// in certain important methods to be called when a process is in a
// crashed state.  Each key and value string are limited to
// KeyValueEntry::MAX_STRING_STORAGE_SIZE-1 bytes (not glyphs).  Strings passed
// in exceeding this length will be truncated.
//
class SimpleStringDictionary {
 public:
  SimpleStringDictionary() {};  // entries will all be cleared

  // Returns the number of active key/value pairs.  The upper limit for this
  // is MAX_NUM_ENTRIES.
  int GetCount() const;

  // Given |key|, returns its corresponding |value|.
  // If |key| is NULL, an assert will fire or NULL will be returned.  If |key|
  // is not found or is an empty string, NULL is returned.
  const char *GetValueForKey(const char *key) const;

  // Stores a string |value| represented by |key|.  If |key| is NULL or an empty
  // string, this will assert (or do nothing).  If |value| is NULL then
  // the |key| will be removed.  An empty string is OK for |value|.
  void SetKeyValue(const char *key, const char *value);

  // Given |key|, removes any associated value.  It will assert (or do nothing)
  // if NULL is passed in.  It will do nothing if |key| is not found.
  void RemoveKey(const char *key);

  // This is the maximum number of key/value pairs which may be set in the
  // dictionary.  An assert may fire if more values than this are set.
  // Don't change this without also changing comment in GoogleBreakpad.h
  enum {MAX_NUM_ENTRIES = 64};

 private:
  friend class SimpleStringDictionaryIterator;

  const KeyValueEntry *GetEntry(int i) const;

  KeyValueEntry entries_[MAX_NUM_ENTRIES];
};

//==============================================================================
class SimpleStringDictionaryIterator {
 public:
  SimpleStringDictionaryIterator(const SimpleStringDictionary &dict)
    : dict_(dict), i_(0) {
    }

  // Initializes iterator to the beginning (may later call Next() )
  void Start() {
    i_ = 0;
  }

  // like the nextObject method of NSEnumerator (in Cocoa)
  // returns NULL when there are no more entries
  //
  const KeyValueEntry* Next() {
    for (; i_ < SimpleStringDictionary::MAX_NUM_ENTRIES; ++i_) {
      const KeyValueEntry *entry = dict_.GetEntry(i_);
      if (entry->IsActive()) {
        i_++;   // move to next entry for next time
        return entry;
      }
    }

    return NULL;  // reached end of array
  }

 private:
  const SimpleStringDictionary& dict_;
  int i_;
};

}  // namespace google_breakpad

#endif  // COMMON_SIMPLE_STRING_DICTIONARY_H_