<commit_before>
/**
 * Object interface for constructing new SmartBuffer instances.
 */
interface SmartBufferOptions {
    // Buffer Encoding to use for reading/writing strings if one is not provided.
    encoding?: BufferEncoding;
    // The initial size of the internal Buffer.
    size?: number;
    // If a Buffer is provided, this Buffer's value will be used as the internal Buffer.
    buff?: Buffer;
}

// The default Buffer size if one is not provided.
const DEFAULT_SMARTBUFFER_SIZE = 4096;

// The default string encoding to use for reading/writing strings. 
const DEFAULT_SMARTBUFFER_ENCODING = 'utf8';

class SmartBuffer {
    public length: number = 0;
    public encoding: BufferEncoding = DEFAULT_SMARTBUFFER_ENCODING;

    private buff: Buffer;
    private writeOffset: number = 0;
    private readOffset: number = 0;

    /**
     * Creates a new SmartBuffer instance with the provided internal Buffer size and optional encoding.
     * 
     * @param size { Number } The size of the internal Buffer.
     * @param encoding { String } The BufferEncoding to use for strings.
     * 
     * @return { SmartBuffer }
     */
    public static fromSize(size: number, encoding?: BufferEncoding): SmartBuffer {
        return new this({
            size: size,
            encoding: encoding
        });
    }

    /**
     * Creates a new SmartBuffer instance with the provided Buffer and optional encoding.
     * 
     * @param buffer { Buffer } The Buffer to use as the internal Buffer value.
     * @param encoding { String } The BufferEncoding to use for strings.
     * 
     * @return { SmartBuffer }
     */
    public static fromBuffer(buff: Buffer, encoding?: BufferEncoding): SmartBuffer {
        return new this({
            buff: buff,
            encoding: encoding
        });
    }

    /**
     * Creates a new SmartBuffer instance with the provided SmartBufferOptions options.
     * 
     * @param options { SmartBufferOptions } The options to use when creating the SmartBuffer instance.
     */
    public static fromOptions(options: SmartBufferOptions): SmartBuffer {
        return new this(options);
    }

    /**
     * Type checking function that determines if an object is a SmartBufferOptions object.
     */
    static isSmartBufferOptions(options: SmartBufferOptions): options is SmartBufferOptions {
        const castOptions = (<SmartBufferOptions>options);

        return castOptions && (castOptions.encoding !== undefined || castOptions.size !== undefined || castOptions.buff !== undefined);
    }


    /**
     * Creates a new SmartBuffer instance.
     * 
     * @param arg1 { Number | BufferEncoding | Buffer | SmartBufferOptions }
     * @param arg2 { BufferEncoding }
     */
    constructor(arg1?: number | BufferEncoding | Buffer | SmartBufferOptions, arg2?: BufferEncoding) {
        
        // Initial buffer size provided
        if (typeof arg1 === 'number') {
            
            if (Number.isFinite(arg1) && Number.isInteger(arg1) && arg1 > 0) {
                this.buff = Buffer.allocUnsafe(arg1);
            } else {
                throw new Error('Invalid size provided. Size must be a valid integer greater than zero.');
            }
        // String Encoding Provided
        } else if (typeof arg1 === 'string') { 
            if (Buffer.isEncoding(arg1)) {
                this.buff = Buffer.allocUnsafe(DEFAULT_SMARTBUFFER_SIZE);
                this.encoding = arg1;
            } else {
                throw new Error('Invalid encoding provided. Please specify a valid encoding the internal Node.js Buffer supports.');
            }
        // Buffer instance provided
        } else if (arg1 instanceof Buffer) {
            this.buff = arg1;
            this.length = arg1.length;
        } else if (SmartBuffer.isSmartBufferOptions(arg1)) {

            // Checks for encoding
            if (arg1.encoding) {
                if (Buffer.isEncoding(arg1.encoding)) {
                    this.encoding = arg1.encoding;
                } else {
                    throw new  Error('Invalid encoding provided. Please specify a valid encoding the internal Node.js Buffer supports.');
                }
            }

            // Checks for initial size length
            if (arg1.size) {
                if (Number.isFinite(arg1.size) && Number.isInteger(arg1.size) && arg1.size > 0) {
                    this.buff = Buffer.allocUnsafe(arg1.size);
                } else {
                    throw new Error('Invalid size provided. Size must be a valid integer greater than zero.');
                }
                // Check for initial Buffer
            } else if (arg1.buff) {
                if (arg1.buff instanceof Buffer) {
                    this.buff = arg1.buff;
                    this.length = arg1.buff.length;
                } else {
                    throw new Error('Invalid buffer provided in SmartBufferOptions.');
                }
            } else {
                this.buff = Buffer.allocUnsafe(DEFAULT_SMARTBUFFER_SIZE);
            }
        } else if (typeof arg1 === 'object') {
            throw new Error('Invalid object supplied to SmartBuffer constructor.');
        } else {
            this.buff = Buffer.allocUnsafe(DEFAULT_SMARTBUFFER_SIZE);
        }

        // Check for encoding (Buffer, Encoding) constructor.
        if (typeof arg2 === 'string') {
            if (Buffer.isEncoding(arg2)) {
                this.encoding = arg2;
            } else {
                throw new Error('Invalid encoding provided. Please specify a valid encoding the internal Node.js Buffer supports.');
            }
        }
    }

