Back to index

lightning-sunbird  0.9+nobinonly
nsMorkReader.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Mork Reader.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Google Inc.
00019  * Portions created by the Initial Developer are Copyright (C) 2006
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Brian Ryner <bryner@brianryner.com> (original author)
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #ifndef nsMorkReader_h_
00040 #define nsMorkReader_h_
00041 
00042 #include "nsDataHashtable.h"
00043 #include "nsILineInputStream.h"
00044 #include "nsTArray.h"
00045 #include "nsAutoPtr.h"
00046 
00047 // The nsMorkReader object allows a consumer to read in a mork-format
00048 // file and enumerate the rows that it contains.  It does not provide
00049 // any functionality for modifying mork tables.
00050 
00051 // References:
00052 //  http://www.mozilla.org/mailnews/arch/mork/primer.txt
00053 //  http://www.mozilla.org/mailnews/arch/mork/grammar.txt
00054 //  http://www.jwz.org/hacks/mork.pl
00055 
00056 class nsMorkReader
00057 {
00058  public:
00059   // This string type has built-in storage for the hex string representation
00060   // of a 32-bit row id or atom map key, plus the terminating null.
00061   class IDString : public nsFixedCString
00062   {
00063   public:
00064     IDString() : fixed_string_type(mStorage, sizeof(mStorage), 0) {}
00065     IDString(const substring_type &str) :
00066       fixed_string_type(mStorage, sizeof(mStorage), 0)
00067     {
00068       Assign(str);
00069     }
00070 
00071   private:
00072     char_type mStorage[9];
00073   };
00074 
00075   // Hashtable key type that contains an IDString
00076   class IDKey : public PLDHashEntryHdr
00077   {
00078   public:
00079     typedef const nsCSubstring& KeyType;
00080     typedef const nsCSubstring* KeyTypePointer;
00081 
00082     IDKey(KeyTypePointer aStr) : mStr(*aStr) { }
00083     IDKey(const IDKey& toCopy) : mStr(toCopy.mStr) { }
00084     ~IDKey() { }
00085 
00086     KeyType GetKey() const { return mStr; }
00087     KeyTypePointer GetKeyPointer() const { return &mStr; }
00088     PRBool KeyEquals(const KeyTypePointer aKey) const
00089     {
00090       return mStr.Equals(*aKey);
00091     }
00092 
00093     static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; }
00094     static PLDHashNumber HashKey(const KeyTypePointer aKey)
00095     {
00096       return HashString(*aKey);
00097     }
00098     enum { ALLOW_MEMMOVE = PR_FALSE };
00099 
00100   private:
00101     const IDString mStr;
00102   };
00103 
00104   // A convenience typedef for an IDKey-to-string mapping.
00105   typedef nsDataHashtable<IDKey,nsCString> StringMap;
00106 
00107   // A convenience typdef for an IDKey-to-index mapping, used for the
00108   // column index hashtable.
00109   typedef nsDataHashtable<IDKey,PRInt32> IndexMap;
00110 
00111   // A MorkColumn represents the data associated with a single table column.
00112   struct MorkColumn
00113   {
00114     MorkColumn(const nsCSubstring &i, const nsCSubstring &n)
00115       : id(i), name(n) {}
00116 
00117     IDString id;
00118     nsCString name;
00119   };
00120 
00121   // Enumerator callback type for processing table rows.
00122   // A row contains cells.  Each cell specifies a column id, and the value
00123   // for the column for that row.
00124   // rowID is the table-unique row id
00125   // values contains the cell values, in an order which corresponds to
00126   //   the columns returned by GetColumns().
00127   //   You should call NormalizeValue() on any cell value that you plan to use.
00128   // userData is the opaque pointer passed to EnumerateRows()
00129   // The callback can return PL_DHASH_NEXT to continue enumerating,
00130   // or PL_DHASH_STOP to stop.
00131   typedef PLDHashOperator
00132   (*PR_CALLBACK RowEnumerator)(const nsCSubstring &rowID, 
00133                                const nsTArray<nsCString> *values,
00134                                void *userData);
00135 
00136   // Initialize the importer object's data structures
00137   nsresult Init();
00138 
00139   // Read in the given mork file
00140   // Note: currently, only single-table mork files are supported
00141   nsresult Read(nsIFile *aFile);
00142 
00143   // Returns the list of columns in the current table.
00144   const nsTArray<MorkColumn>& GetColumns() const { return mColumns; }
00145 
00146   // Enumerate the rows in the current table.
00147   void EnumerateRows(RowEnumerator aCallback, void *aUserData) const;
00148 
00149   // Get the "meta row" for the table.  Each table has at most one meta row,
00150   // which records information about the table.  Like normal rows, the
00151   // meta row contains columns in the same order as returned by GetColumns().
00152   // Returns null if there is no meta row for this table.
00153   const nsTArray<nsCString>* GetMetaRow() const { return mMetaRow; }
00154 
00155   // Normalizes the cell value (resolves references to the value map).
00156   // aValue is modified in-place.
00157   void NormalizeValue(nsCString &aValue) const;
00158 
00159   nsMorkReader() {}
00160   ~nsMorkReader();
00161 
00162 private:
00163   // Parses a line of the file which contains key/value pairs (either
00164   // the column map or the value map).  Additional lines are read from
00165   // mStream if the line ends mid-entry.  The pairs are added to aMap.
00166   nsresult ParseMap(const nsCSubstring &aLine, StringMap *aMap);
00167 
00168   // Parses a line of the file which contains a table or row definition.
00169   // Additional lines are read from mStream of the line ends mid-row.
00170   // An entry is added to mTable using the row ID as the key, which contains
00171   // a column array for the row.  The supplied column hash table maps from
00172   // column id to an index in mColumns.
00173   nsresult ParseTable(const nsCSubstring &aLine, const IndexMap &aColumnMap);
00174 
00175   // Reads a single logical line from mStream into aLine.
00176   // Any continuation lines are consumed and appended to the line.
00177   nsresult ReadLine(nsCString &aLine);
00178 
00179   // Create a new nsCString array and fill it with the supplied number
00180   // of void strings.  Returns null on out-of-memory.
00181   static nsTArray<nsCString>* NewVoidStringArray(PRInt32 aSize);
00182 
00183   nsTArray<MorkColumn> mColumns;
00184   StringMap mValueMap;
00185   nsAutoPtr< nsTArray<nsCString> > mMetaRow;
00186   nsDataHashtable< IDKey,nsTArray<nsCString>* > mTable;
00187   nsCOMPtr<nsILineInputStream> mStream;
00188   nsCString mEmptyString; // note: not EmptyCString() since that's not sharable
00189 };
00190 
00191 #endif // nsMorkReader_h_