# MemoryMap

MemoryMap Represents the contents of a memory layout, with main focus into (possibly sparse) blocks of data.
A `MemoryMap` acts as a subclass of Map. In every entry of it, the key is the starting address of a data block (an integer number), and the value is the `Uint8Array` with the data for that block.
The main rationale for this is that a .hex file can contain a single block of contiguous data starting at memory address 0 (and it's the common case for simple .hex files), but complex files with several non-contiguous data blocks are also possible, thus the need for a data structure on top of the `Uint8Array`s.
In order to parse `.hex` files, use the `MemoryMap.fromHex` static factory method. In order to write `.hex` files, create a new `MemoryMap` and call its `MemoryMap.asHexString` method.

## Constructor

#### new MemoryMap(blocks)

Source:
  - intel-hex.js, line 79

##### Parameters:

Name | Type | Description
--- | --- | ---
`blocks` | `Iterable` | The initial value for the memory blocks inside this `MemoryMap`. All keys must be numeric, and all values must be instances of `Uint8Array`. Optionally it can also be a plain `Object` with only numeric keys.

##### Example

    import MemoryMap from 'nrf-intel-hex';

    let memMap1 = new MemoryMap();
    let memMap2 = new MemoryMap([[0, new Uint8Array(1,2,3,4)]]);
    let memMap3 = new MemoryMap({0: new Uint8Array(1,2,3,4)});
    let memMap4 = new MemoryMap({0xCF0: new Uint8Array(1,2,3,4)});

### Extends

- Map

### Methods

#### (static) flattenOverlaps(overlaps) → {MemoryMap}

Given the output of the `overlapMemoryMaps` (a `Map` of address to an `Array` of `(id, Uint8Array)` tuples), returns a `MemoryMap`. This discards the IDs in the process.
The output `Map` contains as many entries as the input one (using the same addresses as keys), but the value for each entry will be the `Uint8Array` of the last tuple for each address in the input data.
The scenario is wanting to join together several parsed .hex files, not worrying about their overlaps.

Source:
  - intel-hex.js, line 472

##### Parameters:

Name | Type | Description
--- | --- | ---
`overlaps` | `Map.Array.<mixed, Uint8Array>` | The (possibly overlapping) input memory blocks

##### Returns:

Type:
  `MemoryMap`

The flattened memory blocks

#### (static) fromHex(hexText, maxBlockSizeopt) → {MemoryMap}

Parses a string containing data formatted in "Intel HEX" format, and returns an instance of `MemoryMap`.
The insertion order of keys in the `MemoryMap` is guaranteed to be strictly ascending. In other words, when iterating through the `MemoryMap`, the addresses will be ordered in ascending order.
The parser has an opinionated behaviour, and will throw a descriptive error if it encounters some malformed input. Check the project's README file for details.
If `maxBlockSize` is given, any contiguous data block larger than that will be split in several blocks.

Source:
  - intel-hex.js, line 166

##### Parameters:

Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`hexText` | `String` |  |  | The contents of a .hex file.
`maxBlockSize` | `Number` | <optional> | Infinity | Maximum size of the returned `Uint8Array`s.

##### Returns:

Type:
  `MemoryMap`

##### Example

    import MemoryMap from 'nrf-intel-hex';

    let intelHexString =
        ":100000000102030405060708090A0B0C0D0E0F1068\n" +
        ":00000001FF";

    let memMap = MemoryMap.fromHex(intelHexString);

    for (let [address, dataBlock] of memMap) {
        console.log('Data block at ', address, ', bytes: ', dataBlock);
    }

#### (static) fromPaddedUint8Array(bytes, padByteopt, minPadLengthopt) → {MemoryMap}

Given one `Uint8Array`, looks through its contents and returns a new `MemoryMap`, stripping away those regions where there are only padding bytes.
The start of the input `Uint8Array` is assumed to be offset zero for the output.
The use case here is dumping memory from a working device and try to see the "interesting" memory regions it has. This assumes that there is a constant, predefined padding byte value being used in the "non-interesting" regions. In other words: this will work as long as the dump comes from a flash memory which has been previously erased (thus `0xFF`s for padding), or from a previously blanked HDD (thus `0x00`s for padding).
This method uses `subarray` on the input data, and thus does not allocate memory for the `Uint8Array`s.

Source:
  - intel-hex.js, line 767

##### Parameters:

Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`bytes` | `Uint8Array` |  |  | The input data
`padByte` | `Number` | <optional> | 0xFF | The value of the byte assumed to be used as padding
`minPadLength` | `Number` | <optional> | 64 | The minimum number of consecutive pad bytes to be considered actual padding

##### Returns:

Type:
  `MemoryMap`

#### (static) overlapMemoryMaps(memoryMaps) → {Map.Array.<mixed, Uint8Array>}

Given a `Map` of `MemoryMap`s, indexed by a alphanumeric ID, returns a `Map` of address to tuples (`Arrays`s of length 2) of the form `(id, Uint8Array)`s.
The scenario for using this is having several `MemoryMap`s, from several calls to hexToArrays, each having a different identifier. This function locates where those memory block sets overlap, and returns a `Map` containing addresses as keys, and arrays as values. Each array will contain 1 or more `(id, Uint8Array)` tuples: the identifier of the memory block set that has data in that region, and the data itself. When memory block sets overlap, there will be more than one tuple.
The `Uint8Array`s in the output are subarrays of the input data; new memory is not allocated for them.
The insertion order of keys in the output `Map` is guaranteed to be strictly ascending. In other words, when iterating through the `Map`, the addresses will be ordered in ascending order.
When two blocks overlap, the corresponding array of tuples will have the tuples ordered in the insertion order of the input `Map` of block sets.

Source:
  - intel-hex.js, line 407

##### Parameters:

Name | Type | Description
--- | --- | ---
`memoryMaps` | `Map.MemoryMap` | The input memory block sets

##### Returns:

Type:
  `Map.Array.<mixed, Uint8Array>`

The map of possibly overlapping memory blocks

##### Example

    import MemoryMap from 'nrf-intel-hex';

    let memMap1 = MemoryMap.fromHex( hexdata1 );
    let memMap2 = MemoryMap.fromHex( hexdata2 );
    let memMap3 = MemoryMap.fromHex( hexdata3 );

    let maps = new Map([
     ['file A', blocks1],
     ['file B', blocks2],
     ['file C', blocks3]
    ]);

    let overlappings = MemoryMap.overlapMemoryMaps(maps);

    for (let [address, tuples] of overlappings) {
        // if 'tuples' has length > 1, there is an overlap starting at 'address'

        for (let [address, tuples] of overlappings) {
            let [id, bytes] = tuple;
            // 'id' in this example is either 'file A', 'file B' or 'file C'
        }
    }

#### asHexString(lineSizeopt) → {String}

Returns a `String` of text representing a .hex file.
The writer has an opinionated behaviour. Check the project's README file for details.

Source:
  - intel-hex.js, line 599

##### Parameters:

Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`lineSize` | `Number` | <optional> | 16 | Maximum number of bytes to be encoded in each data record. Must have a value between 1 and 255, as per the specification.

##### Returns:

Type:
  `String`

String of text with the .hex representation of the input binary data

##### Example

    import MemoryMap from 'nrf-intel-hex';

    let memMap = new MemoryMap();
    let bytes = new Uint8Array(....);
    memMap.set(0x0FF80000, bytes); // The block with 'bytes' will start at offset 0x0FF80000

    let string = memMap.asHexString();

#### clone() → {MemoryMap}

Performs a deep copy of the current `MemoryMap`, returning a new one with exactly the same contents, but allocating new memory for each of its `Uint8Array`s.

Source:
  - intel-hex.js, line 732

##### Returns:

Type:
  `MemoryMap`

#### contains(memMap) → {Boolean}

Checks whether the current memory map contains the one given as a parameter.
"Contains" means that all the offsets that have a byte value in the given memory map have a value in the current memory map, and that the byte values are the same.
An empty memory map is always contained in any other memory map.
Returns boolean `true` if the memory map is contained, `false` otherwise.

Source:
  - intel-hex.js, line 917

##### Parameters:

Name | Type | Description
--- | --- | ---
`memMap` | `MemoryMap` | The memory map to check

##### Returns:

Type:
  `Boolean`

#### getUint32(offset, littleEndianopt) → {Number|undefined}

Locates the `Uint8Array` which contains the given offset, and returns the four bytes held at that offset, as a 32-bit unsigned integer.
Behaviour is similar to DataView.prototype.getUint32, except that this operates over a `MemoryMap` instead of over an `ArrayBuffer`, and that this may return `undefined` if the address is not entirely contained within one of the `Uint8Array`s.

Source:
  - intel-hex.js, line 562

##### Parameters:

Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`offset` | `Number` |  |  | The memory offset to read the data
`littleEndian` | `Boolean` | <optional> | false | Whether to fetch the 4 bytes as a little- or big-endian integer

##### Returns:

Type:
  `Number` | `undefined`

An unsigned 32-bit integer number

#### join(maxBlockSizeopt) → {MemoryMap}

Returns a new instance of `MemoryMap`, containing the same data, but concatenating together those memory blocks that are adjacent.
The insertion order of keys in the `MemoryMap` is guaranteed to be strictly ascending. In other words, when iterating through the `MemoryMap`, the addresses will be ordered in ascending order.
If `maxBlockSize` is given, blocks will be concatenated together only until the joined block reaches this size in bytes. This means that the output `MemoryMap` might have more entries than the input one.
If there is any overlap between blocks, an error will be thrown.
The returned `MemoryMap` will use newly allocated memory.

Source:
  - intel-hex.js, line 310

##### Parameters:

Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`maxBlockSize` | `Number` | <optional> | Infinity | Maximum size of the `Uint8Array`s in the returned `MemoryMap`.

##### Returns:

Type:
  `MemoryMap`

#### paginate(pageSizeopt, padopt) → {MemoryMap}

Returns a new instance of `MemoryMap`, where:

- Each key (the start address of each `Uint8Array`) is a multiple of `pageSize`
- The size of each `Uint8Array` is exactly `pageSize`
- Bytes from the input map to bytes in the output
- Bytes not in the input are replaced by a padding value

The scenario is wanting to prepare pages of bytes for a write operation, where the write operation affects a whole page/sector at once.
The insertion order of keys in the output `MemoryMap` is guaranteed to be strictly ascending. In other words, when iterating through the `MemoryMap`, the addresses will be ordered in ascending order.
The `Uint8Array`s in the output will be newly allocated.

Source:
  - intel-hex.js, line 506

##### Parameters:

Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`pageSize` | `Number` | <optional> | 1024 | The size of the output pages, in bytes
`pad` | `Number` | <optional> | 0xFF | The byte value to use for padding

##### Returns:

Type:
  `MemoryMap`

#### slice(address, length) → {MemoryMap}

Returns a new instance of `MemoryMap`, containing only data between the addresses `address` and `address + length`. Behaviour is similar to Array.prototype.slice, in that the return value is a portion of the current `MemoryMap`.
The returned `MemoryMap` might be empty.
Internally, this uses `subarray`, so new memory is not allocated.

Source:
  - intel-hex.js, line 838

##### Parameters:

Name | Type | Description
--- | --- | ---
`address` | `Number` | The start address of the slice
`length` | `Number` | The length of memory map to slice out

##### Returns:

Type:
  `MemoryMap`

#### slicePad(address, length, padByteopt) → {MemoryMap}

Returns a new instance of Uint8Array, containing only data between the addresses `address` and `address + length`. Any byte without a value in the input `MemoryMap` will have a value of `padByte`.
This method allocates new memory.

Source:
  - intel-hex.js, line 875

##### Parameters:

Name | Type | Attributes | Default | Description
--- | --- | --- | --- | ---
`address` | `Number` |  |  | The start address of the slice
`length` | `Number` |  |  | The length of memory map to slice out
`padByte` | `Number` | <optional> | 0xFF | The value of the byte assumed to be used as padding

##### Returns:

Type:
  `MemoryMap`