Uname: Linux web3.us.cloudlogin.co 5.10.226-xeon-hst #2 SMP Fri Sep 13 12:28:44 UTC 2024 x86_64
Software: Apache
PHP version: 8.1.31 [ PHP INFO ] PHP os: Linux
Server Ip: 162.210.96.117
Your Ip: 18.191.29.0
User: edustar (269686) | Group: tty (888)
Safe Mode: OFF
Disable Function:
NONE

name : utils.js
/* SPX - A simple profiler for PHP
 * Copyright (C) 2017-2022 Sylvain Lassaut <NoiseByNorthwest@gmail.com>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


import * as math from './?SPX_UI_URI=/js/math.js';

export function getCookieVar(name) {
    let m = document.cookie.match(new RegExp('(^|\\b)' + name + '=([^;]+)'));

    return m ? m[2] : null;
}

export function setCookieVar(name, value) {
    document.cookie = name + '=' + value + '; expires=Thu, 31 Dec 2037 23:59:59 UTC; path=/';
}

export function truncateFunctionName(str, max) {
    if (str.length < max) {
        return str;
    }

    return str.slice(0, max / 2 - 1) + '…' + str.slice(-max / 2);
}

function process(func, async, delay) {
    if (async || false) {
        setTimeout(func, delay || 0);
    } else {
        func();
    }
}

export function processPipeline(calls, async, delay) {
    calls = calls.slice(0);
    calls.reverse();
    let ret;

    function makeNextCall() {
        if (calls.length == 0) {
            return;
        }

        let call = calls.pop();
        ret = call(ret);

        if (calls.length > 0) {
            process(makeNextCall, async, delay);
        }
    }

    process(makeNextCall, async, 0);
}

export function processCallChain(calls, async, delay) {
    calls = calls.slice(0);
    calls.reverse();

    function makeNextCall() {
        if (calls.length == 0) {
            return;
        }

        let call = calls.pop();

        process(() => {
            call(makeNextCall);
        }, async, delay || 0);
    }

    makeNextCall();
}

export function processChunksAsync(from, to, chunkSize, chunkProcessor, done, delay) {
    if (chunkSize < 1) {
        chunkSize = chunkSize * (to - from);
    }

    chunkSize = math.bound(Math.round(chunkSize), 1, to - from);

    let chunks = [];

    while (1) {
        chunks.push([from, Math.min(to, from + chunkSize)]);
        if (from + chunkSize >= to) {
            break;
        }

        from += chunkSize;
    }

    chunks.reverse();

    function processChunk() {
        if (chunks.length == 0) {
            done();

            return;
        }

        let chunk = chunks.pop();
        chunkProcessor(chunk[0], chunk[1]);
        setTimeout(processChunk, delay || 0);
    }

    setTimeout(processChunk, 0);
}

export class PackedRecordArray {

    constructor(fields, size) {
        this.typesInfo = {
            'int8': {
                arrayType: Int8Array,
            },
            'int32': {
                arrayType: Int32Array,
            },
            'float32': {
                arrayType: Float32Array,
            },
            'float64': {
                arrayType: Float64Array,
            },
        };

        this.fields = [];
        this.elemSize = 0;
        for (let fieldName in fields) {
            const type = fields[fieldName];
            if (!(type in this.typesInfo)) {
                throw new Error('Unsupported type: ' + type);
            }

            const typeInfo = this.typesInfo[type];
            this.fields.push({
                name: fieldName,
                typeInfo: typeInfo,
            });

            this.elemSize += typeInfo.arrayType.BYTES_PER_ELEMENT;
        }

        this.fields.sort(
            (a, b) => b.typeInfo.arrayType.BYTES_PER_ELEMENT - a.typeInfo.arrayType.BYTES_PER_ELEMENT
        );

        const alignment = this.fields[0].typeInfo.arrayType.BYTES_PER_ELEMENT;

        this.elemSize = Math.ceil(this.elemSize / alignment) * alignment;
        this.size = size;

        this.buffer = new ArrayBuffer(this.size * this.elemSize);

        this.fieldIndexes = {};
        let currentIdx = 0;
        let currentOffset = 0;
        for (let field of this.fields) {
            this.fieldIndexes[field.name] = currentIdx++;

            field.typeElemSize = this.elemSize / field.typeInfo.arrayType.BYTES_PER_ELEMENT;
            field.typeOffset = currentOffset / field.typeInfo.arrayType.BYTES_PER_ELEMENT;
            field.typeArray = new field.typeInfo.arrayType(this.buffer);

            currentOffset += field.typeInfo.arrayType.BYTES_PER_ELEMENT;
        }
    }

    getSize() {
        return this.size;
    }

    setElement(idx, obj) {
        const elemOffset = idx * this.elemSize;

        for (let field of this.fields) {
            field.typeArray[idx * field.typeElemSize + field.typeOffset] = obj[field.name] || 0;
        }
    }

    setElementFieldValue(idx, fieldName, fieldValue) {
        if (!(fieldName in this.fieldIndexes)) {
            throw new Error('Unknown field: ' + fieldName);
        }

        const field = this.fields[this.fieldIndexes[fieldName]];

        field.typeArray[idx * field.typeElemSize + field.typeOffset] = fieldValue || 0;
    }

    getElement(idx) {
        const elemOffset = idx * this.elemSize;

        let obj = {};
        for (let field of this.fields) {
            obj[field.name] = field.typeArray[idx * field.typeElemSize + field.typeOffset];
        }

        return obj;
    }

    getElementFieldValue(idx, fieldName) {
        if (!(fieldName in this.fieldIndexes)) {
            throw new Error('Unknown field: ' + fieldName);
        }

        const field = this.fields[this.fieldIndexes[fieldName]];

        return field.typeArray[idx * field.typeElemSize + field.typeOffset];
    }
}

export class ChunkedRecordArray {

    constructor(fields, chunkSize) {
        this.fields = fields;
        this.chunkSize = chunkSize;
        this.chunks = [];
        this.size = 0;
    }

    resize(newSize) {
        const chunkCount = Math.ceil(newSize / this.chunkSize);
        for (let i = this.chunks.length; i < chunkCount; i++) {
            this.chunks.push(new PackedRecordArray(this.fields, this.chunkSize));
        }

        this.size = newSize;
    }

    getSize() {
        return this.size;
    }

    setElement(idx, obj) {
        if (idx + 1 > this.getSize()) {
            this.resize(idx + 1);
        }

        this.chunks[Math.floor(idx / this.chunkSize)].setElement(idx % this.chunkSize, obj);
    }

    setElementFieldValue(idx, fieldName, fieldValue) {
        this.chunks[Math.floor(idx / this.chunkSize)].setElementFieldValue(idx % this.chunkSize, fieldName, fieldValue);
    }

    getElement(idx) {
        return this.chunks[Math.floor(idx / this.chunkSize)].getElement(idx % this.chunkSize);
    }

    getElementFieldValue(idx, fieldName) {
        return this.chunks[Math.floor(idx / this.chunkSize)].getElementFieldValue(idx % this.chunkSize, fieldName);
    }
}


/*
    FIXME move all categories related stuff elsewhere (e.g. in a dedicated module)
*/
let categCache = null;
const categStoreKey = 'spx-report-current-categories';

export function getCategories(includeUncategorized=false) {
    if (categCache === null) {
        let loaded = window.localStorage.getItem(categStoreKey);
        categCache = !!loaded ? JSON.parse(loaded): [];
        categCache.forEach(c => {
            c.patterns = c.patterns.map(p => new RegExp(p, 'gi'))
        });
    }

    if (includeUncategorized) {
        let all = categCache.slice();
        all.push({
            label: '<uncategorized>',
            color: [140,140,140],
            patterns: [/./],
            isDefault: true
        });
        return all;
    }
    return categCache;
}

export function setCategories(categories) {
    categCache = null;
    categories = categories.filter(c => !c.isDefault)
    categories.forEach(c => {
        c.patterns = c.patterns.map(p => p.source)
    });
    window.localStorage.setItem(categStoreKey, JSON.stringify(categories));
}
© 2025 GrazzMean