/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is the Mork Reader. * * The Initial Developer of the Original Code is * Google Inc. * Portions created by the Initial Developer are Copyright (C) 2006 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Brian Ryner (original author) * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #ifndef nsMorkReader_h_ #define nsMorkReader_h_ #include "nsDataHashtable.h" #include "nsILineInputStream.h" #include "nsTArray.h" #include "nsAutoPtr.h" // The nsMorkReader object allows a consumer to read in a mork-format // file and enumerate the rows that it contains. It does not provide // any functionality for modifying mork tables. // References: // http://www.mozilla.org/mailnews/arch/mork/primer.txt // http://www.mozilla.org/mailnews/arch/mork/grammar.txt // http://www.jwz.org/hacks/mork.pl class nsMorkReader { public: // This string type has built-in storage for the hex string representation // of a 32-bit row id or atom map key, plus the terminating null. class IDString : public nsFixedCString { public: IDString() : fixed_string_type(mStorage, sizeof(mStorage), 0) {} IDString(const substring_type &str) : fixed_string_type(mStorage, sizeof(mStorage), 0) { Assign(str); } private: char_type mStorage[9]; }; // Hashtable key type that contains an IDString class IDKey : public PLDHashEntryHdr { public: typedef const nsCSubstring& KeyType; typedef const nsCSubstring* KeyTypePointer; IDKey(KeyTypePointer aStr) : mStr(*aStr) { } IDKey(const IDKey& toCopy) : mStr(toCopy.mStr) { } ~IDKey() { } KeyType GetKey() const { return mStr; } KeyTypePointer GetKeyPointer() const { return &mStr; } PRBool KeyEquals(const KeyTypePointer aKey) const { return mStr.Equals(*aKey); } static KeyTypePointer KeyToPointer(KeyType aKey) { return &aKey; } static PLDHashNumber HashKey(const KeyTypePointer aKey) { return HashString(*aKey); } enum { ALLOW_MEMMOVE = PR_FALSE }; private: const IDString mStr; }; // A convenience typedef for an IDKey-to-string mapping. typedef nsDataHashtable StringMap; // A convenience typdef for an IDKey-to-index mapping, used for the // column index hashtable. typedef nsDataHashtable IndexMap; // A MorkColumn represents the data associated with a single table column. struct MorkColumn { MorkColumn(const nsCSubstring &i, const nsCSubstring &n) : id(i), name(n) {} IDString id; nsCString name; }; // Enumerator callback type for processing table rows. // A row contains cells. Each cell specifies a column id, and the value // for the column for that row. // rowID is the table-unique row id // values contains the cell values, in an order which corresponds to // the columns returned by GetColumns(). // You should call NormalizeValue() on any cell value that you plan to use. // userData is the opaque pointer passed to EnumerateRows() // The callback can return PL_DHASH_NEXT to continue enumerating, // or PL_DHASH_STOP to stop. typedef PLDHashOperator (*PR_CALLBACK RowEnumerator)(const nsCSubstring &rowID, const nsTArray *values, void *userData); // Initialize the importer object's data structures nsresult Init(); // Read in the given mork file // Note: currently, only single-table mork files are supported nsresult Read(nsIFile *aFile); // Returns the list of columns in the current table. const nsTArray& GetColumns() const { return mColumns; } // Enumerate the rows in the current table. void EnumerateRows(RowEnumerator aCallback, void *aUserData) const; // Get the "meta row" for the table. Each table has at most one meta row, // which records information about the table. Like normal rows, the // meta row contains columns in the same order as returned by GetColumns(). // Returns null if there is no meta row for this table. const nsTArray* GetMetaRow() const { return mMetaRow; } // Normalizes the cell value (resolves references to the value map). // aValue is modified in-place. void NormalizeValue(nsCString &aValue) const; nsMorkReader() {} ~nsMorkReader(); private: // Parses a line of the file which contains key/value pairs (either // the column map or the value map). Additional lines are read from // mStream if the line ends mid-entry. The pairs are added to aMap. nsresult ParseMap(const nsCSubstring &aLine, StringMap *aMap); // Parses a line of the file which contains a table or row definition. // Additional lines are read from mStream of the line ends mid-row. // An entry is added to mTable using the row ID as the key, which contains // a column array for the row. The supplied column hash table maps from // column id to an index in mColumns. nsresult ParseTable(const nsCSubstring &aLine, const IndexMap &aColumnMap); // Reads a single logical line from mStream into aLine. // Any continuation lines are consumed and appended to the line. nsresult ReadLine(nsCString &aLine); // Create a new nsCString array and fill it with the supplied number // of void strings. Returns null on out-of-memory. static nsTArray* NewVoidStringArray(PRInt32 aSize); nsTArray mColumns; StringMap mValueMap; nsAutoPtr< nsTArray > mMetaRow; nsDataHashtable< IDKey,nsTArray* > mTable; nsCOMPtr mStream; nsCString mEmptyString; // note: not EmptyCString() since that's not sharable }; #endif // nsMorkReader_h_