Back to index

lightning-sunbird  0.9+nobinonly
nsAttrValue.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; 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 mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * IBM Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 2003
00020  * IBM Corporation. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   IBM Corporation
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 nsAttrValue_h___
00040 #define nsAttrValue_h___
00041 
00042 #include "nscore.h"
00043 #include "nsString.h"
00044 #include "nsStringBuffer.h"
00045 #include "nsColor.h"
00046 #include "nsCOMArray.h"
00047 
00048 typedef unsigned long PtrBits;
00049 class nsAString;
00050 class nsIAtom;
00051 class nsICSSStyleRule;
00052 class nsISVGValue;
00053 class nsIDocument;
00054 
00055 #define NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM 12
00056 
00057 #define NS_ATTRVALUE_BASETYPE_MASK (PtrBits(3))
00058 #define NS_ATTRVALUE_POINTERVALUE_MASK (~NS_ATTRVALUE_BASETYPE_MASK)
00059 
00060 #define NS_ATTRVALUE_INTEGERTYPE_BITS 5
00061 #define NS_ATTRVALUE_INTEGERTYPE_MASK (PtrBits((1 << NS_ATTRVALUE_INTEGERTYPE_BITS) - 1))
00062 #define NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER (1 << NS_ATTRVALUE_INTEGERTYPE_BITS)
00063 #define NS_ATTRVALUE_INTEGERTYPE_MAXVALUE ((1 << (31 - NS_ATTRVALUE_INTEGERTYPE_BITS)) - 1)
00064 #define NS_ATTRVALUE_INTEGERTYPE_MINVALUE (-NS_ATTRVALUE_INTEGERTYPE_MAXVALUE - 1)
00065 
00066 #define NS_ATTRVALUE_ENUMTABLEINDEX_BITS (32 - 16 - NS_ATTRVALUE_INTEGERTYPE_BITS)
00067 #define NS_ATTRVALUE_ENUMTABLEINDEX_MAXVALUE ((1 << NS_ATTRVALUE_ENUMTABLEINDEX_BITS) - 1)
00068 #define NS_ATTRVALUE_ENUMTABLEINDEX_MASK (PtrBits((1 << NS_ATTRVALUE_ENUMTABLEINDEX_BITS) - 1))
00069 
00074 class nsCheapString : public nsString {
00075 public:
00076   nsCheapString(nsStringBuffer* aBuf)
00077   {
00078     if (aBuf)
00079       aBuf->ToString(aBuf->StorageSize()/2 - 1, *this);
00080   }
00081 };
00082 
00083 class nsAttrValue {
00084 public:
00085   nsAttrValue();
00086   nsAttrValue(const nsAttrValue& aOther);
00087   explicit nsAttrValue(const nsAString& aValue);
00088   explicit nsAttrValue(nsICSSStyleRule* aValue);
00089 #ifdef MOZ_SVG
00090   explicit nsAttrValue(nsISVGValue* aValue);
00091 #endif
00092   ~nsAttrValue();
00093 
00094   static nsresult Init();
00095   static void Shutdown();
00096 
00097   // This has to be the same as in ValueBaseType
00098   enum ValueType {
00099     eString =       0x00, //    00
00100                           //    01  this value indicates an 'misc' struct
00101     eAtom =         0x02, //    10
00102     eInteger =      0x03, // 00011
00103     eColor =        0x07, // 00111
00104     eProportional = 0x0B, // 01011
00105     eEnum =         0x0F, // 01111  This should eventually die
00106     ePercent =      0x13, // 10011
00107     // Values below here won't matter, they'll be stored in the 'misc' struct
00108     // anyway
00109     eCSSStyleRule = 0x14,
00110     eAtomArray =    0x15 
00111 #ifdef MOZ_SVG
00112     ,eSVGValue =    0x16
00113 #endif
00114   };
00115 
00116   ValueType Type() const;
00117 
00118   void Reset();
00119 
00120   void SetTo(const nsAttrValue& aOther);
00121   void SetTo(const nsAString& aValue);
00122   void SetTo(PRInt16 aInt);
00123   void SetTo(nsICSSStyleRule* aValue);
00124 #ifdef MOZ_SVG
00125   void SetTo(nsISVGValue* aValue);
00126 #endif
00127 
00128   void SwapValueWith(nsAttrValue& aOther);
00129 
00130   void ToString(nsAString& aResult) const;
00131 
00132   // Methods to get value. These methods do not convert so only use them
00133   // to retrieve the datatype that this nsAttrValue has.
00134   inline PRBool IsEmptyString() const;
00135   const nsCheapString GetStringValue() const;
00136   inline nsIAtom* GetAtomValue() const;
00137   inline PRInt32 GetIntegerValue() const;
00138   PRBool GetColorValue(nscolor& aColor) const;
00139   inline PRInt32 GetProportionalValue() const;
00140   inline PRInt16 GetEnumValue() const;
00141   inline float GetPercentValue() const;
00142   inline nsCOMArray<nsIAtom>* GetAtomArrayValue() const;
00143   inline nsICSSStyleRule* GetCSSStyleRuleValue() const;
00144 #ifdef MOZ_SVG
00145   inline nsISVGValue* GetSVGValue() const;
00146 #endif
00147 
00148   // Methods to get access to atoms we may have
00149   // Returns the number of atoms we have; 0 if we have none.  It's OK
00150   // to call this without checking the type first; it handles that.
00151   PRInt32 GetAtomCount() const;
00152   // Returns the atom at aIndex (0-based).  Do not call this with
00153   // aIndex >= GetAtomCount().
00154   nsIAtom* AtomAt(PRInt32 aIndex) const;
00155 
00156   PRUint32 HashValue() const;
00157   PRBool Equals(const nsAttrValue& aOther) const;
00158 
00159   void ParseAtom(const nsAString& aValue);
00160   void ParseAtomArray(const nsAString& aValue);
00161   void ParseStringOrAtom(const nsAString& aValue);
00162 
00173   struct EnumTable {
00175     const char* tag;
00177     PRInt16 value;
00178   };
00179 
00188   PRBool ParseEnumValue(const nsAString& aValue,
00189                         const EnumTable* aTable,
00190                         PRBool aCaseSensitive = PR_FALSE);
00191 
00202   PRBool ParseSpecialIntValue(const nsAString& aString,
00203                               PRBool aCanBePercent,
00204                               PRBool aCanBeProportional);
00205 
00206 
00213   PRBool ParseIntValue(const nsAString& aString) {
00214     return ParseIntWithBounds(aString, NS_ATTRVALUE_INTEGERTYPE_MINVALUE,
00215                               NS_ATTRVALUE_INTEGERTYPE_MAXVALUE);
00216   }
00217 
00226   PRBool ParseIntWithBounds(const nsAString& aString, PRInt32 aMin,
00227                             PRInt32 aMax = NS_ATTRVALUE_INTEGERTYPE_MAXVALUE);
00228 
00236   PRBool ParseColor(const nsAString& aString, nsIDocument* aDocument);
00237 
00238 private:
00239   // These have to be the same as in ValueType
00240   enum ValueBaseType {
00241     eStringBase =    eString,    // 00
00242     eOtherBase =     0x01,       // 01
00243     eAtomBase =      eAtom,      // 10
00244     eIntegerBase =   0x03        // 11
00245   };
00246 
00247   struct MiscContainer
00248   {
00249     ValueType mType;
00250     union {
00251       nscolor mColor;
00252       nsICSSStyleRule* mCSSStyleRule;
00253       nsCOMArray<nsIAtom>* mAtomArray;
00254 #ifdef MOZ_SVG
00255       nsISVGValue* mSVGValue;
00256 #endif
00257     };
00258   };
00259 
00260   inline ValueBaseType BaseType() const;
00261 
00262   inline void SetPtrValueAndType(void* aValue, ValueBaseType aType);
00263   inline void SetIntValueAndType(PRInt32 aValue, ValueType aType);
00264   inline void ResetIfSet();
00265 
00266   inline void* GetPtr() const;
00267   inline MiscContainer* GetMiscContainer() const;
00268   inline PRInt32 GetIntInternal() const;
00269 
00270   PRBool EnsureEmptyMiscContainer();
00271   PRBool EnsureEmptyAtomArray();
00272 
00273   static nsVoidArray* sEnumTableArray;
00274 
00275   PtrBits mBits;
00276 };
00277 
00282 inline nsIAtom*
00283 nsAttrValue::GetAtomValue() const
00284 {
00285   NS_PRECONDITION(Type() == eAtom, "wrong type");
00286   return NS_REINTERPRET_CAST(nsIAtom*, GetPtr());
00287 }
00288 
00289 inline PRInt32
00290 nsAttrValue::GetIntegerValue() const
00291 {
00292   NS_PRECONDITION(Type() == eInteger, "wrong type");
00293   return GetIntInternal();
00294 }
00295 
00296 inline PRInt32
00297 nsAttrValue::GetProportionalValue() const
00298 {
00299   NS_PRECONDITION(Type() == eProportional, "wrong type");
00300   return GetIntInternal();
00301 }
00302 
00303 inline PRInt16
00304 nsAttrValue::GetEnumValue() const
00305 {
00306   NS_PRECONDITION(Type() == eEnum, "wrong type");
00307   // We don't need to worry about sign extension here since we're
00308   // returning an PRInt16 which will cut away the top bits.
00309   return NS_STATIC_CAST(PRInt16,
00310             GetIntInternal() >> NS_ATTRVALUE_ENUMTABLEINDEX_BITS);
00311 }
00312 
00313 inline float
00314 nsAttrValue::GetPercentValue() const
00315 {
00316   NS_PRECONDITION(Type() == ePercent, "wrong type");
00317   return NS_STATIC_CAST(float, GetIntInternal()) /
00318          100.0f;
00319 }
00320 
00321 inline nsCOMArray<nsIAtom>*
00322 nsAttrValue::GetAtomArrayValue() const
00323 {
00324   NS_PRECONDITION(Type() == eAtomArray, "wrong type");
00325   return GetMiscContainer()->mAtomArray;
00326 }
00327 
00328 inline nsICSSStyleRule*
00329 nsAttrValue::GetCSSStyleRuleValue() const
00330 {
00331   NS_PRECONDITION(Type() == eCSSStyleRule, "wrong type");
00332   return GetMiscContainer()->mCSSStyleRule;
00333 }
00334 
00335 #ifdef MOZ_SVG
00336 inline nsISVGValue*
00337 nsAttrValue::GetSVGValue() const
00338 {
00339   NS_PRECONDITION(Type() == eSVGValue, "wrong type");
00340   return GetMiscContainer()->mSVGValue;
00341 }
00342 #endif
00343 
00344 inline nsAttrValue::ValueBaseType
00345 nsAttrValue::BaseType() const
00346 {
00347   return NS_STATIC_CAST(ValueBaseType, mBits & NS_ATTRVALUE_BASETYPE_MASK);
00348 }
00349 
00350 inline void
00351 nsAttrValue::SetPtrValueAndType(void* aValue, ValueBaseType aType)
00352 {
00353   NS_ASSERTION(!(NS_PTR_TO_INT32(aValue) & ~NS_ATTRVALUE_POINTERVALUE_MASK),
00354                "pointer not properly aligned, this will crash");
00355   mBits = NS_REINTERPRET_CAST(PtrBits, aValue) | aType;
00356 }
00357 
00358 inline void
00359 nsAttrValue::SetIntValueAndType(PRInt32 aValue, ValueType aType)
00360 {
00361 #ifdef DEBUG
00362   {
00363     PRInt32 tmp = aValue * NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER;
00364     NS_ASSERTION(tmp / NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER == aValue,
00365                  "Integer too big to fit");
00366   }
00367 #endif
00368   mBits = (aValue * NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER) | aType;
00369 }
00370 
00371 inline void
00372 nsAttrValue::ResetIfSet()
00373 {
00374   if (mBits) {
00375     Reset();
00376   }
00377 }
00378 
00379 inline void*
00380 nsAttrValue::GetPtr() const
00381 {
00382   NS_ASSERTION(BaseType() != eIntegerBase,
00383                "getting pointer from non-pointer");
00384   return NS_REINTERPRET_CAST(void*, mBits & NS_ATTRVALUE_POINTERVALUE_MASK);
00385 }
00386 
00387 inline nsAttrValue::MiscContainer*
00388 nsAttrValue::GetMiscContainer() const
00389 {
00390   NS_ASSERTION(BaseType() == eOtherBase, "wrong type");
00391   return NS_STATIC_CAST(MiscContainer*, GetPtr());
00392 }
00393 
00394 inline PRInt32
00395 nsAttrValue::GetIntInternal() const
00396 {
00397   NS_ASSERTION(BaseType() == eIntegerBase,
00398                "getting integer from non-integer");
00399   // Make sure we get a signed value.
00400   // Lets hope the optimizer optimizes this into a shift. Unfortunatly signed
00401   // bitshift right is implementaion dependant.
00402   return NS_STATIC_CAST(PRInt32, mBits & ~NS_ATTRVALUE_INTEGERTYPE_MASK) /
00403          NS_ATTRVALUE_INTEGERTYPE_MULTIPLIER;
00404 }
00405 
00406 inline PRBool
00407 nsAttrValue::IsEmptyString() const
00408 {
00409   return !mBits;
00410 }
00411 
00412 #endif