simple_string_dictionary.h revision 303311b8370b307ea38201fc3ad241a5610f8cfc
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
333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import <string>
343ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid#import <vector>
353ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidnamespace google_breakpad {
373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// SimpleStringDictionary (and associated class KeyValueEntry) implement a very
403ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// basic dictionary container class.  It has the property of not making any
413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// memory allocations when getting and setting values.  But it is not very
423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// efficient, with calls to get and set values operating in linear time.
433ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// It has the additional limitation of having a fairly small fixed capacity of
443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// SimpleStringDictionary::MAX_NUM_ENTRIES entries.  An assert() will fire if
453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// the client attempts to set more than this number of key/value pairs.
463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Ordinarilly a C++ programmer would use something like the std::map template
473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// class, or on the Macintosh would often choose CFDictionary or NSDictionary.
483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// But these dictionary classes may call malloc() during get and set operations.
493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// Google Breakpad requires that no memory allocations be made in code running
503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// in its exception handling thread, so it uses SimpleStringDictionary as the
513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// underlying implementation for the GoogleBreakpad.framework APIs:
523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GoogleBreakpadSetKeyValue(),  GoogleBreakpadKeyValue(), and
533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// GoogleBreakpadRemoveKeyValue()
543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
553ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
573ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// KeyValueEntry
583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// A helper class used by SimpleStringDictionary representing a single
603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// storage cell for a key/value pair.  Each key and value string are
613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// limited to MAX_STRING_STORAGE_SIZE-1 bytes (not glyphs).  This class
623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// performs no memory allocations.  It has methods for setting  and getting
633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// key and value strings.
643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
653ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass KeyValueEntry {
663ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
673ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  KeyValueEntry() {
683ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    Clear();
693ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
70303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
713ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  KeyValueEntry(const char *key, const char *value) {
723ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    SetKeyValue(key, value);
733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
743ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
75303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org  void SetKeyValue(const char *key, const char *value) {
763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    if (!key) {
773ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid      key = "";
783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
793ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    if (!value) {
803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid      value = "";
813ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
82303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
833ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    strlcpy(key_, key, sizeof(key_));
843ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    strlcpy(value_, value, sizeof(value_));
85303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org  }
863ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
87303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org  void SetValue(const char *value) {
883ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    if (!value) {
893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid      value = "";
903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    strlcpy(value_, value, sizeof(value_));
923ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  };
93303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
943ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Removes the key/value
95303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org  void Clear() {
963ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    memset(key_, 0, sizeof(key_));
973ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    memset(value_, 0, sizeof(value_));
983ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
993ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
100303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org  bool IsActive() const { return key_[0] != '\0'; }
1013ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  const char *GetKey() const { return key_; }
1023ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  const char *GetValue() const { return value_; }
1033ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1043ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Don't change this without considering the fixed size
1053ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // of MachMessage (in MachIPC.h)
1063ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // (see also struct KeyValueMessageData in Inspector.h)
1073ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  enum {MAX_STRING_STORAGE_SIZE = 256};
108303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
1093ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid private:
1103ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  char key_[MAX_STRING_STORAGE_SIZE];
1113ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  char value_[MAX_STRING_STORAGE_SIZE];
1123ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
1133ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1143ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
1153ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// This class is not an efficient dictionary, but for the purposes of breakpad
1163ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// will be just fine.  We're just dealing with ten or so distinct
1173ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// key/value pairs.  The idea is to avoid any malloc() or free() calls
1183ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// in certain important methods to be called when a process is in a
1193ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// crashed state.  Each key and value string are limited to
1203ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// KeyValueEntry::MAX_STRING_STORAGE_SIZE-1 bytes (not glyphs).  Strings passed
1213ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid// in exceeding this length will be truncated.
1223ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//
1233ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass SimpleStringDictionary {
1243ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
1253ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  SimpleStringDictionary() {};  // entries will all be cleared
126303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
1273ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Returns the number of active key/value pairs.  The upper limit for this
1283ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // is MAX_NUM_ENTRIES.
1293ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  int GetCount() const;
1303ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1313ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Given |key|, returns its corresponding |value|.
1323ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // If |key| is NULL, an assert will fire or NULL will be returned.  If |key|
1333ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // is not found or is an empty string, NULL is returned.
13400936cf4ad413ec012b81c814319467c206d7447qsr@chromium.org  const char *GetValueForKey(const char *key) const;
135303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
1363ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Stores a string |value| represented by |key|.  If |key| is NULL or an empty
1373ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // string, this will assert (or do nothing).  If |value| is NULL then
1383ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // the |key| will be removed.  An empty string is OK for |value|.
1393ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  void SetKeyValue(const char *key, const char *value);
140303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
1413ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Given |key|, removes any associated value.  It will assert (or do nothing)
1423ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // if NULL is passed in.  It will do nothing if |key| is not found.
1433ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  void RemoveKey(const char *key);
1443ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1453ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // This is the maximum number of key/value pairs which may be set in the
1463ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // dictionary.  An assert may fire if more values than this are set.
1473ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Don't change this without also changing comment in GoogleBreakpad.h
1483ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  enum {MAX_NUM_ENTRIES = 64};
1493ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1503ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid private:
1513ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  friend class SimpleStringDictionaryIterator;
1523ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1533ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  const KeyValueEntry *GetEntry(int i) const;
1543ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
155303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org  KeyValueEntry entries_[MAX_NUM_ENTRIES];
1563ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
1573ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1583ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid//==============================================================================
1593ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsidclass SimpleStringDictionaryIterator {
1603ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid public:
1613ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  SimpleStringDictionaryIterator(const SimpleStringDictionary &dict)
1623ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    : dict_(dict), i_(0) {
1633ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
1643ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1653ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // Initializes iterator to the beginning (may later call Next() )
1663ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  void Start() {
1673ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    i_ = 0;
1683ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
169303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
1703ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // like the nextObject method of NSEnumerator (in Cocoa)
1713ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  // returns NULL when there are no more entries
1723ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  //
1733ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  const KeyValueEntry* Next() {
1743ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    for (; i_ < SimpleStringDictionary::MAX_NUM_ENTRIES; ++i_) {
1753ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid      const KeyValueEntry *entry = dict_.GetEntry(i_);
1763ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid      if (entry->IsActive()) {
1773ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid        i_++;   // move to next entry for next time
1783ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid        return entry;
1793ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid      }
1803ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    }
1813ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1823ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid    return NULL;  // reached end of array
1833ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid  }
184303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org
1853ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid private:
186303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org  const SimpleStringDictionary& dict_;
187303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org  int i_;
1883ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid};
1893ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
1903ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid}  // namespace google_breakpad
1913ebdb1bd7ae38bf0fb205dfaa2f5fde3d67ea141nealsid
192303311b8370b307ea38201fc3ad241a5610f8cfcrsesek@chromium.org#endif  // COMMON_SIMPLE_STRING_DICTIONARY_H_
193