radare/radare2-webui

View on GitHub
www/m/js/core/BlockNavigator.js

Summary

Maintainability
D
1 day
Test Coverage
import {ChunkStatus} from './ChunkStatus';
import {NavigatorDirection} from './NavigatorDirection';

export class BlockNavigator {

    constructor() { }

    init() {
        if (typeof this.providerWorker === 'undefined') {
            console.log('provider worker should be defined');
            return;
        }

        this.configureWorker_();
    }

    configureWorker_() {
        var _this = this;
        this.providerWorker.onmessage = function(e) {
            if (e.data.dir === NavigatorDirection.CURRENT) {
                if (typeof _this.curChunk.data.callback !== 'undefined') {
                    for (var i = 0 ; i < _this.curChunk.data.callback.length ; i++) {
                        _this.curChunk.data.callback[i](e.data);
                    }
                }
                _this.curChunk.data = e.data;
                _this.curChunk.data.status = ChunkStatus.COMPLETED;
            } else {
                var dir = (e.data.dir === NavigatorDirection.BEFORE) ? 'prev' : 'next';

                var item = _this.curChunk;
                while (typeof item[dir] !== 'undefined') {
                    item = item[dir];
                    if (item.data.offset === e.data.offset) {
                        break;
                    }
                }

                if (item === _this.curChunk) {
                    console.log('Error, history corrupted');
                    return;
                }

                if (typeof item.data.callback !== 'undefined') {
                    for (var i = 0 ; i < item.data.callback.length ; i++) {
                        item.data.callback[i](e.data);
                    }
                }

                item.data = e.data;
                item.data.status = ChunkStatus.COMPLETED;
            }
        };
    }

    reset() {
        this.curChunk = undefined;
    }

    go(where) {
        var goNext = (where === NavigatorDirection.AFTER);
        var dir = (goNext) ? 'next' : 'prev';
        var howMany = this.gap;

        if (typeof this.curChunk[dir] !== 'undefined') {
            this.curChunk = this.curChunk[dir];
            this.currentOffset = this.curChunk.data.offset;
            // Should check (or not?) for negative offset
        } else {
            this.currentOffset = this.currentOffset + where * this.gap;

            var req = {
                dir: where,
                offset: this.currentOffset,
                status: ChunkStatus.LAUNCHED,
                callback: []
            };

            if (this.currentOffset < 0) {
                req.substract = this.currentOffset * -1;
                req.offset = 0;
                this.currentOffset = 0;
            }

            var newChunk = {
                data: req,
                prev: (goNext) ? this.curChunk : undefined,
                next: (!goNext) ? this.curChunk : undefined
            };

            this.curChunk[dir] = newChunk;
            this.curChunk = newChunk;

            this.providerWorker.postMessage(req);
        }
    }

    get(which, callback, force) {
        var dir = (which === NavigatorDirection.BEFORE) ? 'prev' : 'next';

        var item;
        if (which === NavigatorDirection.CURRENT) {
            item = this.curChunk;
        } else {
            if (typeof this.curChunk === 'undefined') {
                item = undefined;
            } else {
                item = this.curChunk[dir];
            }
        }

        // If there is a miss (when we start)
        var req;
        if (typeof item === 'undefined') {
            if (which === NavigatorDirection.CURRENT) {
                req = {
                    dir: NavigatorDirection.CURRENT,
                    offset: this.currentOffset,
                    status: ChunkStatus.LAUNCHED,
                    callback: []
                };
                this.curChunk = {
                    data: req,
                    prev: undefined,
                    next: undefined
                };
                item = this.curChunk;
                this.providerWorker.postMessage(req);
            } else {
                req = {
                    dir: which,
                    offset: this.currentOffset + (which * this.gap),
                    status: ChunkStatus.LAUNCHED,
                    callback: []
                };
                this.curChunk[dir] = {
                    data: req,
                    prev: (which === NavigatorDirection.AFTER) ? this.curChunk : undefined,
                    next: (which === NavigatorDirection.BEFORE) ? this.curChunk : undefined
                };
                item = this.curChunk[dir];
                this.providerWorker.postMessage(req);
            }
        } else if (force === true) {
            item.data.status = ChunkStatus.LAUNCHED;
            this.providerWorker.postMessage(item.data);
        }

        // We infer the data is here
        if (item.data.status !== ChunkStatus.LAUNCHED) {
            return callback(item.data);
        } else { // Data isn't here, we deffer our callback
            if (typeof item.data.callback === 'undefined') {
                item.data.callback = [];
            }
            item.data.callback.push(callback);
            return;
        }
    }

    isInside_(chunk, offset) {
        var start = chunk.offset;
        var end = start + this.gap;
        return (start <= offset && end >= offset);
    }


}