Giter Club home page Giter Club logo

js-sdsl's Introduction

js-sdsl logo

A javascript standard data structure library which benchmark against C++ STL

NPM Version Build Status Coverage Status GITHUB Star NPM Downloads Gzip Size Rate this package MIT-license GITHUB-language

English | 简体中文

✨ Included data structures

  • Stack - first in last out stack.
  • Queue - first in first out queue.
  • PriorityQueue - heap-implemented priority queue.
  • Vector - protected array, cannot to operate properties like length directly.
  • LinkList - linked list of non-contiguous memory addresses.
  • Deque - double-ended-queue, O(1) time complexity to unshift or getting elements by index.
  • OrderedSet - sorted set which implemented by red black tree.
  • OrderedMap - sorted map which implemented by red black tree.
  • HashSet - refer to the polyfill of ES6 Set.
  • HashMap - refer to the polyfill of ES6 Map.

⚔️ Benchmark

We are benchmarking against other popular data structure libraries. In some ways we're better than the best library. See benchmark.

🖥 Supported platforms


IE / Edge

Firefox

Chrome

Safari

Opera

NodeJs
Edge 12 36 49 10 36 10

📦 Download

Download directly by cdn:

Or install js-sdsl using npm:

npm install js-sdsl

Or you can download the isolation packages containing only the containers you want:

package npm size docs
@js-sdsl/stack NPM Package GZIP Size link
@js-sdsl/queue NPM Package GZIP Size link
@js-sdsl/priority-queue NPM Package GZIP Size link
@js-sdsl/vector NPM Package GZIP Size link
@js-sdsl/link-list NPM Package GZIP Size link
@js-sdsl/deque NPM Package GZIP Size link
@js-sdsl/ordered-set NPM Package GZIP Size link
@js-sdsl/ordered-map NPM Package GZIP Size link
@js-sdsl/hash-set NPM Package GZIP Size link
@js-sdsl/hash-map NPM Package GZIP Size link

🪒 Usage

You can visit our official website to get more information.

To help you have a better use, we also provide this API document.

For previous versions of the documentation, please visit:

https://js-sdsl.org/js-sdsl/previous/v${version}/index.html

E.g.

https://js-sdsl.org/js-sdsl/previous/v4.1.5/index.html

For browser

<script src="https://unpkg.com/js-sdsl/dist/umd/js-sdsl.min.js"></script>
<script>
    const {
      Vector,
      Stack,
      Queue,
      LinkList,
      Deque,
      PriorityQueue,
      OrderedSet,
      OrderedMap,
      HashSet,
      HashMap
    } = sdsl;
    const myOrderedMap = new OrderedMap();
    myOrderedMap.setElement(1, 2);
    console.log(myOrderedMap.getElementByKey(1)); // 2
</script>

For npm

// esModule
import { OrderedMap } from 'js-sdsl';
// commonJs
const { OrderedMap } = require('js-sdsl');
const myOrderedMap = new OrderedMap();
myOrderedMap.setElement(1, 2);
console.log(myOrderedMap.getElementByKey(1)); // 2

🛠 Test

Unit test

We use karma and mocha frame to do unit tests and synchronize to coveralls. You can run yarn test:unit command to reproduce it.

For performance

We tested most of the functions for efficiency. You can go to gh-pages/performance.md to see our running results or reproduce it with yarn test:performance command.

You can also visit here to get the result.

⌨️ Development

Use Gitpod, a free online dev environment for GitHub.

Open in Gippod

Or clone locally:

$ git clone https://github.com/js-sdsl/js-sdsl.git
$ cd js-sdsl
$ npm install
$ npm run dev   # development mode

Then you can see the output in dist/cjs folder.

🤝 Contributing

Feel free to dive in! Open an issue or submit PRs. It may be helpful to read the Contributor Guide.

Contributors

Thanks goes to these wonderful people:


Takatoshi Kondo

💻 ⚠️

noname

💻

This project follows the all-contributors specification. Contributions of any kind welcome!

❤️ Sponsors and Backers

The special thanks to these sponsors or backers because they provided support at a very early stage:

eslint logo

Thanks also give to these sponsors or backers:

sponsors

backers

🪪 License

MIT © ZLY201

js-sdsl's People

Contributors

allcontributors[bot] avatar dependabot[bot] avatar noname0310 avatar redboltz avatar zly201 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

js-sdsl's Issues

Get index of key-value pair in OrderedMap

Is your feature request related to a problem? Please describe.
I have such problem: I want to know how much values are between of two keys.
I have a timeline of thousands of events, and I use an OrderedMap (key is timestamp, value — event data), because I draw a line chart for them. I want to give a user an opportunity to know, how many events are between two chosen points.

