Fri, 16 Jan 2015 18:13:44 +0100
Integrate suggestion from review to improve consistency with existing code.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | |
michael@0 | 7 | /** |
michael@0 | 8 | * |
michael@0 | 9 | * A sample of XPConnect. This file contains an implementation nsSample |
michael@0 | 10 | * of the interface nsISample. |
michael@0 | 11 | * |
michael@0 | 12 | */ |
michael@0 | 13 | #include <stdio.h> |
michael@0 | 14 | |
michael@0 | 15 | #include "nsSample.h" |
michael@0 | 16 | #include "nsMemory.h" |
michael@0 | 17 | |
michael@0 | 18 | #include "nsEmbedString.h" |
michael@0 | 19 | #include "nsIClassInfoImpl.h" |
michael@0 | 20 | //////////////////////////////////////////////////////////////////////// |
michael@0 | 21 | |
michael@0 | 22 | nsSampleImpl::nsSampleImpl() : mValue(nullptr) |
michael@0 | 23 | { |
michael@0 | 24 | mValue = (char*)nsMemory::Clone("initial value", 14); |
michael@0 | 25 | } |
michael@0 | 26 | |
michael@0 | 27 | nsSampleImpl::~nsSampleImpl() |
michael@0 | 28 | { |
michael@0 | 29 | if (mValue) |
michael@0 | 30 | nsMemory::Free(mValue); |
michael@0 | 31 | } |
michael@0 | 32 | |
michael@0 | 33 | /** |
michael@0 | 34 | * NS_IMPL_ISUPPORTS expands to a simple implementation of the nsISupports |
michael@0 | 35 | * interface. This includes a proper implementation of AddRef, Release, |
michael@0 | 36 | * and QueryInterface. If this class supported more interfaces than just |
michael@0 | 37 | * nsISupports, |
michael@0 | 38 | * you could use NS_IMPL_ADDREF() and NS_IMPL_RELEASE() to take care of the |
michael@0 | 39 | * simple stuff, but you would have to create QueryInterface on your own. |
michael@0 | 40 | * nsSampleFactory.cpp is an example of this approach. |
michael@0 | 41 | * Notice that the second parameter to the macro is name of the interface, and |
michael@0 | 42 | * NOT the #defined IID. |
michael@0 | 43 | * |
michael@0 | 44 | * The _CI variant adds support for nsIClassInfo, which permits introspection |
michael@0 | 45 | * and interface flattening. |
michael@0 | 46 | */ |
michael@0 | 47 | NS_IMPL_CLASSINFO(nsSampleImpl, nullptr, 0, NS_SAMPLE_CID) |
michael@0 | 48 | NS_IMPL_ISUPPORTS_CI(nsSampleImpl, nsISample) |
michael@0 | 49 | /** |
michael@0 | 50 | * Notice that in the protoype for this function, the NS_IMETHOD macro was |
michael@0 | 51 | * used to declare the return type. For the implementation, the return |
michael@0 | 52 | * type is declared by NS_IMETHODIMP |
michael@0 | 53 | */ |
michael@0 | 54 | NS_IMETHODIMP |
michael@0 | 55 | nsSampleImpl::GetValue(char** aValue) |
michael@0 | 56 | { |
michael@0 | 57 | NS_PRECONDITION(aValue != nullptr, "null ptr"); |
michael@0 | 58 | if (! aValue) |
michael@0 | 59 | return NS_ERROR_NULL_POINTER; |
michael@0 | 60 | |
michael@0 | 61 | if (mValue) { |
michael@0 | 62 | /** |
michael@0 | 63 | * GetValue's job is to return data known by an instance of |
michael@0 | 64 | * nsSampleImpl to the outside world. If we were to simply return |
michael@0 | 65 | * a pointer to data owned by this instance, and the client were to |
michael@0 | 66 | * free it, bad things would surely follow. |
michael@0 | 67 | * On the other hand, if we create a new copy of the data for our |
michael@0 | 68 | * client, and it turns out that client is implemented in JavaScript, |
michael@0 | 69 | * there would be no way to free the buffer. The solution to the |
michael@0 | 70 | * buffer ownership problem is the nsMemory singleton. Any buffer |
michael@0 | 71 | * returned by an XPCOM method should be allocated by the nsMemory. |
michael@0 | 72 | * This convention lets things like JavaScript reflection do their |
michael@0 | 73 | * job, and simplifies the way C++ clients deal with returned buffers. |
michael@0 | 74 | */ |
michael@0 | 75 | *aValue = (char*) nsMemory::Clone(mValue, strlen(mValue) + 1); |
michael@0 | 76 | if (! *aValue) |
michael@0 | 77 | return NS_ERROR_NULL_POINTER; |
michael@0 | 78 | } |
michael@0 | 79 | else { |
michael@0 | 80 | *aValue = nullptr; |
michael@0 | 81 | } |
michael@0 | 82 | return NS_OK; |
michael@0 | 83 | } |
michael@0 | 84 | |
michael@0 | 85 | NS_IMETHODIMP |
michael@0 | 86 | nsSampleImpl::SetValue(const char* aValue) |
michael@0 | 87 | { |
michael@0 | 88 | NS_PRECONDITION(aValue != nullptr, "null ptr"); |
michael@0 | 89 | if (! aValue) |
michael@0 | 90 | return NS_ERROR_NULL_POINTER; |
michael@0 | 91 | |
michael@0 | 92 | if (mValue) { |
michael@0 | 93 | nsMemory::Free(mValue); |
michael@0 | 94 | } |
michael@0 | 95 | |
michael@0 | 96 | /** |
michael@0 | 97 | * Another buffer passing convention is that buffers passed INTO your |
michael@0 | 98 | * object ARE NOT YOURS. Keep your hands off them, unless they are |
michael@0 | 99 | * declared "inout". If you want to keep the value for posterity, |
michael@0 | 100 | * you will have to make a copy of it. |
michael@0 | 101 | */ |
michael@0 | 102 | mValue = (char*) nsMemory::Clone(aValue, strlen(aValue) + 1); |
michael@0 | 103 | return NS_OK; |
michael@0 | 104 | } |
michael@0 | 105 | |
michael@0 | 106 | NS_IMETHODIMP |
michael@0 | 107 | nsSampleImpl::Poke(const char* aValue) |
michael@0 | 108 | { |
michael@0 | 109 | return SetValue((char*) aValue); |
michael@0 | 110 | } |
michael@0 | 111 | |
michael@0 | 112 | |
michael@0 | 113 | static void GetStringValue(nsACString& aValue) |
michael@0 | 114 | { |
michael@0 | 115 | NS_CStringSetData(aValue, "GetValue"); |
michael@0 | 116 | } |
michael@0 | 117 | |
michael@0 | 118 | NS_IMETHODIMP |
michael@0 | 119 | nsSampleImpl::WriteValue(const char* aPrefix) |
michael@0 | 120 | { |
michael@0 | 121 | NS_PRECONDITION(aPrefix != nullptr, "null ptr"); |
michael@0 | 122 | if (! aPrefix) |
michael@0 | 123 | return NS_ERROR_NULL_POINTER; |
michael@0 | 124 | |
michael@0 | 125 | printf("%s %s\n", aPrefix, mValue); |
michael@0 | 126 | |
michael@0 | 127 | // This next part illustrates the nsEmbedString: |
michael@0 | 128 | nsEmbedString foopy; |
michael@0 | 129 | foopy.Append(char16_t('f')); |
michael@0 | 130 | foopy.Append(char16_t('o')); |
michael@0 | 131 | foopy.Append(char16_t('o')); |
michael@0 | 132 | foopy.Append(char16_t('p')); |
michael@0 | 133 | foopy.Append(char16_t('y')); |
michael@0 | 134 | |
michael@0 | 135 | const char16_t* f = foopy.get(); |
michael@0 | 136 | uint32_t l = foopy.Length(); |
michael@0 | 137 | printf("%c%c%c%c%c %d\n", char(f[0]), char(f[1]), char(f[2]), char(f[3]), char(f[4]), l); |
michael@0 | 138 | |
michael@0 | 139 | nsEmbedCString foopy2; |
michael@0 | 140 | GetStringValue(foopy2); |
michael@0 | 141 | |
michael@0 | 142 | //foopy2.AppendLiteral("foopy"); |
michael@0 | 143 | const char* f2 = foopy2.get(); |
michael@0 | 144 | uint32_t l2 = foopy2.Length(); |
michael@0 | 145 | |
michael@0 | 146 | printf("%s %d\n", f2, l2); |
michael@0 | 147 | |
michael@0 | 148 | return NS_OK; |
michael@0 | 149 | } |