# Prefsfile module

## Introduction

The Prefsfile module provides APIs for reading and writing the Opera configuration file formats directly, and support for language files. This is used mainly by the Preferences module, but also several other parts of the code.

Current information about the Prefsfile module and its releases is available on the developer wiki.

## Interface overview and API documentation

### API documentation

The API documentation is extracted automatically by Doxygen.

### Overview

The PrefsFile is the general-purpose configuration storage API used by the Preferences module (and others) to store configuration options on disk. Platforms that want to re-implement the reading of preferences (for instance using system APIs) can implement new file formats inside the PrefsFile framework by implementing the PrefsAccessor interface.

The PrefsFile class implements support for cascading preferences using several preferences files.

## Use-cases

### Reading auxiliary `INI` files/file sets

To read an auxiliary preferences file (normally in `INI` or `LNG` format), an instance of PrefsFile class is constructed and initialised. When creating the object, the type of the file must be supplied. For core code, the special constant `PREFS_STD` should always be used when it needs to access files, as this will always select the platform default type (configurable through the tweak system).

After performing a `PrefsFile::LoadAllL()`, the instance of PrefsFile permits direct access to the settings stored in the `INI` (or `LNG`) file using the various `Read*()` methods, and to write (not `LNG`) using the `Write*` methods. To store the modified file to disk, `PrefsFile::CommitL()` is called.

Please note that as long as the PrefsFile object is not flushed, either by `PrefsFile::CommitL()` or a direct call to `PrefsFile::Flush()`, any changes done to the file on-disk will be ignored.

For more details on how to use preferences files and an explanation of how the design is supposed to work, please see the background information.

### Changing file formats

The PrefsFile class is not tied to using a specific file format for storing its preferences, all reading and writing to the actual files is performed by the PrefsAccessor interface. The requirement when changing both the file format and storage method is that data can be stored keyed to a section and key, and that the data types that can be written are at least strings and numbers (in PrefsAccessor and associated classes, all preferences are written as strings).

## Supported standards

The file format used by `IniAccessor` is based on the standard Windows `INI` file format, with some extensions. The language file format is an extended `INI` file format with embedded encoding information, and is used by the locale code.

## Implementation and design

See also the API documentation.

### Memory management

#### Heap usage

Footprint usage can be decreased by disabling hashing code. Memory usage will decrease as well, as the data associated with the hash tables is no longer used. Memory and footprint usage will be decreased further when enabling case sensitive preference key names.

These settings also affect performance, and can be manually tuned, see "Performance" below for more details.

#### Stack usage

There are no recursive calls.

#### Static memory usage

There is one global `PrefsHashFunctions` pointer, which is live for the entire lifetime of Opera (under certain circumstances it might even be initialised before the call `InitL`).

There is also a temporary buffer used for case conversion and environment variable expansion. This buffer is of 4096 `uni_char`s if expansion of environment variables is enabled, or of 2048 `uni_char`s if case insensitive name look-up are used. If neither expansion nor case insensitivity is enabled, this buffer is not enabled.

#### OOM policies

The vast majority of functions that require memory to be allocated is using the `TRAP`/`LEAVE` convention.

### Performance

#### Caching

To make reading and writing from preference files faster, the files are cached inside the PrefsFile class.

#### Hashing

Furthermore, PrefsFile uses hash tables to make lookup into the parsed files faster. For small machines, this should probably be disabled, and the linear search used. The coded needs to retain the linear ordering of the preferences anyway.

For most devices with large ini files it is probably a good idea to enabled `FEATURE_PREFS_ENTRIES_HASH` (hashing of keys in a section) and `FEATURE_PREFS_SECTION_HASH` (hashing of sections), if the increased memory usage can be afforded. Hashing of sections is not normally necessary unless ini files with a large number of sections is used (e.g skinning files).

Language files are read sequentially by the LanguageManager implementation, so no performance penalty is induced for language files if hashing is removed, even for large language files.

#### Case sensitivity

Normally the section and key names in the preference files are case insensitive (in a normal Windows `INI` file, case is not considered), to make it easier to edit these files by hand. If you enable `TWEAK_PF_CASE_SENSITIVE`, the strings are made case sensitive, speeding up the related string comparisons. For devices where the user or other software will not be touching the preference files this should probably be enabled. This is especially useful when hashing is disabled.

## References

- Preferences module
- Locale module