Describe the solution you'd like
If I'd have an index of an item, I could do this:

// eventMap is an OrderedMap
const leftIndex = eventMap.getIndexByKey(leftKey)
const rightIndex = eventMap.getIndexByKey(rightKey)
const eventsBetween = rightIndex - leftIndex - 1

Describe alternatives you've considered
I could also have a simple method like OrderedMap.prototype.itemsBetweenKeys:

// eventMap is an OrderedMap
const eventsBetween = eventMap.itemsBetweenKeys(leftKey, rightKey)

bug: get wrong tree index when tree size is 1

Describe the bug

Get wrong tree index when tree size is 1.

To Reproduce

const st = new OrderedSet([1], undefined, true);
console.log(st.begin().index);  // expected 0 but get 2

Expected behavior

Expected 0 but get 2.

Question: OrderedSet and comparison function

Is there any possibility to use comparison by two fields for a set of objects?

Example:
I have simple objects, like

{
    "id": 1,
    "price": 10
},
{
    "id": 2,
    "price": 9
},
{
    "id": 3,
    "price": 3
}

I wanna set of this objects, but ordered by price ASC and id DESC.
Is it real?

Thanks for any advice!

RBTree insert optimization

Optimize the red-black tree insertion function until the performance is equal to functional-red-black-tree

`isAccessible` property for iterators?

Is your feature request related to a problem? Please describe.

This is not really a problem, but I noticed accessing an iterator's pointer causes users some confusion (e.g. #145).

From what I can tell, the correct way to check if an iterator's pointer can be accessed varies slightly for each collection, but is usually something like (given collection, collection, and the appropriate iterator instance, it):

!it.equals(collection.end())

Describe the solution you'd like

I wonder if it is a good idea to have an isAccessible boolean getter on all the iterators so you can check if it can be accessed.

Describe alternatives you've considered
Otherwise you can just try to access it and catch the RangeError, but this is not the best practice in JavaScript (errors are best used for genuine runtime errors etc. rather than for logic).

Users making sure they understand how the collection works and when the pointer can be accessed or not is always a good idea, of course 😉.

Additional context

This could also help with enhancing the code readability and self-documenting, as there would be functions defined in the source providing definitive way of checking if the pointer can be accessed.

Export default for isolatation package

Is your feature request related to a problem? Please describe.

Now:

import { OrderedSet } from '@js-sdsl/ordered-set';

Describe the solution you'd like

I want:

import OrderedSet from '@js-sdsl/ordered-set';

Additional context

import { OrderedSet } from '@js-sdsl/ordered-set';

It doesn't make sense because there is only one member has been exported which named OrderedSet.

Does it possible? @noname0310

I think the problem will be require doesn't support default.

[feature request] insert with hint for TreeContainers

Is your feature request related to a problem? Please describe.

I want to update the element in the TreeContainer (e.g. OrderedSet), but it is prohibited.
It is reasonable because updated element could insert the different position.

However, users sometimes know the updated element is still the same position.
For example,

Before update:
    V
[1, 3, 5]

After update:
    V
[1, 4, 5]

When I want to update the element, I need to do the following steps:

  1. container.find(key) the element's iterator. Then got it.
  2. container.eraseElementByIterator(it)
  3. Create the new element based on the gotten element and insert it.

Step1 and 3 are O(logN) time complexity.
I want to eliminate Step3 cost.

Describe the solution you'd like
js-sdsl's design refers to C++ STL.
C++ std::set::insert has insert(hint, value) overload.
https://en.cppreference.com/w/cpp/container/set/insert
See (3) (4) overloads.

Since C++ 11
3-4) Amortized constant if the insertion happens in the position just before the hint, logarithmic in the size of the container otherwise.

container.eraseElementByIterator(it) at the step2 returns the iterator just after the erased element.
So if I use the returned iterator as the hint, then the hint iterator is the insertion happens in the position just before the hint.

So the steps become as follows:

  1. container.find(key) the element's iterator. Then got it.
  2. it = container.eraseElementByIterator(it)
  3. Create the new element based on the gotten element and insert it with hint. container.insertWithHint(it, 4)

Step3 becomes O(1) time complexity thanks to the hint it.

I guess that js-sdsl can implement similar way to the C++ one.

Describe alternatives you've considered

Directly modify the element value by user's risk. However, insert() with hint achieves the same goal (eliminate extra O(logN) time complexity) more elegant way.

Additional context

