Bug 1885489 - Part 5: Add SnapshotIterator::readInt32(). r=iain
[gecko.git] / xpcom / threads / nsEnvironment.cpp
blob54efd9194a46580a7c1dbb6fd3c478413208597a
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsEnvironment.h"
8 #include "prenv.h"
9 #include "nsBaseHashtable.h"
10 #include "nsHashKeys.h"
11 #include "nsPromiseFlatString.h"
12 #include "nsDependentString.h"
13 #include "nsNativeCharsetUtils.h"
14 #include "mozilla/Printf.h"
15 #include "mozilla/StaticMutex.h"
17 using namespace mozilla;
19 NS_IMPL_ISUPPORTS(nsEnvironment, nsIEnvironment)
21 nsresult nsEnvironment::Create(REFNSIID aIID, void** aResult) {
22 nsresult rv;
23 *aResult = nullptr;
25 nsEnvironment* obj = new nsEnvironment();
27 rv = obj->QueryInterface(aIID, aResult);
28 if (NS_FAILED(rv)) {
29 delete obj;
31 return rv;
34 NS_IMETHODIMP
35 nsEnvironment::Exists(const nsAString& aName, bool* aOutValue) {
36 nsAutoCString nativeName;
37 nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
38 if (NS_WARN_IF(NS_FAILED(rv))) {
39 return rv;
42 nsAutoCString nativeVal;
43 #if defined(XP_UNIX)
44 /* For Unix/Linux platforms we follow the Unix definition:
45 * An environment variable exists when |getenv()| returns a non-nullptr
46 * value. An environment variable does not exist when |getenv()| returns
47 * nullptr.
49 const char* value = PR_GetEnv(nativeName.get());
50 *aOutValue = value && *value;
51 #else
52 /* For non-Unix/Linux platforms we have to fall back to a
53 * "portable" definition (which is incorrect for Unix/Linux!!!!)
54 * which simply checks whether the string returned by |Get()| is empty
55 * or not.
57 nsAutoString value;
58 Get(aName, value);
59 *aOutValue = !value.IsEmpty();
60 #endif /* XP_UNIX */
62 return NS_OK;
65 NS_IMETHODIMP
66 nsEnvironment::Get(const nsAString& aName, nsAString& aOutValue) {
67 nsAutoCString nativeName;
68 nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
69 if (NS_WARN_IF(NS_FAILED(rv))) {
70 return rv;
73 nsAutoCString nativeVal;
74 const char* value = PR_GetEnv(nativeName.get());
75 if (value && *value) {
76 rv = NS_CopyNativeToUnicode(nsDependentCString(value), aOutValue);
77 } else {
78 aOutValue.Truncate();
79 rv = NS_OK;
82 return rv;
85 /* Environment strings must have static duration; We're gonna leak all of this
86 * at shutdown: this is by design, caused how Unix/Linux implement environment
87 * vars.
90 typedef nsBaseHashtableET<nsCharPtrHashKey, char*> EnvEntryType;
91 typedef nsTHashtable<EnvEntryType> EnvHashType;
93 static StaticMutex gEnvHashMutex;
94 static EnvHashType* gEnvHash MOZ_GUARDED_BY(gEnvHashMutex) = nullptr;
96 static EnvHashType* EnsureEnvHash() MOZ_REQUIRES(gEnvHashMutex) {
97 if (!gEnvHash) {
98 gEnvHash = new EnvHashType;
100 return gEnvHash;
103 NS_IMETHODIMP
104 nsEnvironment::Set(const nsAString& aName, const nsAString& aValue) {
105 nsAutoCString nativeName;
106 nsAutoCString nativeVal;
108 nsresult rv = NS_CopyUnicodeToNative(aName, nativeName);
109 if (NS_WARN_IF(NS_FAILED(rv))) {
110 return rv;
113 rv = NS_CopyUnicodeToNative(aValue, nativeVal);
114 if (NS_WARN_IF(NS_FAILED(rv))) {
115 return rv;
118 StaticMutexAutoLock lock(gEnvHashMutex);
119 EnvEntryType* entry = EnsureEnvHash()->PutEntry(nativeName.get());
120 if (!entry) {
121 return NS_ERROR_OUT_OF_MEMORY;
124 SmprintfPointer newData =
125 mozilla::Smprintf("%s=%s", nativeName.get(), nativeVal.get());
126 if (!newData) {
127 return NS_ERROR_OUT_OF_MEMORY;
130 PR_SetEnv(newData.get());
131 if (entry->GetData()) {
132 free(entry->GetData());
134 entry->SetData(newData.release());
135 return NS_OK;