1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/xpcom/ds/nsStringEnumerator.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,227 @@ 1.4 +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 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 + 1.10 +#include "nsStringEnumerator.h" 1.11 +#include "nsISimpleEnumerator.h" 1.12 +#include "nsSupportsPrimitives.h" 1.13 +#include "mozilla/Attributes.h" 1.14 +#include "nsTArray.h" 1.15 + 1.16 +// 1.17 +// nsStringEnumerator 1.18 +// 1.19 + 1.20 +class nsStringEnumerator MOZ_FINAL : public nsIStringEnumerator, 1.21 + public nsIUTF8StringEnumerator, 1.22 + public nsISimpleEnumerator 1.23 +{ 1.24 +public: 1.25 + nsStringEnumerator(const nsTArray<nsString>* aArray, bool aOwnsArray) : 1.26 + mArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(true) 1.27 + {} 1.28 + 1.29 + nsStringEnumerator(const nsTArray<nsCString>* aArray, bool aOwnsArray) : 1.30 + mCArray(aArray), mIndex(0), mOwnsArray(aOwnsArray), mIsUnicode(false) 1.31 + {} 1.32 + 1.33 + nsStringEnumerator(const nsTArray<nsString>* aArray, nsISupports* aOwner) : 1.34 + mArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(false), mIsUnicode(true) 1.35 + {} 1.36 + 1.37 + nsStringEnumerator(const nsTArray<nsCString>* aArray, nsISupports* aOwner) : 1.38 + mCArray(aArray), mIndex(0), mOwner(aOwner), mOwnsArray(false), mIsUnicode(false) 1.39 + {} 1.40 + 1.41 + NS_DECL_ISUPPORTS 1.42 + NS_DECL_NSIUTF8STRINGENUMERATOR 1.43 + 1.44 + // have to declare nsIStringEnumerator manually, because of 1.45 + // overlapping method names 1.46 + NS_IMETHOD GetNext(nsAString& aResult); 1.47 + NS_DECL_NSISIMPLEENUMERATOR 1.48 + 1.49 +private: 1.50 + ~nsStringEnumerator() { 1.51 + if (mOwnsArray) { 1.52 + // const-casting is safe here, because the NS_New* 1.53 + // constructors make sure mOwnsArray is consistent with 1.54 + // the constness of the objects 1.55 + if (mIsUnicode) 1.56 + delete const_cast<nsTArray<nsString>*>(mArray); 1.57 + else 1.58 + delete const_cast<nsTArray<nsCString>*>(mCArray); 1.59 + } 1.60 + } 1.61 + 1.62 + union { 1.63 + const nsTArray<nsString>* mArray; 1.64 + const nsTArray<nsCString>* mCArray; 1.65 + }; 1.66 + 1.67 + inline uint32_t Count() { 1.68 + return mIsUnicode ? mArray->Length() : mCArray->Length(); 1.69 + } 1.70 + 1.71 + uint32_t mIndex; 1.72 + 1.73 + // the owner allows us to hold a strong reference to the object 1.74 + // that owns the array. Having a non-null value in mOwner implies 1.75 + // that mOwnsArray is false, because we rely on the real owner 1.76 + // to release the array 1.77 + nsCOMPtr<nsISupports> mOwner; 1.78 + bool mOwnsArray; 1.79 + bool mIsUnicode; 1.80 +}; 1.81 + 1.82 +NS_IMPL_ISUPPORTS(nsStringEnumerator, 1.83 + nsIStringEnumerator, 1.84 + nsIUTF8StringEnumerator, 1.85 + nsISimpleEnumerator) 1.86 + 1.87 +NS_IMETHODIMP 1.88 +nsStringEnumerator::HasMore(bool* aResult) 1.89 +{ 1.90 + *aResult = mIndex < Count(); 1.91 + return NS_OK; 1.92 +} 1.93 + 1.94 +NS_IMETHODIMP 1.95 +nsStringEnumerator::HasMoreElements(bool* aResult) 1.96 +{ 1.97 + return HasMore(aResult); 1.98 +} 1.99 + 1.100 +NS_IMETHODIMP 1.101 +nsStringEnumerator::GetNext(nsISupports** aResult) 1.102 +{ 1.103 + if (mIsUnicode) { 1.104 + nsSupportsStringImpl* stringImpl = new nsSupportsStringImpl(); 1.105 + if (!stringImpl) return NS_ERROR_OUT_OF_MEMORY; 1.106 + 1.107 + stringImpl->SetData(mArray->ElementAt(mIndex++)); 1.108 + *aResult = stringImpl; 1.109 + } 1.110 + else { 1.111 + nsSupportsCStringImpl* cstringImpl = new nsSupportsCStringImpl(); 1.112 + if (!cstringImpl) return NS_ERROR_OUT_OF_MEMORY; 1.113 + 1.114 + cstringImpl->SetData(mCArray->ElementAt(mIndex++)); 1.115 + *aResult = cstringImpl; 1.116 + } 1.117 + NS_ADDREF(*aResult); 1.118 + return NS_OK; 1.119 +} 1.120 + 1.121 +NS_IMETHODIMP 1.122 +nsStringEnumerator::GetNext(nsAString& aResult) 1.123 +{ 1.124 + if (NS_WARN_IF(mIndex >= Count())) 1.125 + return NS_ERROR_UNEXPECTED; 1.126 + 1.127 + if (mIsUnicode) 1.128 + aResult = mArray->ElementAt(mIndex++); 1.129 + else 1.130 + CopyUTF8toUTF16(mCArray->ElementAt(mIndex++), aResult); 1.131 + 1.132 + return NS_OK; 1.133 +} 1.134 + 1.135 +NS_IMETHODIMP 1.136 +nsStringEnumerator::GetNext(nsACString& aResult) 1.137 +{ 1.138 + if (NS_WARN_IF(mIndex >= Count())) 1.139 + return NS_ERROR_UNEXPECTED; 1.140 + 1.141 + if (mIsUnicode) 1.142 + CopyUTF16toUTF8(mArray->ElementAt(mIndex++), aResult); 1.143 + else 1.144 + aResult = mCArray->ElementAt(mIndex++); 1.145 + 1.146 + return NS_OK; 1.147 +} 1.148 + 1.149 +template<class T> 1.150 +static inline nsresult 1.151 +StringEnumeratorTail(T** aResult) 1.152 +{ 1.153 + if (!*aResult) 1.154 + return NS_ERROR_OUT_OF_MEMORY; 1.155 + NS_ADDREF(*aResult); 1.156 + return NS_OK; 1.157 +} 1.158 + 1.159 +// 1.160 +// constructors 1.161 +// 1.162 + 1.163 +nsresult 1.164 +NS_NewStringEnumerator(nsIStringEnumerator** aResult, 1.165 + const nsTArray<nsString>* aArray, nsISupports* aOwner) 1.166 +{ 1.167 + if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) 1.168 + return NS_ERROR_INVALID_ARG; 1.169 + 1.170 + *aResult = new nsStringEnumerator(aArray, aOwner); 1.171 + return StringEnumeratorTail(aResult); 1.172 +} 1.173 + 1.174 + 1.175 +nsresult 1.176 +NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult, 1.177 + const nsTArray<nsCString>* aArray, nsISupports* aOwner) 1.178 +{ 1.179 + if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) 1.180 + return NS_ERROR_INVALID_ARG; 1.181 + 1.182 + *aResult = new nsStringEnumerator(aArray, aOwner); 1.183 + return StringEnumeratorTail(aResult); 1.184 +} 1.185 + 1.186 +nsresult 1.187 +NS_NewAdoptingStringEnumerator(nsIStringEnumerator** aResult, 1.188 + nsTArray<nsString>* aArray) 1.189 +{ 1.190 + if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) 1.191 + return NS_ERROR_INVALID_ARG; 1.192 + 1.193 + *aResult = new nsStringEnumerator(aArray, true); 1.194 + return StringEnumeratorTail(aResult); 1.195 +} 1.196 + 1.197 +nsresult 1.198 +NS_NewAdoptingUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult, 1.199 + nsTArray<nsCString>* aArray) 1.200 +{ 1.201 + if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) 1.202 + return NS_ERROR_INVALID_ARG; 1.203 + 1.204 + *aResult = new nsStringEnumerator(aArray, true); 1.205 + return StringEnumeratorTail(aResult); 1.206 +} 1.207 + 1.208 +// const ones internally just forward to the non-const equivalents 1.209 +nsresult 1.210 +NS_NewStringEnumerator(nsIStringEnumerator** aResult, 1.211 + const nsTArray<nsString>* aArray) 1.212 +{ 1.213 + if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) 1.214 + return NS_ERROR_INVALID_ARG; 1.215 + 1.216 + *aResult = new nsStringEnumerator(aArray, false); 1.217 + return StringEnumeratorTail(aResult); 1.218 +} 1.219 + 1.220 +nsresult 1.221 +NS_NewUTF8StringEnumerator(nsIUTF8StringEnumerator** aResult, 1.222 + const nsTArray<nsCString>* aArray) 1.223 +{ 1.224 + if (NS_WARN_IF(!aResult) || NS_WARN_IF(!aArray)) 1.225 + return NS_ERROR_INVALID_ARG; 1.226 + 1.227 + *aResult = new nsStringEnumerator(aArray, false); 1.228 + return StringEnumeratorTail(aResult); 1.229 +} 1.230 +