libc++ implementation of std::set::insert(hint, value)
https://github.com/llvm-mirror/libcxx/blob/2f961a057f1ecb29d40892fe9198fe4e4b5c5619/include/set#L704-L711

[feature request] lower_bound like function for Map

Thank you for writing a great library.
I'm looking for https://stackoverflow.com/questions/65948823/sorted-ordered-collection-for-javascript

https://github.com/ZLY201/js-sdsl/blob/1ea84551eb7c7cf07cce5752406e18896f0c34ab/src/Map/Map.ts
seems to have the follwoing methods:

  • size()
  • empty()
  • clear()
  • front()
  • back()
  • forEach()
  • getElementByPos()
  • eraseElementByPos()
  • eraseElementByKey()
  • setElement()
  • find()
  • getElementByKey()
  • union()
  • getHeight()

I'd like to do as follows.
Let's say the Map has the key [1, 3, 6, 7] (values are not important so I omit them), and call some lower_bound() like function with the argument 4, then return node 6 because it is just after the 4.
I guess that I can't do that using a combination of existing methods.

Tree shaking not work with js-sdsl

Describe the bug

Tree shaking not work with js-sdsl when use import { xxx } from 'js-sdsl'

To Reproduce

Expected behavior

Tree shaking should work.

Screenshots

Additional context

See here.

Queue is empty, but the last value still exists

Describe the bug
The last value comes out even though the size of the queue is 0.

To Reproduce
Steps to reproduce the behavior:

import { Queue } from "js-sdsl";

const testQueue = new Queue<number>();
testQueue.push(1);
testQueue.push(2);

console.log(testQueue.front(), testQueue.size());
testQueue.pop();
console.log(testQueue.front(), testQueue.size());
testQueue.pop();
console.log(testQueue.front(), testQueue.size());

Expected behavior
expected behavior is:

1 2
2 1
undefined 0

actual result is:

1 2
2 1 
2 0

Additional context
There was a similar problem with version 4.1.2 and it was fixed in 4.1.3

This problem occurred again in 4.1.4-beta.0

In my opinion, adding operations on empty containers to the test case will prevent recurrence of this problem in future updates.

Memory complexity?

After swapping functional-red-black-tree to js-sdsl in ethereumjs/ethereumjs-monorepo#2283, we now run into an out-of-memory exception in one of the unit tests which uses a big chunk of memory. This seems to imply that js-sdsl is worse in memory usage than functional-red-black-tree. Is there any theory of this memory complexity?

OrderedSet with less than 3 items reverse iteration infinite loop

Describe the bug
OrderedSet with less than 3 (exactly 2 or 1) items reverse iteration falls into infinite loop

  • Tested on node 16.8.1 / FF 113.0.2 (Mac)
  • @js-sdsl/ordered-set version 4.4.0

To Reproduce

const orderedSet = new OrderedSet([1, 2]);
const result = [];
const begin = orderedSet.rBegin();
const end = orderedSet.rEnd();
for (const it = begin; !it.equals(end); it.next()) {
  result.push(it.pointer);
}
console.log(result); // Must be [2, 1]

Expected behavior
Everything works

Actual behavior
Browser just goes into infinite loop. Node crashes:

#
# Fatal error in , line 0
# Fatal JavaScript invalid size error 169220804
#
#
#
#FailureMessage Object: 0x7ff7bd33b880
 1: 0x102cf8cf2 node::NodePlatform::GetStackTracePrinter()::$_3::__invoke() [~/.nvm/versions/node/v16.18.1/bin/node]
 2: 0x103ccddf3 V8_Fatal(char const*, ...) [~/.nvm/versions/node/v16.18.1/bin/node]
 3: 0x102f74826 v8::internal::FactoryBase<v8::internal::Factory>::NewFixedArray(int, v8::internal::AllocationType) [~/.nvm/versions/node/v16.18.1/bin/node]
 4: 0x103102014 v8::internal::(anonymous namespace)::ElementsAccessorBase<v8::internal::(anonymous namespace)::FastPackedSmiElementsAccessor, v8::internal::(anonymous namespace)::ElementsKindTraits<(v8::internal::ElementsKind)0> >::GrowCapacity(v8::internal::Handle<v8::internal::JSObject>, unsigned int) [~/.nvm/versions/node/v16.18.1/bin/node]
 5: 0x10332601d v8::internal::Runtime_GrowArrayElements(int, unsigned long*, v8::internal::Isolate*) [~/.nvm/versions/node/v16.18.1/bin/node]
 6: 0x1036dcc19 Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_NoBuiltinExit [~/.nvm/versions/node/v16.18.1/bin/node]
 7: 0x10d7b1890 
 8: 0x10366f6ea Builtins_InterpreterEntryTrampoline [~/.nvm/versions/node/v16.18.1/bin/node]

