Bug 1249157: prefapi enums into class enums, explicit conversion, cleanup. r=bsmedberg
MozReview-Commit-ID: nvvOD8ajV4
--- a/modules/libpref/Preferences.cpp
+++ b/modules/libpref/Preferences.cpp
@@ -1310,17 +1310,17 @@ static nsresult pref_InitInitialObjects(
rv = pref_LoadPrefsInDirList(NS_APP_PREFS_DEFAULTS_DIR_LIST);
NS_ENSURE_SUCCESS(rv, rv);
// Set up the correct default for toolkit.telemetry.enabled.
// If this build has MOZ_TELEMETRY_ON_BY_DEFAULT *or* we're on the beta
// channel, telemetry is on by default, otherwise not. This is necessary
// so that beta users who are testing final release builds don't flipflop
// defaults.
- if (Preferences::GetDefaultType(kTelemetryPref) == PREF_INVALID) {
+ if (Preferences::GetDefaultType(kTelemetryPref) == nsIPrefBranch::PREF_INVALID) {
bool prerelease = false;
#ifdef MOZ_TELEMETRY_ON_BY_DEFAULT
prerelease = true;
#else
if (Preferences::GetDefaultCString(kChannelPref).EqualsLiteral("beta")) {
prerelease = true;
}
#endif
--- a/modules/libpref/nsPrefBranch.cpp
+++ b/modules/libpref/nsPrefBranch.cpp
@@ -122,17 +122,31 @@ NS_IMETHODIMP nsPrefBranch::GetRoot(char
*aRoot = ToNewCString(mPrefRoot);
return NS_OK;
}
NS_IMETHODIMP nsPrefBranch::GetPrefType(const char *aPrefName, int32_t *_retval)
{
NS_ENSURE_ARG(aPrefName);
const char *pref = getPrefName(aPrefName);
- *_retval = PREF_GetPrefType(pref);
+ switch (PREF_GetPrefType(pref)) {
+ case PrefType::String:
+ *_retval = PREF_STRING;
+ break;
+ case PrefType::Int:
+ *_retval = PREF_INT;
+ break;
+ case PrefType::Bool:
+ *_retval = PREF_BOOL;
+ break;
+ case PrefType::Invalid:
+ default:
+ *_retval = PREF_INVALID;
+ break;
+ }
return NS_OK;
}
NS_IMETHODIMP nsPrefBranch::GetBoolPref(const char *aPrefName, bool *_retval)
{
NS_ENSURE_ARG(aPrefName);
const char *pref = getPrefName(aPrefName);
return PREF_GetBoolPref(pref, _retval, mIsDefault);
--- a/modules/libpref/prefapi.cpp
+++ b/modules/libpref/prefapi.cpp
@@ -35,17 +35,17 @@
#include "prlink.h"
using namespace mozilla;
static void
clearPrefEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
{
PrefHashEntry *pref = static_cast<PrefHashEntry *>(entry);
- if (pref->flags & PREF_STRING)
+ if (pref->prefFlags.IsTypeString())
{
if (pref->defaultPref.stringVal)
PL_strfree(pref->defaultPref.stringVal);
if (pref->userPref.stringVal)
PL_strfree(pref->userPref.stringVal);
}
// don't need to free this as it's allocated in memory owned by
// gPrefNameArena
@@ -112,23 +112,17 @@ static char *ArenaStrDup(const char* str
PL_ARENA_ALLOCATE(mem, aArena, len+1);
if (mem)
memcpy(mem, str, len+1);
return static_cast<char*>(mem);
}
/*---------------------------------------------------------------------------*/
-#define PREF_IS_LOCKED(pref) ((pref)->flags & PREF_LOCKED)
-#define PREF_HAS_DEFAULT_VALUE(pref) ((pref)->flags & PREF_HAS_DEFAULT)
-#define PREF_HAS_USER_VALUE(pref) ((pref)->flags & PREF_USERSET)
-#define PREF_TYPE(pref) (PrefType)((pref)->flags & PREF_VALUETYPE_MASK)
-
static bool pref_ValueChanged(PrefValue oldValue, PrefValue newValue, PrefType type);
-
/* -- Privates */
struct CallbackNode {
char* domain;
// If someone attempts to remove the node from the callback list while
// pref_DoCallback is running, |func| is set to nullptr. Such nodes will
// be removed at the end of pref_DoCallback.
PrefChangedFunc func;
void* data;
@@ -244,35 +238,35 @@ PREF_SetCharPref(const char *pref_name,
{
if ((uint32_t)strlen(value) > MAX_PREF_LENGTH) {
return NS_ERROR_ILLEGAL_VALUE;
}
PrefValue pref;
pref.stringVal = (char*)value;
- return pref_HashPref(pref_name, pref, PREF_STRING, set_default ? kPrefSetDefault : 0);
+ return pref_HashPref(pref_name, pref, PrefType::String, set_default ? kPrefSetDefault : 0);
}
nsresult
PREF_SetIntPref(const char *pref_name, int32_t value, bool set_default)
{
PrefValue pref;
pref.intVal = value;
- return pref_HashPref(pref_name, pref, PREF_INT, set_default ? kPrefSetDefault : 0);
+ return pref_HashPref(pref_name, pref, PrefType::Int, set_default ? kPrefSetDefault : 0);
}
nsresult
PREF_SetBoolPref(const char *pref_name, bool value, bool set_default)
{
PrefValue pref;
pref.boolVal = value;
- return pref_HashPref(pref_name, pref, PREF_BOOL, set_default ? kPrefSetDefault : 0);
+ return pref_HashPref(pref_name, pref, PrefType::Bool, set_default ? kPrefSetDefault : 0);
}
enum WhichValue { DEFAULT_VALUE, USER_VALUE };
static nsresult
SetPrefValue(const char* aPrefName, const dom::PrefValue& aValue,
WhichValue aWhich)
{
bool setDefault = (aWhich == DEFAULT_VALUE);
@@ -330,38 +324,38 @@ pref_savePrefs(PLDHashTable* aTable)
nsAutoCString prefValue;
nsAutoCString prefPrefix;
prefPrefix.AssignLiteral("user_pref(\"");
// where we're getting our pref from
PrefValue* sourcePref;
- if (PREF_HAS_USER_VALUE(pref) &&
+ if (pref->prefFlags.HasUserValue() &&
(pref_ValueChanged(pref->defaultPref,
pref->userPref,
- (PrefType) PREF_TYPE(pref)) ||
- !(pref->flags & PREF_HAS_DEFAULT) ||
- pref->flags & PREF_STICKY_DEFAULT)) {
+ pref->prefFlags.GetPrefType()) ||
+ !(pref->prefFlags.HasDefault()) ||
+ pref->prefFlags.HasStickyDefault())) {
sourcePref = &pref->userPref;
} else {
// do not save default prefs that haven't changed
continue;
}
// strings are in quotes!
- if (pref->flags & PREF_STRING) {
+ if (pref->prefFlags.IsTypeString()) {
prefValue = '\"';
str_escape(sourcePref->stringVal, prefValue);
prefValue += '\"';
- } else if (pref->flags & PREF_INT) {
+ } else if (pref->prefFlags.IsTypeInt()) {
prefValue.AppendInt(sourcePref->intVal);
- } else if (pref->flags & PREF_BOOL) {
+ } else if (pref->prefFlags.IsTypeBool()) {
prefValue = (sourcePref->boolVal) ? "true" : "false";
}
nsAutoCString prefName;
str_escape(pref->key, prefName);
savedPrefs[j++] = ToNewCString(prefPrefix +
prefName +
@@ -384,41 +378,41 @@ GetPrefValueFromEntry(PrefHashEntry *aHa
aPref->userValue() = dom::PrefValue();
settingValue = &aPref->userValue().get_PrefValue();
} else {
value = &aHashEntry->defaultPref;
aPref->defaultValue() = dom::PrefValue();
settingValue = &aPref->defaultValue().get_PrefValue();
}
- switch (aHashEntry->flags & PREF_VALUETYPE_MASK) {
- case PREF_STRING:
+ switch (aHashEntry->prefFlags.GetPrefType()) {
+ case PrefType::String:
*settingValue = nsDependentCString(value->stringVal);
return;
- case PREF_INT:
+ case PrefType::Int:
*settingValue = value->intVal;
return;
- case PREF_BOOL:
+ case PrefType::Bool:
*settingValue = !!value->boolVal;
return;
default:
MOZ_CRASH();
}
}
void
pref_GetPrefFromEntry(PrefHashEntry *aHashEntry, dom::PrefSetting* aPref)
{
aPref->name() = aHashEntry->key;
- if (PREF_HAS_DEFAULT_VALUE(aHashEntry)) {
+ if (aHashEntry->prefFlags.HasDefault()) {
GetPrefValueFromEntry(aHashEntry, aPref, DEFAULT_VALUE);
} else {
aPref->defaultValue() = null_t();
}
- if (PREF_HAS_USER_VALUE(aHashEntry)) {
+ if (aHashEntry->prefFlags.HasUserValue()) {
GetPrefValueFromEntry(aHashEntry, aPref, USER_VALUE);
} else {
aPref->userValue() = null_t();
}
MOZ_ASSERT(aPref->defaultValue().type() == dom::MaybePrefValue::Tnull_t ||
aPref->userValue().type() == dom::MaybePrefValue::Tnull_t ||
(aPref->defaultValue().get_PrefValue().type() ==
@@ -446,92 +440,84 @@ pref_CompareStrings(const void *v1, cons
}
bool PREF_HasUserPref(const char *pref_name)
{
if (!gHashTable)
return false;
PrefHashEntry *pref = pref_HashTableLookup(pref_name);
- if (!pref) return false;
-
- /* convert PREF_HAS_USER_VALUE to bool */
- return (PREF_HAS_USER_VALUE(pref) != 0);
-
+ return pref && pref->prefFlags.HasUserValue();
}
nsresult
PREF_CopyCharPref(const char *pref_name, char ** return_buffer, bool get_default)
{
if (!gHashTable)
return NS_ERROR_NOT_INITIALIZED;
nsresult rv = NS_ERROR_UNEXPECTED;
char* stringVal;
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
- if (pref && (pref->flags & PREF_STRING))
- {
- if (get_default || PREF_IS_LOCKED(pref) || !PREF_HAS_USER_VALUE(pref))
+ if (pref && (pref->prefFlags.IsTypeString())) {
+ if (get_default || pref->prefFlags.IsLocked() || !pref->prefFlags.HasUserValue()) {
stringVal = pref->defaultPref.stringVal;
- else
+ } else {
stringVal = pref->userPref.stringVal;
+ }
if (stringVal) {
*return_buffer = NS_strdup(stringVal);
rv = NS_OK;
}
}
return rv;
}
nsresult PREF_GetIntPref(const char *pref_name,int32_t * return_int, bool get_default)
{
if (!gHashTable)
return NS_ERROR_NOT_INITIALIZED;
nsresult rv = NS_ERROR_UNEXPECTED;
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
- if (pref && (pref->flags & PREF_INT))
- {
- if (get_default || PREF_IS_LOCKED(pref) || !PREF_HAS_USER_VALUE(pref))
- {
+ if (pref && (pref->prefFlags.IsTypeInt())) {
+ if (get_default || pref->prefFlags.IsLocked() || !pref->prefFlags.HasUserValue()) {
int32_t tempInt = pref->defaultPref.intVal;
/* check to see if we even had a default */
- if (!(pref->flags & PREF_HAS_DEFAULT))
+ if (!pref->prefFlags.HasDefault()) {
return NS_ERROR_UNEXPECTED;
+ }
*return_int = tempInt;
+ } else {
+ *return_int = pref->userPref.intVal;
}
- else
- *return_int = pref->userPref.intVal;
rv = NS_OK;
}
return rv;
}
nsresult PREF_GetBoolPref(const char *pref_name, bool * return_value, bool get_default)
{
if (!gHashTable)
return NS_ERROR_NOT_INITIALIZED;
nsresult rv = NS_ERROR_UNEXPECTED;
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
//NS_ASSERTION(pref, pref_name);
- if (pref && (pref->flags & PREF_BOOL))
- {
- if (get_default || PREF_IS_LOCKED(pref) || !PREF_HAS_USER_VALUE(pref))
- {
+ if (pref && (pref->prefFlags.IsTypeBool())) {
+ if (get_default || pref->prefFlags.IsLocked() || !pref->prefFlags.HasUserValue()) {
bool tempBool = pref->defaultPref.boolVal;
/* check to see if we even had a default */
- if (pref->flags & PREF_HAS_DEFAULT) {
+ if (pref->prefFlags.HasDefault()) {
*return_value = tempBool;
rv = NS_OK;
}
- }
- else {
+ } else {
*return_value = pref->userPref.boolVal;
rv = NS_OK;
}
}
return rv;
}
nsresult
@@ -579,21 +565,20 @@ PREF_DeleteBranch(const char *branch_nam
nsresult
PREF_ClearUserPref(const char *pref_name)
{
if (!gHashTable)
return NS_ERROR_NOT_INITIALIZED;
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
- if (pref && PREF_HAS_USER_VALUE(pref))
- {
- pref->flags &= ~PREF_USERSET;
+ if (pref && pref->prefFlags.HasUserValue()) {
+ pref->prefFlags.SetHasUserValue(false);
- if (!(pref->flags & PREF_HAS_DEFAULT)) {
+ if (!pref->prefFlags.HasDefault()) {
gHashTable->RemoveEntry(pref);
}
pref_DoCallback(pref_name);
gDirty = true;
}
return NS_OK;
}
@@ -607,21 +592,21 @@ PREF_ClearAllUserPrefs()
if (!gHashTable)
return NS_ERROR_NOT_INITIALIZED;
std::vector<std::string> prefStrings;
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
auto pref = static_cast<PrefHashEntry*>(iter.Get());
- if (PREF_HAS_USER_VALUE(pref)) {
+ if (pref->prefFlags.HasUserValue()) {
prefStrings.push_back(std::string(pref->key));
- pref->flags &= ~PREF_USERSET;
- if (!(pref->flags & PREF_HAS_DEFAULT)) {
+ pref->prefFlags.SetHasUserValue(false);
+ if (!pref->prefFlags.HasDefault()) {
iter.Remove();
}
}
}
for (std::string& prefString : prefStrings) {
pref_DoCallback(prefString.c_str());
}
@@ -635,71 +620,76 @@ nsresult PREF_LockPref(const char *key,
if (!gHashTable)
return NS_ERROR_NOT_INITIALIZED;
PrefHashEntry* pref = pref_HashTableLookup(key);
if (!pref)
return NS_ERROR_UNEXPECTED;
if (lockit) {
- if (!PREF_IS_LOCKED(pref))
- {
- pref->flags |= PREF_LOCKED;
+ if (!pref->prefFlags.IsLocked()) {
+ pref->prefFlags.SetLocked(true);
gIsAnyPrefLocked = true;
pref_DoCallback(key);
}
- }
- else
- {
- if (PREF_IS_LOCKED(pref))
- {
- pref->flags &= ~PREF_LOCKED;
+ } else {
+ if (pref->prefFlags.IsLocked()) {
+ pref->prefFlags.SetLocked(false);
pref_DoCallback(key);
}
}
return NS_OK;
}
/*
* Hash table functions
*/
static bool pref_ValueChanged(PrefValue oldValue, PrefValue newValue, PrefType type)
{
bool changed = true;
- if (type & PREF_STRING)
- {
- if (oldValue.stringVal && newValue.stringVal)
+ switch(type) {
+ case PrefType::String:
+ if (oldValue.stringVal && newValue.stringVal) {
changed = (strcmp(oldValue.stringVal, newValue.stringVal) != 0);
+ }
+ break;
+ case PrefType::Int:
+ changed = oldValue.intVal != newValue.intVal;
+ break;
+ case PrefType::Bool:
+ changed = oldValue.boolVal != newValue.boolVal;
+ break;
+ case PrefType::Invalid:
+ default:
+ changed = false;
+ break;
}
- else if (type & PREF_INT)
- changed = oldValue.intVal != newValue.intVal;
- else if (type & PREF_BOOL)
- changed = oldValue.boolVal != newValue.boolVal;
return changed;
}
/*
* Overwrite the type and value of an existing preference. Caller must
* ensure that they are not changing the type of a preference that has
* a default value.
*/
-static void pref_SetValue(PrefValue* existingValue, uint16_t *existingFlags,
- PrefValue newValue, PrefType newType)
+static PrefTypeFlags pref_SetValue(PrefValue* existingValue, PrefTypeFlags flags,
+ PrefValue newValue, PrefType newType)
{
- if ((*existingFlags & PREF_STRING) && existingValue->stringVal) {
+ if (flags.IsTypeString() && existingValue->stringVal) {
PL_strfree(existingValue->stringVal);
}
- *existingFlags = (*existingFlags & ~PREF_VALUETYPE_MASK) | newType;
- if (newType & PREF_STRING) {
+ flags.SetPrefType(newType);
+ if (flags.IsTypeString()) {
PR_ASSERT(newValue.stringVal);
existingValue->stringVal = newValue.stringVal ? PL_strdup(newValue.stringVal) : nullptr;
}
else {
*existingValue = newValue;
}
+ return flags;
}
PrefHashEntry* pref_HashTableLookup(const char *key)
{
#ifndef MOZ_B2G
MOZ_ASSERT(NS_IsMainThread());
#endif
@@ -718,73 +708,63 @@ nsresult pref_HashPref(const char *key,
auto pref = static_cast<PrefHashEntry*>(gHashTable->Add(key, fallible));
if (!pref)
return NS_ERROR_OUT_OF_MEMORY;
// new entry, better initialize
if (!pref->key) {
// initialize the pref entry
- pref->flags = type;
+ pref->prefFlags.Reset().SetPrefType(type);
pref->key = ArenaStrDup(key, &gPrefNameArena);
memset(&pref->defaultPref, 0, sizeof(pref->defaultPref));
memset(&pref->userPref, 0, sizeof(pref->userPref));
- }
- else if ((pref->flags & PREF_HAS_DEFAULT) && PREF_TYPE(pref) != type)
- {
+ } else if (pref->prefFlags.HasDefault() && !pref->prefFlags.IsPrefType(type)) {
NS_WARNING(nsPrintfCString("Trying to overwrite value of default pref %s with the wrong type!", key).get());
return NS_ERROR_UNEXPECTED;
}
bool valueChanged = false;
- if (flags & kPrefSetDefault)
- {
- if (!PREF_IS_LOCKED(pref))
- { /* ?? change of semantics? */
+ if (flags & kPrefSetDefault) {
+ if (!pref->prefFlags.IsLocked()) {
+ /* ?? change of semantics? */
if (pref_ValueChanged(pref->defaultPref, value, type) ||
- !(pref->flags & PREF_HAS_DEFAULT))
- {
- pref_SetValue(&pref->defaultPref, &pref->flags, value, type);
- pref->flags |= PREF_HAS_DEFAULT;
- if (flags & kPrefStickyDefault)
- pref->flags |= PREF_STICKY_DEFAULT;
- if (!PREF_HAS_USER_VALUE(pref))
+ !pref->prefFlags.HasDefault()) {
+ pref->prefFlags = pref_SetValue(&pref->defaultPref, pref->prefFlags, value, type).SetHasDefault(true);
+ if (flags & kPrefStickyDefault) {
+ pref->prefFlags.SetHasStickyDefault(true);
+ }
+ if (!pref->prefFlags.HasUserValue()) {
valueChanged = true;
+ }
}
// What if we change the default to be the same as the user value?
// Should we clear the user value?
}
- }
- else
- {
+ } else {
/* If new value is same as the default value and it's not a "sticky"
pref, then un-set the user value.
Otherwise, set the user value only if it has changed */
- if ((pref->flags & PREF_HAS_DEFAULT) &&
- !(pref->flags & PREF_STICKY_DEFAULT) &&
+ if ((pref->prefFlags.HasDefault()) &&
+ !(pref->prefFlags.HasStickyDefault()) &&
!pref_ValueChanged(pref->defaultPref, value, type) &&
- !(flags & kPrefForceSet))
- {
- if (PREF_HAS_USER_VALUE(pref))
- {
+ !(flags & kPrefForceSet)) {
+ if (pref->prefFlags.HasUserValue()) {
/* XXX should we free a user-set string value if there is one? */
- pref->flags &= ~PREF_USERSET;
- if (!PREF_IS_LOCKED(pref)) {
+ pref->prefFlags.SetHasUserValue(false);
+ if (!pref->prefFlags.IsLocked()) {
gDirty = true;
valueChanged = true;
}
}
- }
- else if (!PREF_HAS_USER_VALUE(pref) ||
- PREF_TYPE(pref) != type ||
- pref_ValueChanged(pref->userPref, value, type) )
- {
- pref_SetValue(&pref->userPref, &pref->flags, value, type);
- pref->flags |= PREF_USERSET;
- if (!PREF_IS_LOCKED(pref)) {
+ } else if (!pref->prefFlags.HasUserValue() ||
+ !pref->prefFlags.IsPrefType(type) ||
+ pref_ValueChanged(pref->userPref, value, type) ) {
+ pref->prefFlags = pref_SetValue(&pref->userPref, pref->prefFlags, value, type).SetHasUserValue(true);
+ if (!pref->prefFlags.IsLocked()) {
gDirty = true;
valueChanged = true;
}
}
}
if (valueChanged) {
return pref_DoCallback(key);
@@ -803,39 +783,34 @@ pref_SizeOfPrivateData(MallocSizeOf aMal
return n;
}
PrefType
PREF_GetPrefType(const char *pref_name)
{
if (gHashTable) {
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
- if (pref)
- {
- if (pref->flags & PREF_STRING)
- return PREF_STRING;
- else if (pref->flags & PREF_INT)
- return PREF_INT;
- else if (pref->flags & PREF_BOOL)
- return PREF_BOOL;
+ if (pref) {
+ return pref->prefFlags.GetPrefType();
}
}
- return PREF_INVALID;
+ return PrefType::Invalid;
}
/* -- */
bool
PREF_PrefIsLocked(const char *pref_name)
{
bool result = false;
if (gIsAnyPrefLocked && gHashTable) {
PrefHashEntry* pref = pref_HashTableLookup(pref_name);
- if (pref && PREF_IS_LOCKED(pref))
+ if (pref && pref->prefFlags.IsLocked()) {
result = true;
+ }
}
return result;
}
/* Adds a node to the beginning of the callback list. */
void
PREF_RegisterCallback(const char *pref_node,
@@ -968,15 +943,21 @@ static nsresult pref_DoCallback(const ch
}
void PREF_ReaderCallback(void *closure,
const char *pref,
PrefValue value,
PrefType type,
bool isDefault,
bool isStickyDefault)
+
{
- uint32_t flags = isDefault ? kPrefSetDefault : kPrefForceSet;
- if (isDefault && isStickyDefault) {
- flags |= kPrefStickyDefault;
+ uint32_t flags = 0;
+ if (isDefault) {
+ flags |= kPrefSetDefault;
+ if (isStickyDefault) {
+ flags |= kPrefStickyDefault;
+ }
+ } else {
+ flags |= kPrefForceSet;
}
pref_HashPref(pref, value, type, flags);
}
--- a/modules/libpref/prefapi.h
+++ b/modules/libpref/prefapi.h
@@ -23,58 +23,115 @@ static const uint32_t MAX_ADVISABLE_PREF
typedef union
{
char* stringVal;
int32_t intVal;
bool boolVal;
} PrefValue;
-struct PrefHashEntry : PLDHashEntryHdr
-{
- uint16_t flags; // This field goes first to minimize struct size on 64-bit.
- const char *key;
- PrefValue defaultPref;
- PrefValue userPref;
-};
-
/*
// <font color=blue>
// The Init function initializes the preference context and creates
// the preference hashtable.
// </font>
*/
void PREF_Init();
/*
-// Cleanup should be called at program exit to free the
+// Cleanup should be called at program exit to free the
// list of registered callbacks.
*/
void PREF_Cleanup();
void PREF_CleanupPrefs();
/*
// <font color=blue>
-// Preference flags, including the native type of the preference
+// Preference flags, including the native type of the preference. Changing any of these
+// values will require modifying the code inside of PrefTypeFlags class.
// </font>
*/
-typedef enum { PREF_INVALID = 0,
- PREF_LOCKED = 1, PREF_USERSET = 2, PREF_CONFIG = 4, PREF_REMOTE = 8,
- PREF_LILOCAL = 16, PREF_STRING = 32, PREF_INT = 64, PREF_BOOL = 128,
- PREF_HAS_DEFAULT = 256,
- // pref is default pref with "sticky" semantics
- PREF_STICKY_DEFAULT = 512,
- PREF_VALUETYPE_MASK = (PREF_STRING | PREF_INT | PREF_BOOL)
- } PrefType;
+enum class PrefType {
+ Invalid = 0,
+ String = 1,
+ Int = 2,
+ Bool = 3,
+};
+
+// Keep the type of the preference, as well as the flags guiding its behaviour.
+class PrefTypeFlags
+{
+public:
+ PrefTypeFlags() : mValue(AsInt(PrefType::Invalid)) {}
+ PrefTypeFlags(PrefType aType) : mValue(AsInt(aType)) {}
+ PrefTypeFlags& Reset() { mValue = AsInt(PrefType::Invalid); return *this; }
+
+ bool IsTypeValid() const { return !IsPrefType(PrefType::Invalid); }
+ bool IsTypeString() const { return IsPrefType(PrefType::String); }
+ bool IsTypeInt() const { return IsPrefType(PrefType::Int); }
+ bool IsTypeBool() const { return IsPrefType(PrefType::Bool); }
+ bool IsPrefType(PrefType type) const { return GetPrefType() == type; }
+
+ PrefTypeFlags& SetPrefType(PrefType aType) {
+ mValue = mValue - AsInt(GetPrefType()) + AsInt(aType);
+ return *this;
+ }
+ PrefType GetPrefType() const {
+ return (PrefType)(mValue & (AsInt(PrefType::String) |
+ AsInt(PrefType::Int) |
+ AsInt(PrefType::Bool)));
+ }
+
+ bool HasDefault() const { return mValue & PREF_FLAG_HAS_DEFAULT; }
+ PrefTypeFlags& SetHasDefault(bool aSetOrUnset) { return SetFlag(PREF_FLAG_HAS_DEFAULT, aSetOrUnset); }
+
+ bool HasStickyDefault() const { return mValue & PREF_FLAG_STICKY_DEFAULT; }
+ PrefTypeFlags& SetHasStickyDefault(bool aSetOrUnset) { return SetFlag(PREF_FLAG_STICKY_DEFAULT, aSetOrUnset); }
+
+ bool IsLocked() const { return mValue & PREF_FLAG_LOCKED; }
+ PrefTypeFlags& SetLocked(bool aSetOrUnset) { return SetFlag(PREF_FLAG_LOCKED, aSetOrUnset); }
+
+ bool HasUserValue() const { return mValue & PREF_FLAG_USERSET; }
+ PrefTypeFlags& SetHasUserValue(bool aSetOrUnset) { return SetFlag(PREF_FLAG_USERSET, aSetOrUnset); }
+
+private:
+ static uint16_t AsInt(PrefType aType) { return (uint16_t)aType; }
+
+ PrefTypeFlags& SetFlag(uint16_t aFlag, bool aSetOrUnset) {
+ mValue = aSetOrUnset ? mValue | aFlag : mValue & ~aFlag;
+ return *this;
+ }
+
+ // Pack both the value of type (PrefType) and flags into the same int. This is why
+ // the flag enum starts at 4, as PrefType occupies the bottom two bits.
+ enum {
+ PREF_FLAG_LOCKED = 4,
+ PREF_FLAG_USERSET = 8,
+ PREF_FLAG_CONFIG = 16,
+ PREF_FLAG_REMOTE = 32,
+ PREF_FLAG_LILOCAL = 64,
+ PREF_FLAG_HAS_DEFAULT = 128,
+ PREF_FLAG_STICKY_DEFAULT = 256,
+ };
+ uint16_t mValue;
+};
+
+struct PrefHashEntry : PLDHashEntryHdr
+{
+ PrefTypeFlags prefFlags; // This field goes first to minimize struct size on 64-bit.
+ const char *key;
+ PrefValue defaultPref;
+ PrefValue userPref;
+};
/*
// <font color=blue>
// Set the various types of preferences. These functions take a dotted
-// notation of the preference name (e.g. "browser.startup.homepage").
+// notation of the preference name (e.g. "browser.startup.homepage").
// Note that this will cause the preference to be saved to the file if
// it is different from the default. In other words, these are used
// to set the _user_ preferences.
//
// If set_default is set to true however, it sets the default value.
// This will only affect the program behavior if the user does not have a value
// saved over it for the particular preference. In addition, these will never
// be saved out to disk.
@@ -98,18 +155,18 @@ bool PREF_HasUserPref(const char* pr
// error value. At the moment, this is simply an int but it may
// be converted to an enum once the global error strategy is worked out.
//
// They will perform conversion if the type doesn't match what was requested.
// (if it is reasonably possible)
// </font>
*/
nsresult PREF_GetIntPref(const char *pref,
- int32_t * return_int, bool get_default);
-nsresult PREF_GetBoolPref(const char *pref, bool * return_val, bool get_default);
+ int32_t * return_int, bool get_default);
+nsresult PREF_GetBoolPref(const char *pref, bool * return_val, bool get_default);
/*
// <font color=blue>
// These functions are similar to the above "Get" version with the significant
// difference that the preference module will alloc the memory (e.g. XP_STRDUP) and
// the caller will need to be responsible for freeing it...
// </font>
*/
nsresult PREF_CopyCharPref(const char *pref, char ** return_buf, bool get_default);
@@ -168,20 +225,20 @@ typedef void (*PrefChangedFunc) (const c
/*
// <font color=blue>
// Register a callback. This takes a node in the preference tree and will
// call the callback function if anything below that node is modified.
// Unregister returns PREF_NOERROR if a callback was found that
// matched all the parameters; otherwise it returns PREF_ERROR.
// </font>
*/
-void PREF_RegisterCallback( const char* domain,
- PrefChangedFunc callback, void* instance_data );
-nsresult PREF_UnregisterCallback( const char* domain,
- PrefChangedFunc callback, void* instance_data );
+void PREF_RegisterCallback(const char* domain,
+ PrefChangedFunc callback, void* instance_data );
+nsresult PREF_UnregisterCallback(const char* domain,
+ PrefChangedFunc callback, void* instance_data );
/*
* Used by nsPrefService as the callback function of the 'pref' parser
*/
void PREF_ReaderCallback( void *closure,
const char *pref,
PrefValue value,
PrefType type,
--- a/modules/libpref/prefread.cpp
+++ b/modules/libpref/prefread.cpp
@@ -109,27 +109,27 @@ pref_GrowBuf(PrefParseState *ps)
* @return false to indicate a fatal error.
*/
static bool
pref_DoCallback(PrefParseState *ps)
{
PrefValue value;
switch (ps->vtype) {
- case PREF_STRING:
+ case PrefType::String:
value.stringVal = ps->vb;
break;
- case PREF_INT:
+ case PrefType::Int:
if ((ps->vb[0] == '-' || ps->vb[0] == '+') && ps->vb[1] == '\0') {
NS_WARNING("malformed integer value");
return false;
}
value.intVal = atoi(ps->vb);
break;
- case PREF_BOOL:
+ case PrefType::Bool:
value.boolVal = (ps->vb == kTrue);
break;
default:
break;
}
(*ps->reader)(ps->closure, ps->lb, value, ps->vtype, ps->fdefault,
ps->fstickydefault);
return true;
@@ -149,17 +149,17 @@ PREF_FinalizeParseState(PrefParseState *
if (ps->lb)
free(ps->lb);
}
/**
* Pseudo-BNF
* ----------
* function = LJUNK function-name JUNK function-args
- * function-name = "user_pref" | "pref"
+ * function-name = "user_pref" | "pref" | "sticky_pref"
* function-args = "(" JUNK pref-name JUNK "," JUNK pref-value JUNK ")" JUNK ";"
* pref-name = quoted-string
* pref-value = quoted-string | "true" | "false" | integer-value
* JUNK = *(WS | comment-block | comment-line)
* LJUNK = *(WS | comment-block | comment-line | bcomment-line)
* WS = SP | HT | LF | VT | FF | CR
* SP = <US-ASCII SP, space (32)>
* HT = <US-ASCII HT, horizontal-tab (9)>
@@ -183,32 +183,37 @@ PREF_ParseBuf(PrefParseState *ps, const
for (end = buf + bufLen; buf != end; ++buf) {
c = *buf;
switch (state) {
/* initial state */
case PREF_PARSE_INIT:
if (ps->lbcur != ps->lb) { /* reset state */
ps->lbcur = ps->lb;
ps->vb = nullptr;
- ps->vtype = PREF_INVALID;
+ ps->vtype = PrefType::Invalid;
ps->fdefault = false;
ps->fstickydefault = false;
}
switch (c) {
case '/': /* begin comment block or line? */
state = PREF_PARSE_COMMENT_MAYBE_START;
break;
case '#': /* accept shell style comments */
state = PREF_PARSE_UNTIL_EOL;
break;
case 'u': /* indicating user_pref */
+ case 's': /* indicating sticky_pref */
case 'p': /* indicating pref */
- case 's': /* indicating sticky_pref */
- ps->smatch = (c == 'u' ? kUserPref :
- (c == 's' ? kPrefSticky : kPref));
+ if (c == 'u') {
+ ps->smatch = kUserPref;
+ } else if (c == 's') {
+ ps->smatch = kPrefSticky;
+ } else {
+ ps->smatch = kPref;
+ }
ps->sindex = 1;
ps->nextstate = PREF_PARSE_UNTIL_OPEN_PAREN;
state = PREF_PARSE_MATCH_STRING;
break;
/* else skip char */
}
break;
@@ -243,16 +248,18 @@ PREF_ParseBuf(PrefParseState *ps, const
else
*ps->lbcur++ = c;
break;
/* name parsing */
case PREF_PARSE_UNTIL_NAME:
if (c == '\"' || c == '\'') {
ps->fdefault = (ps->smatch == kPref || ps->smatch == kPrefSticky);
+ ps->fdefault = (ps->smatch == kPref ||
+ ps->smatch == kPrefSticky);
ps->fstickydefault = (ps->smatch == kPrefSticky);
ps->quotechar = c;
ps->nextstate = PREF_PARSE_UNTIL_COMMA; /* return here when done */
state = PREF_PARSE_QUOTED_STRING;
}
else if (c == '/') { /* allow embedded comment */
ps->nextstate = state; /* return here when done with comment */
state = PREF_PARSE_COMMENT_MAYBE_START;
@@ -279,31 +286,31 @@ PREF_ParseBuf(PrefParseState *ps, const
}
break;
/* value parsing */
case PREF_PARSE_UNTIL_VALUE:
/* the pref value type is unknown. so, we scan for the first
* character of the value, and determine the type from that. */
if (c == '\"' || c == '\'') {
- ps->vtype = PREF_STRING;
+ ps->vtype = PrefType::String;
ps->quotechar = c;
ps->nextstate = PREF_PARSE_UNTIL_CLOSE_PAREN;
state = PREF_PARSE_QUOTED_STRING;
}
else if (c == 't' || c == 'f') {
ps->vb = (char *) (c == 't' ? kTrue : kFalse);
- ps->vtype = PREF_BOOL;
+ ps->vtype = PrefType::Bool;
ps->smatch = ps->vb;
ps->sindex = 1;
ps->nextstate = PREF_PARSE_UNTIL_CLOSE_PAREN;
state = PREF_PARSE_MATCH_STRING;
}
else if (isdigit(c) || (c == '-') || (c == '+')) {
- ps->vtype = PREF_INT;
+ ps->vtype = PrefType::Int;
/* write c to line buffer... */
if (ps->lbcur == ps->lbend && !pref_GrowBuf(ps))
return false; /* out of memory */
*ps->lbcur++ = c;
state = PREF_PARSE_INT_VALUE;
}
else if (c == '/') { /* allow embedded comment */
ps->nextstate = state; /* return here when done with comment */
@@ -506,23 +513,22 @@ PREF_ParseBuf(PrefParseState *ps, const
}
else if (!isspace(c)) {
NS_WARNING("malformed pref file");
return false;
}
break;
case PREF_PARSE_UNTIL_CLOSE_PAREN:
/* tolerate only whitespace and embedded comments */
- if (c == ')')
+ if (c == ')') {
state = PREF_PARSE_UNTIL_SEMICOLON;
- else if (c == '/') {
+ } else if (c == '/') {
ps->nextstate = state; /* return here when done with comment */
state = PREF_PARSE_COMMENT_MAYBE_START;
- }
- else if (!isspace(c)) {
+ } else if (!isspace(c)) {
NS_WARNING("malformed pref file");
return false;
}
break;
/* function terminator ';' parsing */
case PREF_PARSE_UNTIL_SEMICOLON:
/* tolerate only whitespace and embedded comments */
--- a/modules/libpref/prefread.h
+++ b/modules/libpref/prefread.h
@@ -49,17 +49,17 @@ typedef struct PrefParseState {
int esclen; /* length in esctmp */
char esctmp[6]; /* raw escape to put back if err */
char quotechar; /* char delimiter for quotations */
char *lb; /* line buffer (only allocation) */
char *lbcur; /* line buffer cursor */
char *lbend; /* line buffer end */
char *vb; /* value buffer (ptr into lb) */
PrefType vtype; /* PREF_STRING,INT,BOOL */
- bool fdefault; /* true if (default) pref */
+ bool fdefault; /* true if (default) pref */
bool fstickydefault; /* true if (sticky) pref */
} PrefParseState;
/**
* PREF_InitParseState
*
* Called to initialize a PrefParseState instance.
*