npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

qfs-compression

v0.2.1

Published

A JavaScript implementation of the QFS compression and decompression algorithm

Downloads

45

Readme

qfs-compression

This library provides a JS implementation of the QFS compression algorithm. This algorithm is based on LZ77 and is commonly found in files used by EA games.

It is basically a port of an original C implementation made by @wouanagaine. More information on it can be found on the SC4 devotion wiki.

Installation

npm install qfs-compression

Usage

The module exports two functions: compress() and decompress(). Both accept either a Node.js Buffer or a Uint8Array.

import { compress, decompress } from 'qfs-compression';

let input = Buffer.from([...]);
let input = new Uint8Array([...]);

let compressed = compress(input);
let original = decompress(compressed);

Input-output matching

It is important to understand that the type of the output buffer depends on the type of the input buffer. In short, if a Node.js buffer was passed, a Node.js buffer is returned, otherwise a bare Uint8Array is returned. This is useful for example in the browser as it does not require a Buffer polyfill this way.

Technically speaking however, if the input object's constructor exposes an .allocUnsafe(size) method - such as Node.js buffers - this method is used for setting up the output object as this is the fastest. If no .allocUnsafe() is found, then the output object is created using new input.constructor[Symbol.species](size), so it should work for custom classes that override Uint8Array too:

class MyBuffer extends Uint8Array {}
let output = decompress(new MyBuffer(1024));
// output instanceof MyBuffer === true

Documentation

compress(input[, options])

  • input <Buffer> | <Uint8Array> An uncompressed buffer of binary data that needs compression.
  • options <Object>:
    • windowBits: The amount of bits used for the sliding window. Defaults to 17, which means a sliding window of 128 kB.
    • includeSize: Prefix the compressed output with its size as an Uint32LE. Defaults to false.

decompress(input)

  • input <Buffer> | <Uint8Array> A buffer with binary data that was previously compressed using QFS compression.

Caveats

  • The limit of data that can be compressed is 16MB. This is because the uncompressed size is stored in the header using 3 bytes, which means a maximum size of 0xffffff bytes can be properly written away in the header.

  • In some games (for example SimCity 4), a compressed buffer is prefixed by 4 bytes containing the size of the entire buffer. The library does not detect this automatically, so if you are dealing with such games, you need to manually truncate the bytes as

    decompress(input.slice(4))

Performance

Obviously a pure C implementation is faster than a JS implementation. However, v8 is able to produce really good optimized code for the library, so if the compression function gets hot, it will match the performance of a C implementation, and may even be faster than linking a C implementation using native Node addons.