ESM build has classes downleveled to functions, but CJS build does not

See files published on NPM:
ESM: https://unpkg.com/browse/[email protected]/dist/esm/container/OtherContainer/Queue.js

ESM Build Source
var __extends = this && this.t || function() {
    var extendStatics = function(t, i) {
        extendStatics = Object.setPrototypeOf || {
            __proto__: []
        } instanceof Array && function(t, i) {
            t.__proto__ = i;
        } || function(t, i) {
            for (var n in i) if (Object.prototype.hasOwnProperty.call(i, n)) t[n] = i[n];
        };
        return extendStatics(t, i);
    };
    return function(t, i) {
        if (typeof i !== "function" && i !== null) throw new TypeError("Class extends value " + String(i) + " is not a constructor or null");
        extendStatics(t, i);
        function __() {
            this.constructor = t;
        }
        t.prototype = i === null ? Object.create(i) : (__.prototype = i.prototype, new __);
    };
}();

import { Base } from "../ContainerBase";

var Queue = function(t) {
    __extends(Queue, t);
    function Queue(i) {
        if (i === void 0) {
            i = [];
        }
        var n = t.call(this) || this;
        n.A = 0;
        n.tt = [];
        var e = n;
        i.forEach((function(t) {
            e.push(t);
        }));
        return n;
    }
    Queue.prototype.clear = function() {
        this.tt = [];
        this.M = this.A = 0;
    };
    Queue.prototype.push = function(t) {
        var i = this.tt.length;
        if (this.A / i > .5 && this.A + this.M >= i && i > 4096) {
            var n = this.M;
            for (var e = 0; e < n; ++e) {
                this.tt[e] = this.tt[this.A + e];
            }
            this.A = 0;
            this.tt[this.M] = t;
        } else this.tt[this.A + this.M] = t;
        return ++this.M;
    };
    Queue.prototype.pop = function() {
        if (this.M === 0) return;
        var t = this.tt[this.A++];
        this.M -= 1;
        return t;
    };
    Queue.prototype.front = function() {
        if (this.M === 0) return;
        return this.tt[this.A];
    };
    return Queue;
}(Base);

export default Queue;
//# sourceMappingURL=Queue.js.map

CJS: https://unpkg.com/browse/[email protected]/dist/cjs/container/OtherContainer/Queue.js

CJS Build Source
"use strict";

Object.defineProperty(exports, "t", {
    value: true
});

exports.default = void 0;

var _ContainerBase = require("../ContainerBase");

class Queue extends _ContainerBase.Base {
    constructor(t = []) {
        super();
        this.j = 0;
        this.q = [];
        const s = this;
        t.forEach((function(t) {
            s.push(t);
        }));
    }
    clear() {
        this.q = [];
        this.i = this.j = 0;
    }
    push(t) {
        const s = this.q.length;
        if (this.j / s > .5 && this.j + this.i >= s && s > 4096) {
            const s = this.i;
            for (let t = 0; t < s; ++t) {
                this.q[t] = this.q[this.j + t];
            }
            this.j = 0;
            this.q[this.i] = t;
        } else this.q[this.j + this.i] = t;
        return ++this.i;
    }
    pop() {
        if (this.i === 0) return;
        const t = this.q[this.j++];
        this.i -= 1;
        return t;
    }
    front() {
        if (this.i === 0) return;
        return this.q[this.j];
    }
}

var _default = Queue;

exports.default = _default;
//# sourceMappingURL=Queue.js.map

If I had to guess it's because the ESM build is set to target ES5:

js-sdsl/gulpfile.ts

Lines 27 to 37 in 28fe66c