    // Signed integers

    /**
     * Reads an Int8 value from the current read position.
     * 
     * @return { Number }
     */
    readInt8(): number {
        return this.readNumberValue(Buffer.prototype.readUInt8, 1);
    }

    /**
     * Reads an Int16BE value from the current read position.
     * 
     * @return { Number }
     */
    readInt16BE(): number {
        return this.readNumberValue(Buffer.prototype.readUInt16BE, 2);
    }

    /**
     * Reads an Int16LE value from the current read position.
     * 
     * @return { Number }
     */
    readInt16LE(): number {
        return this.readNumberValue(Buffer.prototype.readUInt16LE, 2);
    }

    /**
     * Reads an Int32BE value from the current read position.
     * 
     * @return { Number }
     */
    readInt32BE(): number {
        return this.readNumberValue(Buffer.prototype.readUInt32BE, 4);
    }

    /**
     * Reads an Int32LE value from the current read position.
     * 
     * @return { Number }
     */
    readInt32LE(): number {
        return this.readNumberValue(Buffer.prototype.readUInt32LE, 4);
    }

    /**
     * Writes an Int8 value to the current write position (or at optional offset).
     * 
     * @param value { Number } The value to write.
     * @param offset { Number } The offset to write the value at.
     * 
     * @return this<commit_msg>Fixed issue where reading signed values resulted in reading unsigned values<commit_after>
/**
 * Object interface for constructing new SmartBuffer instances.
 */
interface SmartBufferOptions {
    // Buffer Encoding to use for reading/writing strings if one is not provided.
    encoding?: BufferEncoding;
    // The initial size of the internal Buffer.
    size?: number;
    // If a Buffer is provided, this Buffer's value will be used as the internal Buffer.
    buff?: Buffer;
}

// The default Buffer size if one is not provided.
const DEFAULT_SMARTBUFFER_SIZE = 4096;

// The default string encoding to use for reading/writing strings. 
const DEFAULT_SMARTBUFFER_ENCODING = 'utf8';

class SmartBuffer {
    public length: number = 0;
    public encoding: BufferEncoding = DEFAULT_SMARTBUFFER_ENCODING;

    private buff: Buffer;
    private writeOffset: number = 0;
    private readOffset: number = 0;

    /**
     * Creates a new SmartBuffer instance with the provided internal Buffer size and optional encoding.
     * 
     * @param size { Number } The size of the internal Buffer.
     * @param encoding { String } The BufferEncoding to use for strings.
     * 
     * @return { SmartBuffer }
     */
    public static fromSize(size: number, encoding?: BufferEncoding): SmartBuffer {
        return new this({
            size: size,
            encoding: encoding
        });
    }

    /**
     * Creates a new SmartBuffer instance with the provided Buffer and optional encoding.
     * 
     * @param buffer { Buffer } The Buffer to use as the internal Buffer value.
     * @param encoding { String } The BufferEncoding to use for strings.
     * 
     * @return { SmartBuffer }
     */
    public static fromBuffer(buff: Buffer, encoding?: BufferEncoding): SmartBuffer {
        return new this({
            buff: buff,
            encoding: encoding
        });
    }

    /**
     * Creates a new SmartBuffer instance with the provided SmartBufferOptions options.
     * 
     * @param options { SmartBufferOptions } The options to use when creating the SmartBuffer instance.
     */
    public static fromOptions(options: SmartBufferOptions): SmartBuffer {
        return new this(options);
    }

    /**
     * Type checking function that determines if an object is a SmartBufferOptions object.
     */
    static isSmartBufferOptions(options: SmartBufferOptions): options is SmartBufferOptions {
        const castOptions = (<SmartBufferOptions>options);

        return castOptions && (castOptions.encoding !== undefined || castOptions.size !== undefined || castOptions.buff !== undefined);
    }


