// 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. // // SimpleStringDictionary.h // #ifndef SimpleStringDictionary_H__ #define SimpleStringDictionary_H__ #import #import 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); // 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 // SimpleStringDictionary_H__