1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/bindings/DOMString.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,186 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef mozilla_dom_DOMString_h 1.10 +#define mozilla_dom_DOMString_h 1.11 + 1.12 +#include "nsStringGlue.h" 1.13 +#include "nsStringBuffer.h" 1.14 +#include "mozilla/Assertions.h" 1.15 +#include "mozilla/Attributes.h" 1.16 +#include "mozilla/Maybe.h" 1.17 +#include "nsDOMString.h" 1.18 +#include "nsIAtom.h" 1.19 + 1.20 +namespace mozilla { 1.21 +namespace dom { 1.22 + 1.23 +/** 1.24 + * A class for representing string return values. This can be either passed to 1.25 + * callees that have an nsString or nsAString out param or passed to a callee 1.26 + * that actually knows about this class and can work with it. Such a callee may 1.27 + * call SetStringBuffer or SetOwnedString or SetOwnedAtom on this object, but 1.28 + * only if it plans to keep holding a strong ref to the internal stringbuffer! 1.29 + * 1.30 + * The proper way to store a value in this class is to either to do nothing 1.31 + * (which leaves this as an empty string), to call SetStringBuffer with a 1.32 + * non-null stringbuffer, to call SetOwnedString, to call SetOwnedAtom, to call 1.33 + * SetNull(), or to call AsAString() and set the value in the resulting 1.34 + * nsString. These options are mutually exclusive! Don't do more than one of 1.35 + * them. 1.36 + * 1.37 + * The proper way to extract a value is to check IsNull(). If not null, then 1.38 + * check HasStringBuffer(). If that's true, check for a zero length, and if the 1.39 + * length is nonzero call StringBuffer(). If the length is zero this is the 1.40 + * empty string. If HasStringBuffer() returns false, call AsAString() and get 1.41 + * the value from that. 1.42 + */ 1.43 +class MOZ_STACK_CLASS DOMString { 1.44 +public: 1.45 + DOMString() 1.46 + : mStringBuffer(nullptr) 1.47 + , mLength(0) 1.48 + , mIsNull(false) 1.49 + {} 1.50 + ~DOMString() 1.51 + { 1.52 + MOZ_ASSERT(mString.empty() || !mStringBuffer, 1.53 + "Shouldn't have both present!"); 1.54 + } 1.55 + 1.56 + operator nsString&() 1.57 + { 1.58 + return AsAString(); 1.59 + } 1.60 + 1.61 + nsString& AsAString() 1.62 + { 1.63 + MOZ_ASSERT(!mStringBuffer, "We already have a stringbuffer?"); 1.64 + MOZ_ASSERT(!mIsNull, "We're already set as null"); 1.65 + if (mString.empty()) { 1.66 + mString.construct(); 1.67 + } 1.68 + return mString.ref(); 1.69 + } 1.70 + 1.71 + bool HasStringBuffer() const 1.72 + { 1.73 + MOZ_ASSERT(mString.empty() || !mStringBuffer, 1.74 + "Shouldn't have both present!"); 1.75 + MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first"); 1.76 + return mString.empty(); 1.77 + } 1.78 + 1.79 + // Get the stringbuffer. This can only be called if HasStringBuffer() 1.80 + // returned true and StringBufferLength() is nonzero. If that's true, it will 1.81 + // never return null. 1.82 + nsStringBuffer* StringBuffer() const 1.83 + { 1.84 + MOZ_ASSERT(!mIsNull, "Caller should have checked IsNull() first"); 1.85 + MOZ_ASSERT(HasStringBuffer(), 1.86 + "Don't ask for the stringbuffer if we don't have it"); 1.87 + MOZ_ASSERT(StringBufferLength() != 0, "Why are you asking for this?"); 1.88 + MOZ_ASSERT(mStringBuffer, 1.89 + "If our length is nonzero, we better have a stringbuffer."); 1.90 + return mStringBuffer; 1.91 + } 1.92 + 1.93 + // Get the length of the stringbuffer. Can only be called if 1.94 + // HasStringBuffer(). 1.95 + uint32_t StringBufferLength() const 1.96 + { 1.97 + MOZ_ASSERT(HasStringBuffer(), "Don't call this if there is no stringbuffer"); 1.98 + return mLength; 1.99 + } 1.100 + 1.101 + void SetStringBuffer(nsStringBuffer* aStringBuffer, uint32_t aLength) 1.102 + { 1.103 + MOZ_ASSERT(mString.empty(), "We already have a string?"); 1.104 + MOZ_ASSERT(!mIsNull, "We're already set as null"); 1.105 + MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?"); 1.106 + MOZ_ASSERT(aStringBuffer, "Why are we getting null?"); 1.107 + mStringBuffer = aStringBuffer; 1.108 + mLength = aLength; 1.109 + } 1.110 + 1.111 + void SetOwnedString(const nsAString& aString) 1.112 + { 1.113 + MOZ_ASSERT(mString.empty(), "We already have a string?"); 1.114 + MOZ_ASSERT(!mIsNull, "We're already set as null"); 1.115 + MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?"); 1.116 + nsStringBuffer* buf = nsStringBuffer::FromString(aString); 1.117 + if (buf) { 1.118 + SetStringBuffer(buf, aString.Length()); 1.119 + } else if (aString.IsVoid()) { 1.120 + SetNull(); 1.121 + } else if (!aString.IsEmpty()) { 1.122 + AsAString() = aString; 1.123 + } 1.124 + } 1.125 + 1.126 + enum NullHandling 1.127 + { 1.128 + eTreatNullAsNull, 1.129 + eTreatNullAsEmpty, 1.130 + eNullNotExpected 1.131 + }; 1.132 + 1.133 + void SetOwnedAtom(nsIAtom* aAtom, NullHandling aNullHandling) 1.134 + { 1.135 + MOZ_ASSERT(mString.empty(), "We already have a string?"); 1.136 + MOZ_ASSERT(!mIsNull, "We're already set as null"); 1.137 + MOZ_ASSERT(!mStringBuffer, "Setting stringbuffer twice?"); 1.138 + MOZ_ASSERT(aAtom || aNullHandling != eNullNotExpected); 1.139 + if (aNullHandling == eNullNotExpected || aAtom) { 1.140 + SetStringBuffer(aAtom->GetStringBuffer(), aAtom->GetLength()); 1.141 + } else if (aNullHandling == eTreatNullAsNull) { 1.142 + SetNull(); 1.143 + } 1.144 + } 1.145 + 1.146 + void SetNull() 1.147 + { 1.148 + MOZ_ASSERT(!mStringBuffer, "Should have no stringbuffer if null"); 1.149 + MOZ_ASSERT(mString.empty(), "Should have no string if null"); 1.150 + mIsNull = true; 1.151 + } 1.152 + 1.153 + bool IsNull() const 1.154 + { 1.155 + MOZ_ASSERT(!mStringBuffer || mString.empty(), 1.156 + "How could we have a stringbuffer and a nonempty string?"); 1.157 + return mIsNull || (!mString.empty() && mString.ref().IsVoid()); 1.158 + } 1.159 + 1.160 + void ToString(nsAString& aString) 1.161 + { 1.162 + if (IsNull()) { 1.163 + SetDOMStringToNull(aString); 1.164 + } else if (HasStringBuffer()) { 1.165 + if (StringBufferLength() == 0) { 1.166 + aString.Truncate(); 1.167 + } else { 1.168 + StringBuffer()->ToString(StringBufferLength(), aString); 1.169 + } 1.170 + } else { 1.171 + aString = AsAString(); 1.172 + } 1.173 + } 1.174 + 1.175 +private: 1.176 + // We need to be able to act like a string as needed 1.177 + Maybe<nsAutoString> mString; 1.178 + 1.179 + // For callees that know we exist, we can be a stringbuffer/length/null-flag 1.180 + // triple. 1.181 + nsStringBuffer* mStringBuffer; 1.182 + uint32_t mLength; 1.183 + bool mIsNull; 1.184 +}; 1.185 + 1.186 +} // namespace dom 1.187 +} // namespace mozilla 1.188 + 1.189 +#endif // mozilla_dom_DOMString_h