    /**
     * Creates a new SmartBuffer instance.
     * 
     * @param arg1 { Number | BufferEncoding | Buffer | SmartBufferOptions }
     * @param arg2 { BufferEncoding }
     */
    constructor(arg1?: number | BufferEncoding | Buffer | SmartBufferOptions, arg2?: BufferEncoding) {
        
        // Initial buffer size provided
        if (typeof arg1 === 'number') {
            
            if (Number.isFinite(arg1) && Number.isInteger(arg1) && arg1 > 0) {
                this.buff = Buffer.allocUnsafe(arg1);
            } else {
                throw new Error('Invalid size provided. Size must be a valid integer greater than zero.');
            }
        // String Encoding Provided
        } else if (typeof arg1 === 'string') { 
            if (Buffer.isEncoding(arg1)) {
                this.buff = Buffer.allocUnsafe(DEFAULT_SMARTBUFFER_SIZE);
                this.encoding = arg1;
            } else {
                throw new Error('Invalid encoding provided. Please specify a valid encoding the internal Node.js Buffer supports.');
            }
        // Buffer instance provided
        } else if (arg1 instanceof Buffer) {
            this.buff = arg1;
            this.length = arg1.length;
        } else if (SmartBuffer.isSmartBufferOptions(arg1)) {

            // Checks for encoding
            if (arg1.encoding) {
                if (Buffer.isEncoding(arg1.encoding)) {
                    this.encoding = arg1.encoding;
                } else {
                    throw new  Error('Invalid encoding provided. Please specify a valid encoding the internal Node.js Buffer supports.');
                }
            }

            // Checks for initial size length
            if (arg1.size) {
                if (Number.isFinite(arg1.size) && Number.isInteger(arg1.size) && arg1.size > 0) {
                    this.buff = Buffer.allocUnsafe(arg1.size);
                } else {
                    throw new Error('Invalid size provided. Size must be a valid integer greater than zero.');
                }
                // Check for initial Buffer
            } else if (arg1.buff) {
                if (arg1.buff instanceof Buffer) {
                    this.buff = arg1.buff;
                    this.length = arg1.buff.length;
                } else {
                    throw new Error('Invalid buffer provided in SmartBufferOptions.');
                }
            } else {
                this.buff = Buffer.allocUnsafe(DEFAULT_SMARTBUFFER_SIZE);
            }
        } else if (typeof arg1 === 'object') {
            throw new Error('Invalid object supplied to SmartBuffer constructor.');
        } else {
            this.buff = Buffer.allocUnsafe(DEFAULT_SMARTBUFFER_SIZE);
        }

        // Check for encoding (Buffer, Encoding) constructor.
        if (typeof arg2 === 'string') {
            if (Buffer.isEncoding(arg2)) {
                this.encoding = arg2;
            } else {
                throw new Error('Invalid encoding provided. Please specify a valid encoding the internal Node.js Buffer supports.');
            }
        }
    }

    // Signed integers

    /**
     * Reads an Int8 value from the current read position.
     * 
     * @return { Number }
     */
    readInt8(): number {
        return this.readNumberValue(Buffer.prototype.readInt8, 1);
    }

    /**
     * Reads an Int16BE value from the current read position.
     * 
     * @return { Number }
     */
    readInt16BE(): number {
        return this.readNumberValue(Buffer.prototype.readInt16BE, 2);
    }

    /**
     * Reads an Int16LE value from the current read position.
     * 
     * @return { Number }
     */
    readInt16LE(): number {
        return this.readNumberValue(Buffer.prototype.readInt16LE, 2);
    }

    /**
     * Reads an Int32BE value from the current read position.
     * 
     * @return { Number }
     */
    readInt32BE(): number {
        return this.readNumberValue(Buffer.prototype.readInt32BE, 4);
    }

    /**
     * Reads an Int32LE value from the current read position.
     * 
     * @return { Number }
     */
    readInt32LE(): number {
        return this.readNumberValue(Buffer.prototype.readInt32LE, 4);
    }

    /**
     * Writes an Int8 value to the current write position (or at optional offset).
     * 
     * @param value { Number } The value to write.
     * @param offset { Number } The offset to write the value at.
     * 
     * @return this
{'fraction_non_alphanumeric': 0.09090263475605426, 'fraction_numerical': 0.010652652510475109, 'mean_word_length': 1.9615141955835962, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3261727', 'n_tokens_mistral': 3695, 'n_tokens_neox': 3520, 'n_words': 1183}