178 lines
4.3 KiB
JavaScript
178 lines
4.3 KiB
JavaScript
// Copyright 2014 Cognitect. All Rights Reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS-IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
goog.provide("com.cognitect.transit.caching");
|
|
goog.require("com.cognitect.transit.delimiters");
|
|
|
|
goog.scope(function() {
|
|
|
|
var caching = com.cognitect.transit.caching,
|
|
d = com.cognitect.transit.delimiters;
|
|
|
|
/**
|
|
* @const
|
|
* @type {number}
|
|
*/
|
|
caching.MIN_SIZE_CACHEABLE = 3;
|
|
|
|
/**
|
|
* @const
|
|
* @type {number}
|
|
*/
|
|
caching.BASE_CHAR_IDX = 48;
|
|
|
|
/**
|
|
* @const
|
|
* @type {number}
|
|
*/
|
|
caching.CACHE_CODE_DIGITS = 44;
|
|
|
|
/**
|
|
* @const
|
|
* @type {number}
|
|
*/
|
|
caching.MAX_CACHE_ENTRIES = caching.CACHE_CODE_DIGITS*caching.CACHE_CODE_DIGITS;
|
|
|
|
/**
|
|
* @const
|
|
* @type {number}
|
|
*/
|
|
caching.MAX_CACHE_SIZE = 4096;
|
|
|
|
caching.isCacheable = function(string, asMapKey) {
|
|
if(string.length > caching.MIN_SIZE_CACHEABLE) {
|
|
if(asMapKey) {
|
|
return true;
|
|
} else {
|
|
var c0 = string.charAt(0),
|
|
c1 = string.charAt(1);
|
|
if(c0 === d.ESC) {
|
|
return c1 === ":" || c1 === "$" || c1 === "#";
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
};
|
|
|
|
// =============================================================================
|
|
// WriteCache
|
|
|
|
caching.idxToCode = function(idx) {
|
|
var hi = Math.floor(idx / caching.CACHE_CODE_DIGITS),
|
|
lo = idx % caching.CACHE_CODE_DIGITS,
|
|
loc = String.fromCharCode(lo + caching.BASE_CHAR_IDX)
|
|
if(hi === 0) {
|
|
return d.SUB + loc;
|
|
} else {
|
|
return d.SUB + String.fromCharCode(hi + caching.BASE_CHAR_IDX) + loc;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @constructor
|
|
*/
|
|
caching.WriteCache = function() {
|
|
this.idx = 0;
|
|
this.gen = 0;
|
|
this.cacheSize = 0;
|
|
this.cache = {};
|
|
};
|
|
|
|
caching.WriteCache.prototype.write = function(string, asMapKey) {
|
|
if(caching.isCacheable(string, asMapKey)) {
|
|
if(this.cacheSize === caching.MAX_CACHE_SIZE) {
|
|
this.clear();
|
|
this.gen = 0;
|
|
this.cache = {};
|
|
} else if(this.idx === caching.MAX_CACHE_ENTRIES) {
|
|
this.clear();
|
|
}
|
|
var entry = this.cache[string];
|
|
if(entry == null) {
|
|
this.cache[string] = [caching.idxToCode(this.idx), this.gen];
|
|
this.idx++;
|
|
return string;
|
|
} else if(entry[1] != this.gen) {
|
|
entry[1] = this.gen;
|
|
entry[0] = caching.idxToCode(this.idx);
|
|
this.idx++;
|
|
return string;
|
|
} else {
|
|
return entry[0];
|
|
}
|
|
} else {
|
|
return string;
|
|
}
|
|
};
|
|
|
|
caching.WriteCache.prototype.clear = function Transit$WriteCache() {
|
|
this.idx = 0;
|
|
this.gen++;
|
|
};
|
|
|
|
caching.writeCache = function() {
|
|
return new caching.WriteCache();
|
|
};
|
|
|
|
// =============================================================================
|
|
// ReadCache
|
|
|
|
caching.isCacheCode = function(string) {
|
|
return (string.charAt(0) === d.SUB) && (string.charAt(1) !== " ");
|
|
};
|
|
|
|
caching.codeToIdx = function(code) {
|
|
if(code.length === 2) {
|
|
return code.charCodeAt(1) - caching.BASE_CHAR_IDX;
|
|
} else {
|
|
var hi = (code.charCodeAt(1) - caching.BASE_CHAR_IDX) * caching.CACHE_CODE_DIGITS,
|
|
lo = (code.charCodeAt(2) - caching.BASE_CHAR_IDX);
|
|
return hi + lo;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @constructor
|
|
*/
|
|
caching.ReadCache = function Transit$ReadCache() {
|
|
this.idx = 0;
|
|
this.cache = [];
|
|
};
|
|
|
|
caching.ReadCache.prototype.write = function(obj, asMapKey) {
|
|
if(this.idx == caching.MAX_CACHE_ENTRIES) {
|
|
this.idx = 0;
|
|
}
|
|
this.cache[this.idx] = obj;
|
|
this.idx++;
|
|
return obj;
|
|
};
|
|
|
|
caching.ReadCache.prototype.read = function(string, asMapKey) {
|
|
return this.cache[caching.codeToIdx(string)];
|
|
};
|
|
|
|
caching.ReadCache.prototype.clear = function() {
|
|
this.idx = 0;
|
|
};
|
|
|
|
caching.readCache = function() {
|
|
return new caching.ReadCache();
|
|
};
|
|
|
|
});
|