gulp.task(
'esm',
() => gulpFactory(
{ globs: 'src/**/*.ts' },
'dist/esm',
{
overrideSettings: {
target: 'ES5',
module: 'ES2015',
declaration: true
}

Whereas the CJS build does not:

js-sdsl/gulpfile.ts

Lines 12 to 21 in 28fe66c

gulp.task(
'cjs',
() => gulpFactory(
{ globs: 'src/**/*.ts' },
'dist/cjs',
{
overrideSettings: {
module: 'ES2015',
declaration: true
},

Error: Cannot find module './Base'

Describe the bug
Could it be that this changes now hides that index file in the cjs build?
https://github.com/js-sdsl/js-sdsl/pull/57/files#diff-8a95d77a8ee9283d083856706c50385315d87a75d2ab9f963b64a16c06b8c332R4

It breaks for me here
image

To Reproduce
Steps to reproduce the behavior:

  1. Run eslint >= 8.23.1 with some indenting rules active
  2. See error
> eslint "./src/**/*.ts"


Oops! Something went wrong! :(

  ESLint: 8.26.0

Error: Cannot find module './Base'
Require stack:
- my_project/node_modules/js-sdsl/dist/cjs/container/TreeContainer/OrderedSet.js
- my_project/node_modules/js-sdsl/dist/cjs/index.js
- my_project/node_modules/eslint/lib/rules/indent.js
- my_project/node_modules/eslint/lib/rules/index.js
- my_project/node_modules/eslint/lib/linter/rules.js
- my_project/node_modules/eslint/lib/linter/linter.js
- my_project/node_modules/eslint/lib/linter/index.js
- my_project/node_modules/eslint/lib/cli-engine/cli-engine.js
- my_project/node_modules/eslint/lib/eslint/eslint.js
- my_project/node_modules/eslint/lib/eslint/index.js
- my_project/node_modules/eslint/lib/cli.js
- my_project/node_modules/eslint/bin/eslint.js
at Module._resolveFilename (node:internal/modules/cjs/loader:985:15)
at Module._load (node:internal/modules/cjs/loader:833:27)
at Module.require (node:internal/modules/cjs/loader:1051:19)
at require (node:internal/modules/cjs/helpers:103:18)
at Object.<anonymous> (my_project/node_modules/js-sdsl/dist/cjs/container/TreeContainer/OrderedSet.js:9:36)
    at Module._compile (node:internal/modules/cjs/loader:1149:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1203:10)
    at Module.load (node:internal/modules/cjs/loader:1027:32)
    at Module._load (node:internal/modules/cjs/loader:868:12)
    at Module.require (node:internal/modules/cjs/loader:1051:19)

Expected behavior
A compilable module is packaged.

Screenshots
See above

Additional context

OrderedMapIterator.pointer does not support array destructuring assignment (TypeError: it.pointer is not iterable)

Describe the bug
The value returned by OrderedMapIterator#pointer only supports access by index and does not implement iterable protocol, and hence you can't use it with destructuring assignment syntax.

I am working with OrderedMap but presumably the same problem applies to iterators for the other map collections.

To Reproduce
Given an OrderedMapIterator, it, which is not pointing to end() or rEnd()
(example setup code):

const map = new OrderedMap();
map.setElement('a', 1);
map.setElement('c', 2);
const it = map.lowerBound('b'); // Will be pointing to key 'c'
// Does not work:
const [key, value] = it.pointer; // Throws TypeError: it.pointer is not iterable
// Works:
const key = it.pointer[0];
const value = it.pointer[1];

Expected behavior
Array destructuring assignment is idiomatic so I think it would be expected to be able to do this.
The solution is to implement Symbol.iterator method on the Proxy object returned by pointer.
However, I would like to suggest a simpler solution, maybe we can just allow accessing by property names "key" and "value".
So we could do e.g.

// ...
const {key, value} = it.pointer;
// Or if we want to assign different local variable names:
const {key: diffNameForKey, value: diffNameForValue} = it.pointer;

This would not be a breaking change as accessing by index could still be supported. For completeness, the iterable implementation is pretty simple and allows using the array destructuring syntax. (I can have a go at providing an implementation if you want). I wonder if it would be simpler to just return an array rather than use a Proxy, but I assume Proxy was chosen for a reason?

Additional context
This problem may not show up if transpiling to an older ES target, where destructuring assignment is transpiled to accessing by index syntax.

Another idea for a solution: I wonder if it would be a good idea to provide convenience property getters directly on the OrderedMapIterator? e.g. it.key and it.value.

Make heap stronger

Add follow functions to heap:

  • find (check if element is in heap)
  • remove (remove specified item)
  • updateItem (update item and it's pos in the heap)
  • toArray (return copy array of heap)

[RFC] About the version 5.x

In previous versions, I relied too much on C++ STL.

In fact, many designs in C++ STL are not suitable for Javascript, especially in the function name specification.

This RFC (Request for Comment) outlines the all updates to js-sdsl which will be done in 2023.

  • Modify the names of all apis to conform to the specification in javascript.
  • Organize the code of the red-black tree or perform simple refactoring to make its code structure clearer. #159
  • If possible further optimize hash table performance, at least as a good polyfill.
  • Improve performance of iterators for sequential containers, especially Deque.
  • Add algorithm and awesome module.
  • Change oop to functional programming. [Refused]
  • Change ESM building target to ES6. #158

Although this is a RFC for 5.x, I think some works could be done in version 4.x.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.