aboutsummaryrefslogtreecommitdiff
path: root/src/common/simple_string_dictionary.h
diff options
context:
space:
mode:
authorrsesek@chromium.org <rsesek@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-04-18 20:17:29 +0000
committerrsesek@chromium.org <rsesek@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2013-04-18 20:17:29 +0000
commit30bb1ab6015b462b5f2c4b3ce1986dec96d1f716 (patch)
treedcb02e594eeb0234448c5105f6c489777b1e3cbd /src/common/simple_string_dictionary.h
parentAdd Android ifdef to fix issue 526 (diff)
downloadbreakpad-30bb1ab6015b462b5f2c4b3ce1986dec96d1f716.tar.xz
Move SimpleStringDictionary from common/mac/ to just common/.
This also cleans up some things like the file name, trailing whitespace, and making the test use gtest instead of sentest, since there's nothing Mac specific about this. BUG=https://code.google.com/p/chromium/issues/detail?id=77656 Review URL: https://breakpad.appspot.com/561003 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1154 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/common/simple_string_dictionary.h')
-rw-r--r--src/common/simple_string_dictionary.h192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/common/simple_string_dictionary.h b/src/common/simple_string_dictionary.h
new file mode 100644
index 00000000..dbeaabc0
--- /dev/null
+++ b/src/common/simple_string_dictionary.h
@@ -0,0 +1,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_