2015-02-10 16:39:50 -08:00
; ( function ( ) {
// Note: For maximum-speed code, see "Optimizing Code" on the Emscripten wiki, https://github.com/kripken/emscripten/wiki/Optimizing-Code
// Note: Some Emscripten settings may limit the speed of the generated code.
try {
this [ 'Module' ] = Module ;
Module . test ;
} catch ( e ) {
this [ 'Module' ] = Module = { } ;
}
// The environment setup code below is customized to use Module.
// *** Environment setup code ***
var ENVIRONMENT _IS _NODE = typeof process === 'object' && typeof require === 'function' ;
var ENVIRONMENT _IS _WEB = typeof window === 'object' ;
var ENVIRONMENT _IS _WORKER = typeof importScripts === 'function' ;
var ENVIRONMENT _IS _SHELL = ! ENVIRONMENT _IS _WEB && ! ENVIRONMENT _IS _NODE && ! ENVIRONMENT _IS _WORKER ;
if ( typeof module === "object" ) {
module . exports = Module ;
}
if ( ENVIRONMENT _IS _NODE ) {
// Expose functionality in the same simple way that the shells work
// Note that we pollute the global namespace here, otherwise we break in node
Module [ 'print' ] = function ( x ) {
process [ 'stdout' ] . write ( x + '\n' ) ;
} ;
Module [ 'printErr' ] = function ( x ) {
process [ 'stderr' ] . write ( x + '\n' ) ;
} ;
var nodeFS = require ( 'fs' ) ;
var nodePath = require ( 'path' ) ;
Module [ 'read' ] = function ( filename , binary ) {
filename = nodePath [ 'normalize' ] ( filename ) ;
var ret = nodeFS [ 'readFileSync' ] ( filename ) ;
// The path is absolute if the normalized version is the same as the resolved.
if ( ! ret && filename != nodePath [ 'resolve' ] ( filename ) ) {
filename = path . join ( _ _dirname , '..' , 'src' , filename ) ;
ret = nodeFS [ 'readFileSync' ] ( filename ) ;
}
if ( ret && ! binary ) ret = ret . toString ( ) ;
return ret ;
} ;
Module [ 'readBinary' ] = function ( filename ) { return Module [ 'read' ] ( filename , true ) } ;
Module [ 'load' ] = function ( f ) {
globalEval ( read ( f ) ) ;
} ;
if ( ! Module [ 'arguments' ] ) {
Module [ 'arguments' ] = process [ 'argv' ] . slice ( 2 ) ;
}
}
if ( ENVIRONMENT _IS _SHELL ) {
Module [ 'print' ] = print ;
if ( typeof printErr != 'undefined' ) Module [ 'printErr' ] = printErr ; // not present in v8 or older sm
Module [ 'read' ] = read ;
Module [ 'readBinary' ] = function ( f ) {
return read ( f , 'binary' ) ;
} ;
if ( ! Module [ 'arguments' ] ) {
if ( typeof scriptArgs != 'undefined' ) {
Module [ 'arguments' ] = scriptArgs ;
} else if ( typeof arguments != 'undefined' ) {
Module [ 'arguments' ] = arguments ;
}
}
}
if ( ENVIRONMENT _IS _WEB && ! ENVIRONMENT _IS _WORKER ) {
if ( ! Module [ 'print' ] ) {
Module [ 'print' ] = function ( x ) {
console . log ( x ) ;
} ;
}
if ( ! Module [ 'printErr' ] ) {
Module [ 'printErr' ] = function ( x ) {
console . log ( x ) ;
} ;
}
}
if ( ENVIRONMENT _IS _WEB || ENVIRONMENT _IS _WORKER ) {
Module [ 'read' ] = function ( url ) {
var xhr = new XMLHttpRequest ( ) ;
xhr . open ( 'GET' , url , false ) ;
xhr . send ( null ) ;
return xhr . responseText ;
} ;
if ( ! Module [ 'arguments' ] ) {
if ( typeof arguments != 'undefined' ) {
Module [ 'arguments' ] = arguments ;
}
}
}
if ( ENVIRONMENT _IS _WORKER ) {
// We can do very little here...
var TRY _USE _DUMP = false ;
if ( ! Module [ 'print' ] ) {
Module [ 'print' ] = ( TRY _USE _DUMP && ( typeof ( dump ) !== "undefined" ) ? ( function ( x ) {
dump ( x ) ;
} ) : ( function ( x ) {
// self.postMessage(x); // enable this if you want stdout to be sent as messages
} ) ) ;
}
Module [ 'load' ] = importScripts ;
}
if ( ! ENVIRONMENT _IS _WORKER && ! ENVIRONMENT _IS _WEB && ! ENVIRONMENT _IS _NODE && ! ENVIRONMENT _IS _SHELL ) {
// Unreachable because SHELL is dependant on the others
throw 'Unknown runtime environment. Where are we?' ;
}
function globalEval ( x ) {
eval . call ( null , x ) ;
}
if ( ! Module [ 'load' ] == 'undefined' && Module [ 'read' ] ) {
Module [ 'load' ] = function ( f ) {
globalEval ( Module [ 'read' ] ( f ) ) ;
} ;
}
if ( ! Module [ 'print' ] ) {
Module [ 'print' ] = function ( ) { } ;
}
if ( ! Module [ 'printErr' ] ) {
Module [ 'printErr' ] = Module [ 'print' ] ;
}
if ( ! Module [ 'arguments' ] ) {
Module [ 'arguments' ] = [ ] ;
}
// *** Environment setup code ***
// Closure helpers
Module . print = Module [ 'print' ] ;
Module . printErr = Module [ 'printErr' ] ;
// Callbacks
if ( ! Module [ 'preRun' ] ) Module [ 'preRun' ] = [ ] ;
if ( ! Module [ 'postRun' ] ) Module [ 'postRun' ] = [ ] ;
// === Auto-generated preamble library stuff ===
//========================================
// Runtime code shared with compiler
//========================================
var Runtime = {
stackSave : function ( ) {
return STACKTOP ;
} ,
stackRestore : function ( stackTop ) {
STACKTOP = stackTop ;
} ,
forceAlign : function ( target , quantum ) {
quantum = quantum || 4 ;
if ( quantum == 1 ) return target ;
if ( isNumber ( target ) && isNumber ( quantum ) ) {
return Math . ceil ( target / quantum ) * quantum ;
} else if ( isNumber ( quantum ) && isPowerOfTwo ( quantum ) ) {
var logg = log2 ( quantum ) ;
return '((((' + target + ')+' + ( quantum - 1 ) + ')>>' + logg + ')<<' + logg + ')' ;
}
return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum ;
} ,
isNumberType : function ( type ) {
return type in Runtime . INT _TYPES || type in Runtime . FLOAT _TYPES ;
} ,
isPointerType : function isPointerType ( type ) {
return type [ type . length - 1 ] == '*' ;
} ,
isStructType : function isStructType ( type ) {
if ( isPointerType ( type ) ) return false ;
if ( isArrayType ( type ) ) return true ;
if ( /<?{ ?[^}]* ?}>?/ . test ( type ) ) return true ; // { i32, i8 } etc. - anonymous struct types
// See comment in isStructPointerType()
return type [ 0 ] == '%' ;
} ,
INT _TYPES : { "i1" : 0 , "i8" : 0 , "i16" : 0 , "i32" : 0 , "i64" : 0 } ,
FLOAT _TYPES : { "float" : 0 , "double" : 0 } ,
or64 : function ( x , y ) {
var l = ( x | 0 ) | ( y | 0 ) ;
var h = ( Math . round ( x / 4294967296 ) | Math . round ( y / 4294967296 ) ) * 4294967296 ;
return l + h ;
} ,
and64 : function ( x , y ) {
var l = ( x | 0 ) & ( y | 0 ) ;
var h = ( Math . round ( x / 4294967296 ) & Math . round ( y / 4294967296 ) ) * 4294967296 ;
return l + h ;
} ,
xor64 : function ( x , y ) {
var l = ( x | 0 ) ^ ( y | 0 ) ;
var h = ( Math . round ( x / 4294967296 ) ^ Math . round ( y / 4294967296 ) ) * 4294967296 ;
return l + h ;
} ,
getNativeTypeSize : function ( type , quantumSize ) {
if ( Runtime . QUANTUM _SIZE == 1 ) return 1 ;
var size = {
'%i1' : 1 ,
'%i8' : 1 ,
'%i16' : 2 ,
'%i32' : 4 ,
'%i64' : 8 ,
"%float" : 4 ,
"%double" : 8
} [ '%' + type ] ; // add '%' since float and double confuse Closure compiler as keys, and also spidermonkey as a compiler will remove 's from '_i8' etc
if ( ! size ) {
if ( type . charAt ( type . length - 1 ) == '*' ) {
size = Runtime . QUANTUM _SIZE ; // A pointer
} else if ( type [ 0 ] == 'i' ) {
var bits = parseInt ( type . substr ( 1 ) ) ;
assert ( bits % 8 == 0 ) ;
size = bits / 8 ;
}
}
return size ;
} ,
getNativeFieldSize : function ( type ) {
return Math . max ( Runtime . getNativeTypeSize ( type ) , Runtime . QUANTUM _SIZE ) ;
} ,
dedup : function dedup ( items , ident ) {
var seen = { } ;
if ( ident ) {
return items . filter ( function ( item ) {
if ( seen [ item [ ident ] ] ) return false ;
seen [ item [ ident ] ] = true ;
return true ;
} ) ;
} else {
return items . filter ( function ( item ) {
if ( seen [ item ] ) return false ;
seen [ item ] = true ;
return true ;
} ) ;
}
} ,
set : function set ( ) {
var args = typeof arguments [ 0 ] === 'object' ? arguments [ 0 ] : arguments ;
var ret = { } ;
for ( var i = 0 ; i < args . length ; i ++ ) {
ret [ args [ i ] ] = 0 ;
}
return ret ;
} ,
STACK _ALIGN : 8 ,
getAlignSize : function ( type , size , vararg ) {
// we align i64s and doubles on 64-bit boundaries, unlike x86
if ( type == 'i64' || type == 'double' || vararg ) return 8 ;
if ( ! type ) return Math . min ( size , 8 ) ; // align structures internally to 64 bits
return Math . min ( size || ( type ? Runtime . getNativeFieldSize ( type ) : 0 ) , Runtime . QUANTUM _SIZE ) ;
} ,
calculateStructAlignment : function calculateStructAlignment ( type ) {
type . flatSize = 0 ;
type . alignSize = 0 ;
var diffs = [ ] ;
var prev = - 1 ;
type . flatIndexes = type . fields . map ( function ( field ) {
var size , alignSize ;
if ( Runtime . isNumberType ( field ) || Runtime . isPointerType ( field ) ) {
size = Runtime . getNativeTypeSize ( field ) ; // pack char; char; in structs, also char[X]s.
alignSize = Runtime . getAlignSize ( field , size ) ;
} else if ( Runtime . isStructType ( field ) ) {
size = Types . types [ field ] . flatSize ;
alignSize = Runtime . getAlignSize ( null , Types . types [ field ] . alignSize ) ;
} else if ( field [ 0 ] == 'b' ) {
// bN, large number field, like a [N x i8]
size = field . substr ( 1 ) | 0 ;
alignSize = 1 ;
} else {
throw 'Unclear type in struct: ' + field + ', in ' + type . name _ + ' :: ' + dump ( Types . types [ type . name _ ] ) ;
}
if ( type . packed ) alignSize = 1 ;
type . alignSize = Math . max ( type . alignSize , alignSize ) ;
var curr = Runtime . alignMemory ( type . flatSize , alignSize ) ; // if necessary, place this on aligned memory
type . flatSize = curr + size ;
if ( prev >= 0 ) {
diffs . push ( curr - prev ) ;
}
prev = curr ;
return curr ;
} ) ;
type . flatSize = Runtime . alignMemory ( type . flatSize , type . alignSize ) ;
if ( diffs . length == 0 ) {
type . flatFactor = type . flatSize ;
} else if ( Runtime . dedup ( diffs ) . length == 1 ) {
type . flatFactor = diffs [ 0 ] ;
}
type . needsFlattening = ( type . flatFactor != 1 ) ;
return type . flatIndexes ;
} ,
generateStructInfo : function ( struct , typeName , offset ) {
var type , alignment ;
if ( typeName ) {
offset = offset || 0 ;
type = ( typeof Types === 'undefined' ? Runtime . typeInfo : Types . types ) [ typeName ] ;
if ( ! type ) return null ;
if ( type . fields . length != struct . length ) {
printErr ( 'Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo' ) ;
return null ;
}
alignment = type . flatIndexes ;
} else {
var type = { fields : struct . map ( function ( item ) { return item [ 0 ] } ) } ;
alignment = Runtime . calculateStructAlignment ( type ) ;
}
var ret = {
_ _size _ _ : type . flatSize
} ;
if ( typeName ) {
struct . forEach ( function ( item , i ) {
if ( typeof item === 'string' ) {
ret [ item ] = alignment [ i ] + offset ;
} else {
// embedded struct
var key ;
for ( var k in item ) key = k ;
ret [ key ] = Runtime . generateStructInfo ( item [ key ] , type . fields [ i ] , alignment [ i ] ) ;
}
} ) ;
} else {
struct . forEach ( function ( item , i ) {
ret [ item [ 1 ] ] = alignment [ i ] ;
} ) ;
}
return ret ;
} ,
dynCall : function ( sig , ptr , args ) {
if ( args && args . length ) {
if ( ! args . splice ) args = Array . prototype . slice . call ( args ) ;
args . splice ( 0 , 0 , ptr ) ;
return Module [ 'dynCall_' + sig ] . apply ( null , args ) ;
} else {
return Module [ 'dynCall_' + sig ] . call ( null , ptr ) ;
}
} ,
functionPointers : [ ] ,
addFunction : function ( func ) {
for ( var i = 0 ; i < Runtime . functionPointers . length ; i ++ ) {
if ( ! Runtime . functionPointers [ i ] ) {
Runtime . functionPointers [ i ] = func ;
return 2 + 2 * i ;
}
}
throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.' ;
} ,
removeFunction : function ( index ) {
Runtime . functionPointers [ ( index - 2 ) / 2 ] = null ;
} ,
warnOnce : function ( text ) {
if ( ! Runtime . warnOnce . shown ) Runtime . warnOnce . shown = { } ;
if ( ! Runtime . warnOnce . shown [ text ] ) {
Runtime . warnOnce . shown [ text ] = 1 ;
Module . printErr ( text ) ;
}
} ,
funcWrappers : { } ,
getFuncWrapper : function ( func , sig ) {
assert ( sig ) ;
if ( ! Runtime . funcWrappers [ func ] ) {
Runtime . funcWrappers [ func ] = function ( ) {
return Runtime . dynCall ( sig , func , arguments ) ;
} ;
}
return Runtime . funcWrappers [ func ] ;
} ,
UTF8Processor : function ( ) {
var buffer = [ ] ;
var needed = 0 ;
this . processCChar = function ( code ) {
code = code & 0xff ;
if ( needed ) {
buffer . push ( code ) ;
needed -- ;
}
if ( buffer . length == 0 ) {
if ( code < 128 ) return String . fromCharCode ( code ) ;
buffer . push ( code ) ;
if ( code > 191 && code < 224 ) {
needed = 1 ;
} else {
needed = 2 ;
}
return '' ;
}
if ( needed > 0 ) return '' ;
var c1 = buffer [ 0 ] ;
var c2 = buffer [ 1 ] ;
var c3 = buffer [ 2 ] ;
var ret ;
if ( c1 > 191 && c1 < 224 ) {
ret = String . fromCharCode ( ( ( c1 & 31 ) << 6 ) | ( c2 & 63 ) ) ;
} else {
ret = String . fromCharCode ( ( ( c1 & 15 ) << 12 ) | ( ( c2 & 63 ) << 6 ) | ( c3 & 63 ) ) ;
}
buffer . length = 0 ;
return ret ;
}
this . processJSString = function ( string ) {
string = unescape ( encodeURIComponent ( string ) ) ;
var ret = [ ] ;
for ( var i = 0 ; i < string . length ; i ++ ) {
ret . push ( string . charCodeAt ( i ) ) ;
}
return ret ;
}
} ,
stackAlloc : function ( size ) { var ret = STACKTOP ; STACKTOP = ( STACKTOP + size ) | 0 ; STACKTOP = ( ( ( ( STACKTOP ) + 7 ) >> 3 ) << 3 ) ; return ret ; } ,
staticAlloc : function ( size ) { var ret = STATICTOP ; STATICTOP = ( STATICTOP + size ) | 0 ; STATICTOP = ( ( ( ( STATICTOP ) + 7 ) >> 3 ) << 3 ) ; return ret ; } ,
dynamicAlloc : function ( size ) { var ret = DYNAMICTOP ; DYNAMICTOP = ( DYNAMICTOP + size ) | 0 ; DYNAMICTOP = ( ( ( ( DYNAMICTOP ) + 7 ) >> 3 ) << 3 ) ; if ( DYNAMICTOP >= TOTAL _MEMORY ) enlargeMemory ( ) ; ; return ret ; } ,
alignMemory : function ( size , quantum ) { var ret = size = Math . ceil ( ( size ) / ( quantum ? quantum : 8 ) ) * ( quantum ? quantum : 8 ) ; return ret ; } ,
makeBigInt : function ( low , high , unsigned ) { var ret = ( unsigned ? ( ( + ( ( ( low ) >>> ( 0 ) ) ) ) + ( ( + ( ( ( high ) >>> ( 0 ) ) ) ) * ( + ( 4294967296 ) ) ) ) : ( ( + ( ( ( low ) >>> ( 0 ) ) ) ) + ( ( + ( ( ( high ) | ( 0 ) ) ) ) * ( + ( 4294967296 ) ) ) ) ) ; return ret ; } ,
GLOBAL _BASE : 8 ,
QUANTUM _SIZE : 4 ,
_ _dummy _ _ : 0
}
//========================================
// Runtime essentials
//========================================
var _ _THREW _ _ = 0 ; // Used in checking for thrown exceptions.
var ABORT = false ; // whether we are quitting the application. no code should run after this. set in exit() and abort()
var undef = 0 ;
// tempInt is used for 32-bit signed values or smaller. tempBigInt is used
// for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt
var tempValue , tempInt , tempBigInt , tempInt2 , tempBigInt2 , tempPair , tempBigIntI , tempBigIntR , tempBigIntS , tempBigIntP , tempBigIntD ;
var tempI64 , tempI64b ;
var tempRet0 , tempRet1 , tempRet2 , tempRet3 , tempRet4 , tempRet5 , tempRet6 , tempRet7 , tempRet8 , tempRet9 ;
function abort ( text ) {
Module . print ( text + ':\n' + ( new Error ) . stack ) ;
ABORT = true ;
throw "Assertion: " + text ;
}
function assert ( condition , text ) {
if ( ! condition ) {
abort ( 'Assertion failed: ' + text ) ;
}
}
var globalScope = this ;
// C calling interface. A convenient way to call C functions (in C files, or
// defined with extern "C").
//
// Note: LLVM optimizations can inline and remove functions, after which you will not be
// able to call them. Closure can also do so. To avoid that, add your function to
// the exports using something like
//
// -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]'
//
// @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C")
// @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and
// 'array' for JavaScript arrays and typed arrays).
// @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType,
// except that 'array' is not possible (there is no way for us to know the length of the array)
// @param args An array of the arguments to the function, as native JS values (as in returnType)
// Note that string arguments will be stored on the stack (the JS string will become a C string on the stack).
// @return The return value, as a native JS value (as in returnType)
function ccall ( ident , returnType , argTypes , args ) {
return ccallFunc ( getCFunc ( ident ) , returnType , argTypes , args ) ;
}
Module [ "ccall" ] = ccall ;
// Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
function getCFunc ( ident ) {
try {
var func = globalScope [ 'Module' ] [ '_' + ident ] ; // closure exported function
if ( ! func ) func = eval ( '_' + ident ) ; // explicit lookup
} catch ( e ) {
}
assert ( func , 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)' ) ;
return func ;
}
// Internal function that does a C call using a function, not an identifier
function ccallFunc ( func , returnType , argTypes , args ) {
var stack = 0 ;
function toC ( value , type ) {
if ( type == 'string' ) {
if ( value === null || value === undefined || value === 0 ) return 0 ; // null string
if ( ! stack ) stack = Runtime . stackSave ( ) ;
var ret = Runtime . stackAlloc ( value . length + 1 ) ;
writeStringToMemory ( value , ret ) ;
return ret ;
} else if ( type == 'array' ) {
if ( ! stack ) stack = Runtime . stackSave ( ) ;
var ret = Runtime . stackAlloc ( value . length ) ;
writeArrayToMemory ( value , ret ) ;
return ret ;
}
return value ;
}
function fromC ( value , type ) {
if ( type == 'string' ) {
return Pointer _stringify ( value ) ;
}
assert ( type != 'array' ) ;
return value ;
}
var i = 0 ;
var cArgs = args ? args . map ( function ( arg ) {
return toC ( arg , argTypes [ i ++ ] ) ;
} ) : [ ] ;
var ret = fromC ( func . apply ( null , cArgs ) , returnType ) ;
if ( stack ) Runtime . stackRestore ( stack ) ;
return ret ;
}
// Returns a native JS wrapper for a C function. This is similar to ccall, but
// returns a function you can call repeatedly in a normal way. For example:
//
// var my_function = cwrap('my_c_function', 'number', ['number', 'number']);
// alert(my_function(5, 22));
// alert(my_function(99, 12));
//
function cwrap ( ident , returnType , argTypes ) {
var func = getCFunc ( ident ) ;
return function ( ) {
return ccallFunc ( func , returnType , argTypes , Array . prototype . slice . call ( arguments ) ) ;
}
}
Module [ "cwrap" ] = cwrap ;
// Sets a value in memory in a dynamic way at run-time. Uses the
// type data. This is the same as makeSetValue, except that
// makeSetValue is done at compile-time and generates the needed
// code then, whereas this function picks the right code at
// run-time.
// Note that setValue and getValue only do *aligned* writes and reads!
// Note that ccall uses JS types as for defining types, while setValue and
// getValue need LLVM types ('i8', 'i32') - this is a lower-level operation
function setValue ( ptr , value , type , noSafe ) {
type = type || 'i8' ;
if ( type . charAt ( type . length - 1 ) === '*' ) type = 'i32' ; // pointers are 32-bit
switch ( type ) {
case 'i1' : HEAP8 [ ( ptr ) ] = value ; break ;
case 'i8' : HEAP8 [ ( ptr ) ] = value ; break ;
case 'i16' : HEAP16 [ ( ( ptr ) >> 1 ) ] = value ; break ;
case 'i32' : HEAP32 [ ( ( ptr ) >> 2 ) ] = value ; break ;
case 'i64' : ( tempI64 = [ value >>> 0 , Math . min ( Math . floor ( ( value ) / ( + ( 4294967296 ) ) ) , ( + ( 4294967295 ) ) ) >>> 0 ] , HEAP32 [ ( ( ptr ) >> 2 ) ] = tempI64 [ 0 ] , HEAP32 [ ( ( ( ptr ) + ( 4 ) ) >> 2 ) ] = tempI64 [ 1 ] ) ; break ;
case 'float' : HEAPF32 [ ( ( ptr ) >> 2 ) ] = value ; break ;
case 'double' : HEAPF64 [ ( ( ptr ) >> 3 ) ] = value ; break ;
default : abort ( 'invalid type for setValue: ' + type ) ;
}
}
Module [ 'setValue' ] = setValue ;
// Parallel to setValue.
function getValue ( ptr , type , noSafe ) {
type = type || 'i8' ;
if ( type . charAt ( type . length - 1 ) === '*' ) type = 'i32' ; // pointers are 32-bit
switch ( type ) {
case 'i1' : return HEAP8 [ ( ptr ) ] ;
case 'i8' : return HEAP8 [ ( ptr ) ] ;
case 'i16' : return HEAP16 [ ( ( ptr ) >> 1 ) ] ;
case 'i32' : return HEAP32 [ ( ( ptr ) >> 2 ) ] ;
case 'i64' : return HEAP32 [ ( ( ptr ) >> 2 ) ] ;
case 'float' : return HEAPF32 [ ( ( ptr ) >> 2 ) ] ;
case 'double' : return HEAPF64 [ ( ( ptr ) >> 3 ) ] ;
default : abort ( 'invalid type for setValue: ' + type ) ;
}
return null ;
}
Module [ 'getValue' ] = getValue ;
var ALLOC _NORMAL = 0 ; // Tries to use _malloc()
var ALLOC _STACK = 1 ; // Lives for the duration of the current function call
var ALLOC _STATIC = 2 ; // Cannot be freed
var ALLOC _DYNAMIC = 3 ; // Cannot be freed except through sbrk
var ALLOC _NONE = 4 ; // Do not allocate
Module [ 'ALLOC_NORMAL' ] = ALLOC _NORMAL ;
Module [ 'ALLOC_STACK' ] = ALLOC _STACK ;
Module [ 'ALLOC_STATIC' ] = ALLOC _STATIC ;
Module [ 'ALLOC_DYNAMIC' ] = ALLOC _DYNAMIC ;
Module [ 'ALLOC_NONE' ] = ALLOC _NONE ;
// allocate(): This is for internal use. You can use it yourself as well, but the interface
// is a little tricky (see docs right below). The reason is that it is optimized
// for multiple syntaxes to save space in generated code. So you should
// normally not use allocate(), and instead allocate memory using _malloc(),
// initialize it with setValue(), and so forth.
// @slab: An array of data, or a number. If a number, then the size of the block to allocate,
// in *bytes* (note that this is sometimes confusing: the next parameter does not
// affect this!)
// @types: Either an array of types, one for each byte (or 0 if no type at that position),
// or a single type which is used for the entire block. This only matters if there
// is initial data - if @slab is a number, then this does not matter at all and is
// ignored.
// @allocator: How to allocate memory, see ALLOC_*
function allocate ( slab , types , allocator , ptr ) {
var zeroinit , size ;
if ( typeof slab === 'number' ) {
zeroinit = true ;
size = slab ;
} else {
zeroinit = false ;
size = slab . length ;
}
var singleType = typeof types === 'string' ? types : null ;
var ret ;
if ( allocator == ALLOC _NONE ) {
ret = ptr ;
} else {
ret = [ _malloc , Runtime . stackAlloc , Runtime . staticAlloc , Runtime . dynamicAlloc ] [ allocator === undefined ? ALLOC _STATIC : allocator ] ( Math . max ( size , singleType ? 1 : types . length ) ) ;
}
if ( zeroinit ) {
var ptr = ret , stop ;
assert ( ( ret & 3 ) == 0 ) ;
stop = ret + ( size & ~ 3 ) ;
for ( ; ptr < stop ; ptr += 4 ) {
HEAP32 [ ( ( ptr ) >> 2 ) ] = 0 ;
}
stop = ret + size ;
while ( ptr < stop ) {
HEAP8 [ ( ( ptr ++ ) | 0 ) ] = 0 ;
}
return ret ;
}
if ( singleType === 'i8' ) {
if ( slab . subarray || slab . slice ) {
HEAPU8 . set ( slab , ret ) ;
} else {
HEAPU8 . set ( new Uint8Array ( slab ) , ret ) ;
}
return ret ;
}
var i = 0 , type , typeSize , previousType ;
while ( i < size ) {
var curr = slab [ i ] ;
if ( typeof curr === 'function' ) {
curr = Runtime . getFunctionIndex ( curr ) ;
}
type = singleType || types [ i ] ;
if ( type === 0 ) {
i ++ ;
continue ;
}
if ( type == 'i64' ) type = 'i32' ; // special case: we have one i32 here, and one i32 later
setValue ( ret + i , curr , type ) ;
// no need to look up size unless type changes, so cache it
if ( previousType !== type ) {
typeSize = Runtime . getNativeTypeSize ( type ) ;
previousType = type ;
}
i += typeSize ;
}
return ret ;
}
Module [ 'allocate' ] = allocate ;
function Pointer _stringify ( ptr , /* optional */ length ) {
// Find the length, and check for UTF while doing so
var hasUtf = false ;
var t ;
var i = 0 ;
while ( 1 ) {
t = HEAPU8 [ ( ( ( ptr ) + ( i ) ) | 0 ) ] ;
if ( t >= 128 ) hasUtf = true ;
else if ( t == 0 && ! length ) break ;
i ++ ;
if ( length && i == length ) break ;
}
if ( ! length ) length = i ;
var ret = '' ;
if ( ! hasUtf ) {
var MAX _CHUNK = 1024 ; // split up into chunks, because .apply on a huge string can overflow the stack
var curr ;
while ( length > 0 ) {
curr = String . fromCharCode . apply ( String , HEAPU8 . subarray ( ptr , ptr + Math . min ( length , MAX _CHUNK ) ) ) ;
ret = ret ? ret + curr : curr ;
ptr += MAX _CHUNK ;
length -= MAX _CHUNK ;
}
return ret ;
}
var utf8 = new Runtime . UTF8Processor ( ) ;
for ( i = 0 ; i < length ; i ++ ) {
t = HEAPU8 [ ( ( ( ptr ) + ( i ) ) | 0 ) ] ;
ret += utf8 . processCChar ( t ) ;
}
return ret ;
}
Module [ 'Pointer_stringify' ] = Pointer _stringify ;
// Memory management
var PAGE _SIZE = 4096 ;
function alignMemoryPage ( x ) {
return ( ( x + 4095 ) >> 12 ) << 12 ;
}
var HEAP ;
var HEAP8 , HEAPU8 , HEAP16 , HEAPU16 , HEAP32 , HEAPU32 , HEAPF32 , HEAPF64 ;
var STATIC _BASE = 0 , STATICTOP = 0 , staticSealed = false ; // static area
var STACK _BASE = 0 , STACKTOP = 0 , STACK _MAX = 0 ; // stack area
var DYNAMIC _BASE = 0 , DYNAMICTOP = 0 ; // dynamic area handled by sbrk
function enlargeMemory ( ) {
abort ( 'Cannot enlarge memory arrays in asm.js. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value, or (2) set Module.TOTAL_MEMORY before the program runs.' ) ;
}
var TOTAL _STACK = Module [ 'TOTAL_STACK' ] || 5242880 ;
var TOTAL _MEMORY = Module [ 'TOTAL_MEMORY' ] || 16777216 ;
var FAST _MEMORY = Module [ 'FAST_MEMORY' ] || 2097152 ;
// Initialize the runtime's memory
// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
assert ( ! ! Int32Array && ! ! Float64Array && ! ! ( new Int32Array ( 1 ) [ 'subarray' ] ) && ! ! ( new Int32Array ( 1 ) [ 'set' ] ) ,
'Cannot fallback to non-typed array case: Code is too specialized' ) ;
var buffer = new ArrayBuffer ( TOTAL _MEMORY ) ;
HEAP8 = new Int8Array ( buffer ) ;
HEAP16 = new Int16Array ( buffer ) ;
HEAP32 = new Int32Array ( buffer ) ;
HEAPU8 = new Uint8Array ( buffer ) ;
HEAPU16 = new Uint16Array ( buffer ) ;
HEAPU32 = new Uint32Array ( buffer ) ;
HEAPF32 = new Float32Array ( buffer ) ;
HEAPF64 = new Float64Array ( buffer ) ;
// Endianness check (note: assumes compiler arch was little-endian)
HEAP32 [ 0 ] = 255 ;
assert ( HEAPU8 [ 0 ] === 255 && HEAPU8 [ 3 ] === 0 , 'Typed arrays 2 must be run on a little-endian system' ) ;
Module [ 'HEAP' ] = HEAP ;
Module [ 'HEAP8' ] = HEAP8 ;
Module [ 'HEAP16' ] = HEAP16 ;
Module [ 'HEAP32' ] = HEAP32 ;
Module [ 'HEAPU8' ] = HEAPU8 ;
Module [ 'HEAPU16' ] = HEAPU16 ;
Module [ 'HEAPU32' ] = HEAPU32 ;
Module [ 'HEAPF32' ] = HEAPF32 ;
Module [ 'HEAPF64' ] = HEAPF64 ;
function callRuntimeCallbacks ( callbacks ) {
while ( callbacks . length > 0 ) {
var callback = callbacks . shift ( ) ;
if ( typeof callback == 'function' ) {
callback ( ) ;
continue ;
}
var func = callback . func ;
if ( typeof func === 'number' ) {
if ( callback . arg === undefined ) {
Runtime . dynCall ( 'v' , func ) ;
} else {
Runtime . dynCall ( 'vi' , func , [ callback . arg ] ) ;
}
} else {
func ( callback . arg === undefined ? null : callback . arg ) ;
}
}
}
var _ _ATINIT _ _ = [ ] ; // functions called during startup
var _ _ATMAIN _ _ = [ ] ; // functions called when main() is to be run
var _ _ATEXIT _ _ = [ ] ; // functions called during shutdown
var runtimeInitialized = false ;
function ensureInitRuntime ( ) {
if ( runtimeInitialized ) return ;
runtimeInitialized = true ;
callRuntimeCallbacks ( _ _ATINIT _ _ ) ;
}
function preMain ( ) {
callRuntimeCallbacks ( _ _ATMAIN _ _ ) ;
}
function exitRuntime ( ) {
callRuntimeCallbacks ( _ _ATEXIT _ _ ) ;
}
// Tools
// This processes a JS string into a C-line array of numbers, 0-terminated.
// For LLVM-originating strings, see parser.js:parseLLVMString function
function intArrayFromString ( stringy , dontAddNull , length /* optional */ ) {
var ret = ( new Runtime . UTF8Processor ( ) ) . processJSString ( stringy ) ;
if ( length ) {
ret . length = length ;
}
if ( ! dontAddNull ) {
ret . push ( 0 ) ;
}
return ret ;
}
Module [ 'intArrayFromString' ] = intArrayFromString ;
function intArrayToString ( array ) {
var ret = [ ] ;
for ( var i = 0 ; i < array . length ; i ++ ) {
var chr = array [ i ] ;
if ( chr > 0xFF ) {
chr &= 0xFF ;
}
ret . push ( String . fromCharCode ( chr ) ) ;
}
return ret . join ( '' ) ;
}
Module [ 'intArrayToString' ] = intArrayToString ;
// Write a Javascript array to somewhere in the heap
function writeStringToMemory ( string , buffer , dontAddNull ) {
var array = intArrayFromString ( string , dontAddNull ) ;
var i = 0 ;
while ( i < array . length ) {
var chr = array [ i ] ;
HEAP8 [ ( ( ( buffer ) + ( i ) ) | 0 ) ] = chr
i = i + 1 ;
}
}
Module [ 'writeStringToMemory' ] = writeStringToMemory ;
function writeArrayToMemory ( array , buffer ) {
for ( var i = 0 ; i < array . length ; i ++ ) {
HEAP8 [ ( ( ( buffer ) + ( i ) ) | 0 ) ] = array [ i ] ;
}
}
Module [ 'writeArrayToMemory' ] = writeArrayToMemory ;
function unSign ( value , bits , ignore , sig ) {
if ( value >= 0 ) {
return value ;
}
return bits <= 32 ? 2 * Math . abs ( 1 << ( bits - 1 ) ) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts
: Math . pow ( 2 , bits ) + value ;
}
function reSign ( value , bits , ignore , sig ) {
if ( value <= 0 ) {
return value ;
}
var half = bits <= 32 ? Math . abs ( 1 << ( bits - 1 ) ) // abs is needed if bits == 32
: Math . pow ( 2 , bits - 1 ) ;
if ( value >= half && ( bits <= 32 || value > half ) ) { // for huge values, we can hit the precision limit and always get true here. so don't do that
// but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors
// TODO: In i64 mode 1, resign the two parts separately and safely
value = - 2 * half + value ; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
}
return value ;
}
if ( ! Math [ 'imul' ] ) Math [ 'imul' ] = function ( a , b ) {
var ah = a >>> 16 ;
var al = a & 0xffff ;
var bh = b >>> 16 ;
var bl = b & 0xffff ;
return ( al * bl + ( ( ah * bl + al * bh ) << 16 ) ) | 0 ;
} ;
// A counter of dependencies for calling run(). If we need to
// do asynchronous work before running, increment this and
// decrement it. Incrementing must happen in a place like
// PRE_RUN_ADDITIONS (used by emcc to add file preloading).
// Note that you can add dependencies in preRun, even though
// it happens right before run - run will be postponed until
// the dependencies are met.
var runDependencies = 0 ;
var runDependencyTracking = { } ;
var calledInit = false , calledRun = false ;
var runDependencyWatcher = null ;
function addRunDependency ( id ) {
runDependencies ++ ;
if ( Module [ 'monitorRunDependencies' ] ) {
Module [ 'monitorRunDependencies' ] ( runDependencies ) ;
}
if ( id ) {
assert ( ! runDependencyTracking [ id ] ) ;
runDependencyTracking [ id ] = 1 ;
} else {
Module . printErr ( 'warning: run dependency added without ID' ) ;
}
}
Module [ 'addRunDependency' ] = addRunDependency ;
function removeRunDependency ( id ) {
runDependencies -- ;
if ( Module [ 'monitorRunDependencies' ] ) {
Module [ 'monitorRunDependencies' ] ( runDependencies ) ;
}
if ( id ) {
assert ( runDependencyTracking [ id ] ) ;
delete runDependencyTracking [ id ] ;
} else {
Module . printErr ( 'warning: run dependency removed without ID' ) ;
}
if ( runDependencies == 0 ) {
if ( runDependencyWatcher !== null ) {
clearInterval ( runDependencyWatcher ) ;
runDependencyWatcher = null ;
2015-02-20 15:05:32 -08:00
}
2015-02-10 16:39:50 -08:00
// If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
if ( ! calledRun && shouldRunNow ) run ( ) ;
}
}
Module [ 'removeRunDependency' ] = removeRunDependency ;
Module [ "preloadedImages" ] = { } ; // maps url to image data
Module [ "preloadedAudios" ] = { } ; // maps url to audio data
function addPreRun ( func ) {
if ( ! Module [ 'preRun' ] ) Module [ 'preRun' ] = [ ] ;
else if ( typeof Module [ 'preRun' ] == 'function' ) Module [ 'preRun' ] = [ Module [ 'preRun' ] ] ;
Module [ 'preRun' ] . push ( func ) ;
}
var awaitingMemoryInitializer = false ;
function loadMemoryInitializer ( filename ) {
function applyData ( data ) {
HEAPU8 . set ( data , STATIC _BASE ) ;
runPostSets ( ) ;
}
// always do this asynchronously, to keep shell and web as similar as possible
addPreRun ( function ( ) {
if ( ENVIRONMENT _IS _NODE || ENVIRONMENT _IS _SHELL ) {
applyData ( Module [ 'readBinary' ] ( filename ) ) ;
} else {
Browser . asyncLoad ( filename , function ( data ) {
applyData ( data ) ;
} , function ( data ) {
throw 'could not load memory initializer ' + filename ;
} ) ;
}
} ) ;
awaitingMemoryInitializer = false ;
}
// === Body ===
STATIC _BASE = 8 ;
STATICTOP = STATIC _BASE + 32536 ;
/* memory initializer */ allocate ( [ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 176 , 160 , 14 , 254 , 211 , 201 , 134 , 255 , 158 , 24 , 143 , 0 , 127 , 105 , 53 , 0 , 96 , 12 , 189 , 0 , 167 , 215 , 251 , 255 , 159 , 76 , 128 , 254 , 106 , 101 , 225 , 255 , 30 , 252 , 4 , 0 , 146 , 12 , 174 , 0 , 89 , 241 , 178 , 254 , 10 , 229 , 166 , 255 , 123 , 221 , 42 , 254 , 30 , 20 , 212 , 0 , 82 , 128 , 3 , 0 , 48 , 209 , 243 , 0 , 119 , 121 , 64 , 255 , 50 , 227 , 156 , 255 , 0 , 110 , 197 , 1 , 103 , 27 , 144 , 0 , 182 , 120 , 89 , 255 , 133 , 114 , 211 , 0 , 189 , 110 , 21 , 255 , 15 , 10 , 106 , 0 , 41 , 192 , 1 , 0 , 152 , 232 , 121 , 255 , 188 , 60 , 160 , 255 , 153 , 113 , 206 , 255 , 0 , 183 , 226 , 254 , 180 , 13 , 72 , 255 , 133 , 59 , 140 , 1 , 189 , 241 , 36 , 255 , 248 , 37 , 195 , 1 , 96 , 220 , 55 , 0 , 183 , 76 , 62 , 255 , 195 , 66 , 61 , 0 , 50 , 76 , 164 , 1 , 225 , 164 , 76 , 255 , 76 , 61 , 163 , 255 , 117 , 62 , 31 , 0 , 81 , 145 , 64 , 255 , 118 , 65 , 14 , 0 , 162 , 115 , 214 , 255 , 6 , 138 , 46 , 0 , 124 , 230 , 244 , 255 , 10 , 138 , 143 , 0 , 52 , 26 , 194 , 0 , 184 , 244 , 76 , 0 , 129 , 143 , 41 , 1 , 190 , 244 , 19 , 255 , 123 , 170 , 122 , 255 , 98 , 129 , 68 , 0 , 121 , 213 , 147 , 0 , 86 , 101 , 30 , 255 , 161 , 103 , 155 , 0 , 140 , 89 , 67 , 255 , 239 , 229 , 190 , 1 , 67 , 11 , 181 , 0 , 198 , 240 , 137 , 254 , 238 , 69 , 188 , 255 , 234 , 113 , 60 , 255 , 37 , 255 , 57 , 255 , 69 , 178 , 182 , 254 , 128 , 208 , 179 , 0 , 118 , 26 , 125 , 254 , 3 , 7 , 214 , 255 , 241 , 50 , 77 , 255 , 85 , 203 , 197 , 255 , 211 , 135 , 250 , 255 , 25 , 48 , 100 , 255 , 187 , 213 , 180 , 254 , 17 , 88 , 105 , 0 , 83 , 209 , 158 , 1 , 5 , 115 , 98 , 0 , 4 , 174 , 60 , 254 , 171 , 55 , 110 , 255 , 217 , 181 , 17 , 255 , 20 , 188 , 170 , 0 , 146 , 156 , 102 , 254 , 87 , 214 , 174 , 255 , 114 , 122 , 155 , 1 , 233 , 44 , 170 , 0 , 127 , 8 , 239 , 1 , 214 , 236 , 234 , 0 , 175 , 5 , 219 , 0 , 49 , 106 , 61 , 255 , 6 , 66 , 208 , 255 , 2 , 106 , 110 , 255 , 81 , 234 , 19 , 255 , 215 , 107 , 192 , 255 , 67 , 151 , 238 , 0 , 19 , 42 , 108 , 255 , 229 , 85 , 113 , 1 , 50 , 68 , 135 , 255 , 17 , 106 , 9 , 0 , 50 , 103 , 1 , 255 , 80 , 1 , 168 , 1 , 35 , 152 , 30 , 255 , 16 , 168 , 185 , 1 , 56 , 89 , 232 , 255 , 101 , 210 , 252 , 0 , 41 , 250 , 71 , 0 , 204 , 170 , 79 , 255 , 14 , 46 , 239 , 255 , 80 , 77 , 239 , 0 , 189 , 214 , 75 , 255 , 17 , 141 , 249 , 0 , 38 , 80 , 76 , 255 , 190 , 85 , 117 , 0 , 86 , 228 , 170 , 0 , 156 , 216 , 208 , 1 , 195 , 207 , 164 , 255 , 150 , 66 , 76 , 255 , 175 , 225 , 16 , 255 , 141 , 80 , 98 , 1 , 76 , 219 , 242 , 0 , 198 , 162 , 114 , 0 , 46 , 218 , 152 , 0 , 155 , 43 , 241 , 254 , 155 , 160 , 104 , 255 , 178 , 9 , 252 , 254 , 100 , 110 , 212 , 0 , 14 , 5 , 167 , 0 , 233 , 239 , 163 , 255 , 28 , 151 , 157 , 1 , 101 , 146 , 10 , 255 , 254 , 158 , 70 , 254 , 71 , 249 , 228 , 0 , 88 , 30 , 50 , 0 , 68 , 58 , 160 , 255 , 191 , 24 , 104 , 1 , 129 , 66 , 129 , 255 , 192 , 50 , 85 , 255 , 8 , 179 , 138 , 255 , 38 , 250 , 201 , 0 , 115 , 80 , 160 , 0 , 131 , 230 , 113 , 0 , 125 , 88 , 147 , 0 , 90 , 68 , 199 , 0 , 253 , 76 , 158 , 0 , 28 , 255 , 118 , 0 , 113 , 250 , 254 , 0 , 66 , 75 , 46 , 0 , 230 , 218 , 43 , 0 , 229 , 120 , 186 , 1 , 148 , 68 , 43 , 0 , 136 , 124 , 238 , 1 , 187 , 107 , 197 , 255 , 84 , 53 , 246 , 255 , 51 , 116 , 254 , 255 , 51 , 187 , 165 , 0 , 2 , 17 , 175 , 0 , 66 , 84 , 160 , 1 , 247 , 58 , 30 , 0 , 35 , 65 , 53 , 254 , 69 , 236 , 191 , 0 , 45 , 134 , 245 , 1 , 163 , 123 , 221 , 0 , 32 , 110 , 20 , 255 , 52 , 23 , 165 , 0 , 186 , 214 , 71 , 0 , 233 , 176 , 96 , 0 , 242 , 239 , 54 , 1 , 57 , 89 , 138 , 0 , 83 , 0 , 84 , 255 , 136 , 160 , 100 , 0 , 92 , 142 , 120 , 254 , 104 , 124 , 190 , 0 , 181 , 177 , 62 , 255 , 250 , 41 , 85 , 0 , 152 , 130 , 42 , 1 , 96 , 252 , 246 , 0 , 151 , 151 , 63 , 254 , 239 , 133 , 62 , 0 , 32 , 56 , 156 , 0 , 45 , 167 , 189 , 255 , 142 , 133 , 179 , 1 , 131 , 86 , 211 , 0 , 187 , 179 , 150 , 254 , 250 , 170 , 14 , 255 , 68 , 113 , 21 , 255 , 222 , 186 , 59 , 255 , 66 , 7 , 241 , 1 , 69 , 6 , 72 , 0 , 86 , 156 , 108 , 254 , 55 , 167 , 89 , 0 , 109 , 52 , 219 , 254 , 13 , 176 , 23 , 255 , 196 , 44 , 106 , 255 , 239 , 149 , 71 , 255 , 164 , 140 , 125 , 255 , 159 , 173 , 1 , 0 , 51 , 41 , 231 , 0 , 145 , 62 , 33 , 0 , 138 , 111 , 93 , 1 , 185 , 83 , 69 , 0 , 144 , 115 , 46 , 0 , 97 , 151 , 16 , 255 , 24 , 228 , 26 , 0 , 49 , 217 , 226 , 0 , 113 , 75 , 234 , 254 , 193 , 153 , 12 , 255 , 182 , 48 , 96 , 255 , 14 , 13 , 26 , 0 , 128 , 195 , 249 , 254 , 69 , 193 , 59 , 0 , 132 , 37 , 81 , 254 , 125 , 106 , 60 , 0 , 214 , 240 , 169 , 1 , 164 , 227 , 66 , 0 , 210 , 163 , 78 , 0 , 37 , 52 , 151 , 0 , 99 , 77 , 26 , 0 , 238 , 156 , 213 , 255 , 213 , 192 , 209 , 1 , 73 , 46 , 84 , 0 , 20 , 65 , 41 , 1 , 54 , 206 , 79 , 0 , 201 , 131 , 146 , 254 , 170 , 111 , 24 , 255 , 177 , 33 , 50 , 254 , 171 , 38 , 203 , 255 , 78 , 247 , 116 , 0 , 209 , 221 , 153 , 0 , 133 , 128 , 178 , 1 , 58 , 44 , 25 , 0 , 201 , 39 , 59 , 1 , 189 , 19 , 252 , 0 , 49 , 229 , 210 , 1 , 117 , 187 , 117 , 0 , 181 , 179 , 184 , 1 , 0 , 114 , 219 , 0 , 48 , 94 , 147 , 0 , 245 , 41 , 56 , 0 , 125 , 13 , 204 , 254 , 244 , 173 , 119 , 0 , 44 , 221 , 32 , 254 , 84 , 234 , 20 , 0 , 249 , 160 , 198 , 1 , 236 , 126 , 234 , 255 , 143 , 62 , 221 , 0 , 129 , 89 , 214 , 255 , 55 , 139 , 5 , 254 , 68 , 20 , 191 , 255 , 14 , 204 , 178 , 1 , 35 , 195 , 217 , 0 , 47 , 51 , 206 , 1 , 38 , 246 , 165 , 0 , 206 , 27 , 6 , 254 , 158 , 87 , 36 , 0 , 217 , 52 , 146 , 255 , 125 , 123 , 215 , 255 , 85 , 60 , 31 , 255 , 171 , 13 , 7 , 0 , 218 , 245 , 88 , 254 , 252 , 35 , 60 , 0 , 55 , 214 , 160 , 255 , 133 , 101 , 56 , 0 , 224 , 32 , 19 , 254 , 147 , 64 , 234 , 0 , 26 , 145 , 162 , 1 , 114 , 118 , 125 , 0 , 248 , 252 , 250 , 0 , 101 , 94 , 196 , 255 , 198 , 141 , 226 , 254 , 51 , 42 , 182 , 0 , 135 , 12 , 9 , 254 , 109 , 172 , 210 , 255 , 197 , 236 , 194 , 1 , 241 , 65 , 154 , 0 , 48 , 156 , 47 , 255 , 153 , 67 , 55 , 255 , 218 , 165 , 34 , 254 , 74 , 180 , 179 , 0 , 218 , 66 , 71 , 1 , 88 , 122 , 99 , 0 , 212 , 181 , 219 , 255 , 92 , 42 , 231 , 255 , 239 , 0 , 154 , 0 , 245 , 77 , 183 , 255 , 94 , 81 , 170 , 1 , 18 , 213 , 216 , 0 , 171 , 93 , 71 , 0 , 52 , 94 , 248 , 0 , 18 , 151 , 161 , 254 , 197 , 209 , 66 , 255 , 174 , 244 , 15 , 254 , 162 , 48 , 183 , 0 , 49 , 61 , 240 , 254 , 182 , 93 , 195 , 0 , 199 , 228 , 6 , 1 , 200 , 5 , 17 , 255 , 137 , 45 , 237 , 255 , 108 , 148 , 4 , 0 , 90 , 79 , 23
. concat ( [ 40 , 21 , 138 , 254 , 104 , 116 , 228 , 0 , 199 , 95 , 137 , 255 , 133 , 190 , 168 , 255 , 146 , 165 , 234 , 1 , 183 , 99 , 39 , 0 , 183 , 220 , 54 , 254 , 255 , 222 , 133 , 0 , 162 , 219 , 121 , 254 , 63 , 239 , 6 , 0 , 225 , 102 , 54 , 255 , 251 , 18 , 246 , 0 , 4 , 34 , 129 , 1 , 135 , 36 , 131 , 0 , 206 , 50 , 59 , 1 , 15 , 97 , 183 , 0 , 171 , 216 , 135 , 255 , 101 , 152 , 43 , 255 , 150 , 251 , 91 , 0 , 38 , 145 , 95 , 0 , 34 , 204 , 38 , 254 , 178 , 140 , 83 , 255 , 25 , 129 , 243 , 255 , 76 , 144 , 37 , 0 , 106 , 36 , 26 , 254 , 118 , 144 , 172 , 255 , 68 , 186 , 229 , 255 , 107 , 161 , 213 , 255 , 46 , 163 , 68 , 255 , 149 , 170 , 253 , 0 , 187 , 17 , 15 , 0 , 218 , 160 , 165 , 255 , 171 , 35 , 246 , 1 , 96 , 13 , 19 , 0 , 165 , 203 , 117 , 0 , 214 , 107 , 192 , 255 , 244 , 123 , 177 , 1 , 100 , 3 , 104 , 0 , 178 , 242 , 97 , 255 , 251 , 76 , 130 , 255 , 211 , 77 , 42 , 1 , 250 , 79 , 70 , 255 , 63 , 244 , 80 , 1 , 105 , 101 , 246 , 0 , 61 , 136 , 58 , 1 , 238 , 91 , 213 , 0 , 14 , 59 , 98 , 255 , 167 , 84 , 77 , 0 , 17 , 132 , 46 , 254 , 57 , 175 , 197 , 255 , 185 , 62 , 184 , 0 , 76 , 64 , 207 , 0 , 172 , 175 , 208 , 254 , 175 , 74 , 37 , 0 , 138 , 27 , 211 , 254 , 148 , 125 , 194 , 0 , 10 , 89 , 81 , 0 , 168 , 203 , 101 , 255 , 43 , 213 , 209 , 1 , 235 , 245 , 54 , 0 , 30 , 35 , 226 , 255 , 9 , 126 , 70 , 0 , 226 , 125 , 94 , 254 , 156 , 117 , 20 , 255 , 57 , 248 , 112 , 1 , 230 , 48 , 64 , 255 , 164 , 92 , 166 , 1 , 224 , 214 , 230 , 255 , 36 , 120 , 143 , 0 , 55 , 8 , 43 , 255 , 251 , 1 , 245 , 1 , 106 , 98 , 165 , 0 , 74 , 107 , 106 , 254 , 53 , 4 , 54 , 255 , 90 , 178 , 150 , 1 , 3 , 120 , 123 , 255 , 244 , 5 , 89 , 1 , 114 , 250 , 61 , 255 , 254 , 153 , 82 , 1 , 77 , 15 , 17 , 0 , 57 , 238 , 90 , 1 , 95 , 223 , 230 , 0 , 236 , 52 , 47 , 254 , 103 , 148 , 164 , 255 , 121 , 207 , 36 , 1 , 18 , 16 , 185 , 255 , 75 , 20 , 74 , 0 , 187 , 11 , 101 , 0 , 46 , 48 , 129 , 255 , 22 , 239 , 210 , 255 , 77 , 236 , 129 , 255 , 111 , 77 , 204 , 255 , 61 , 72 , 97 , 255 , 199 , 217 , 251 , 255 , 42 , 215 , 204 , 0 , 133 , 145 , 201 , 255 , 57 , 230 , 146 , 1 , 235 , 100 , 198 , 0 , 146 , 73 , 35 , 254 , 108 , 198 , 20 , 255 , 182 , 79 , 210 , 255 , 82 , 103 , 136 , 0 , 246 , 108 , 176 , 0 , 34 , 17 , 60 , 255 , 19 , 74 , 114 , 254 , 168 , 170 , 78 , 255 , 157 , 239 , 20 , 255 , 149 , 41 , 168 , 0 , 58 , 121 , 28 , 0 , 79 , 179 , 134 , 255 , 231 , 121 , 135 , 255 , 174 , 209 , 98 , 255 , 243 , 122 , 190 , 0 , 171 , 166 , 205 , 0 , 212 , 116 , 48 , 0 , 29 , 108 , 66 , 255 , 162 , 222 , 182 , 1 , 14 , 119 , 21 , 0 , 213 , 39 , 249 , 255 , 254 , 223 , 228 , 255 , 183 , 165 , 198 , 0 , 133 , 190 , 48 , 0 , 124 , 208 , 109 , 255 , 119 , 175 , 85 , 255 , 9 , 209 , 121 , 1 , 48 , 171 , 189 , 255 , 195 , 71 , 134 , 1 , 136 , 219 , 51 , 255 , 182 , 91 , 141 , 254 , 49 , 159 , 72 , 0 , 35 , 118 , 245 , 255 , 112 , 186 , 227 , 255 , 59 , 137 , 31 , 0 , 137 , 44 , 163 , 0 , 114 , 103 , 60 , 254 , 8 , 213 , 150 , 0 , 162 , 10 , 113 , 255 , 194 , 104 , 72 , 0 , 220 , 131 , 116 , 255 , 178 , 79 , 92 , 0 , 203 , 250 , 213 , 254 , 93 , 193 , 189 , 255 , 130 , 255 , 34 , 254 , 212 , 188 , 151 , 0 , 136 , 17 , 20 , 255 , 20 , 101 , 83 , 255 , 212 , 206 , 166 , 0 , 229 , 238 , 73 , 255 , 151 , 74 , 3 , 255 , 168 , 87 , 215 , 0 , 155 , 188 , 133 , 255 , 166 , 129 , 73 , 0 , 240 , 79 , 133 , 255 , 178 , 211 , 81 , 255 , 203 , 72 , 163 , 254 , 193 , 168 , 165 , 0 , 14 , 164 , 199 , 254 , 30 , 255 , 204 , 0 , 65 , 72 , 91 , 1 , 166 , 74 , 102 , 255 , 200 , 42 , 0 , 255 , 194 , 113 , 227 , 255 , 66 , 23 , 208 , 0 , 229 , 216 , 100 , 255 , 24 , 239 , 26 , 0 , 10 , 233 , 62 , 255 , 123 , 10 , 178 , 1 , 26 , 36 , 174 , 255 , 119 , 219 , 199 , 1 , 45 , 163 , 190 , 0 , 16 , 168 , 42 , 0 , 166 , 57 , 198 , 255 , 28 , 26 , 26 , 0 , 126 , 165 , 231 , 0 , 251 , 108 , 100 , 255 , 61 , 229 , 121 , 255 , 58 , 118 , 138 , 0 , 76 , 207 , 17 , 0 , 13 , 34 , 112 , 254 , 89 , 16 , 168 , 0 , 37 , 208 , 105 , 255 , 35 , 201 , 215 , 255 , 40 , 106 , 101 , 254 , 6 , 239 , 114 , 0 , 40 , 103 , 226 , 254 , 246 , 127 , 110 , 255 , 63 , 167 , 58 , 0 , 132 , 240 , 142 , 0 , 5 , 158 , 88 , 255 , 129 , 73 , 158 , 255 , 94 , 89 , 146 , 0 , 230 , 54 , 146 , 0 , 8 , 45 , 173 , 0 , 79 , 169 , 1 , 0 , 115 , 186 , 247 , 0 , 84 , 64 , 131 , 0 , 67 , 224 , 253 , 255 , 207 , 189 , 64 , 0 , 154 , 28 , 81 , 1 , 45 , 184 , 54 , 255 , 87 , 212 , 224 , 255 , 0 , 96 , 73 , 255 , 129 , 33 , 235 , 1 , 52 , 66 , 80 , 255 , 251 , 174 , 155 , 255 , 4 , 179 , 37 , 0 , 234 , 164 , 93 , 254 , 93 , 175 , 253 , 0 , 198 , 69 , 87 , 255 , 224 , 106 , 46 , 0 , 99 , 29 , 210 , 0 , 62 , 188 , 114 , 255 , 44 , 234 , 8 , 0 , 169 , 175 , 247 , 255 , 23 , 109 , 137 , 255 , 229 , 182 , 39 , 0 , 192 , 165 , 94 , 254 , 245 , 101 , 217 , 0 , 191 , 88 , 96 , 0 , 196 , 94 , 99 , 255 , 106 , 238 , 11 , 254 , 53 , 126 , 243 , 0 , 94 , 1 , 101 , 255 , 46 , 147 , 2 , 0 , 201 , 124 , 124 , 255 , 141 , 12 , 218 , 0 , 13 , 166 , 157 , 1 , 48 , 251 , 237 , 255 , 155 , 250 , 124 , 255 , 106 , 148 , 146 , 255 , 182 , 13 , 202 , 0 , 28 , 61 , 167 , 0 , 217 , 152 , 8 , 254 , 220 , 130 , 45 , 255 , 200 , 230 , 255 , 1 , 55 , 65 , 87 , 255 , 93 , 191 , 97 , 254 , 114 , 251 , 14 , 0 , 32 , 105 , 92 , 1 , 26 , 207 , 141 , 0 , 24 , 207 , 13 , 254 , 21 , 50 , 48 , 255 , 186 , 148 , 116 , 255 , 211 , 43 , 225 , 0 , 37 , 34 , 162 , 254 , 164 , 210 , 42 , 255 , 68 , 23 , 96 , 255 , 182 , 214 , 8 , 255 , 245 , 117 , 137 , 255 , 66 , 195 , 50 , 0 , 75 , 12 , 83 , 254 , 80 , 140 , 164 , 0 , 9 , 165 , 36 , 1 , 228 , 110 , 227 , 0 , 241 , 17 , 90 , 1 , 25 , 52 , 212 , 0 , 6 , 223 , 12 , 255 , 139 , 243 , 57 , 0 , 12 , 113 , 75 , 1 , 246 , 183 , 191 , 255 , 213 , 191 , 69 , 255 , 230 , 15 , 142 , 0 , 1 , 195 , 196 , 255 , 138 , 171 , 47 , 255 , 64 , 63 , 106 , 1 , 16 , 169 , 214 , 255 , 207 , 174 , 56 , 1 , 88 , 73 , 133 , 255 , 182 , 133 , 140 , 0 , 177 , 14 , 25 , 255 , 147 , 184 , 53 , 255 , 10 , 227 , 161 , 255 , 120 , 216 , 244 , 255 , 73 , 77 , 233 , 0 , 157 , 238 , 139 , 1 , 59 , 65 , 233 , 0 , 70 , 251 , 216 , 1 , 41 , 184 , 153 , 255 , 32 , 203 , 112 , 0 , 146 , 147 , 253 , 0 , 87 , 101 , 109 , 1 , 44 , 82 , 133 , 255 , 244 , 150 , 53 , 255 , 94 , 152 , 232 , 255 , 59 , 93 , 39 , 255 , 88 , 147 , 220 , 255 , 78 , 81 , 13 , 1 , 32 , 47 , 252 , 255 , 160 , 19 , 114 , 255 , 93 , 107 , 39 , 255 , 118 , 16 , 211 , 1 , 185 , 119 , 209 , 255 , 227 , 219 , 127 , 254 , 88 , 105 , 236 , 255 , 162 , 110 , 23 , 255 , 36 , 166 , 110 , 255 , 91 , 236 , 221 , 2
. concat ( [ 187 , 164 , 227 , 1 , 160 , 25 , 5 , 0 , 12 , 78 , 195 , 1 , 43 , 197 , 225 , 0 , 48 , 142 , 41 , 254 , 196 , 155 , 60 , 255 , 223 , 199 , 18 , 1 , 145 , 136 , 156 , 0 , 252 , 117 , 169 , 254 , 145 , 226 , 238 , 0 , 239 , 23 , 107 , 0 , 109 , 181 , 188 , 255 , 230 , 112 , 49 , 254 , 73 , 170 , 237 , 255 , 231 , 183 , 227 , 255 , 80 , 220 , 20 , 0 , 194 , 107 , 127 , 1 , 127 , 205 , 101 , 0 , 46 , 52 , 197 , 1 , 210 , 171 , 36 , 255 , 88 , 3 , 90 , 255 , 56 , 151 , 141 , 0 , 96 , 187 , 255 , 255 , 42 , 78 , 200 , 0 , 254 , 70 , 70 , 1 , 244 , 125 , 168 , 0 , 204 , 68 , 138 , 1 , 124 , 215 , 70 , 0 , 102 , 66 , 200 , 254 , 17 , 52 , 228 , 0 , 117 , 220 , 143 , 254 , 203 , 248 , 123 , 0 , 56 , 18 , 174 , 255 , 186 , 151 , 164 , 255 , 51 , 232 , 208 , 1 , 160 , 228 , 43 , 255 , 249 , 29 , 25 , 1 , 68 , 190 , 63 , 0 , 34 , 174 , 40 , 215 , 152 , 47 , 138 , 66 , 205 , 101 , 239 , 35 , 145 , 68 , 55 , 113 , 47 , 59 , 77 , 236 , 207 , 251 , 192 , 181 , 188 , 219 , 137 , 129 , 165 , 219 , 181 , 233 , 56 , 181 , 72 , 243 , 91 , 194 , 86 , 57 , 25 , 208 , 5 , 182 , 241 , 17 , 241 , 89 , 155 , 79 , 25 , 175 , 164 , 130 , 63 , 146 , 24 , 129 , 109 , 218 , 213 , 94 , 28 , 171 , 66 , 2 , 3 , 163 , 152 , 170 , 7 , 216 , 190 , 111 , 112 , 69 , 1 , 91 , 131 , 18 , 140 , 178 , 228 , 78 , 190 , 133 , 49 , 36 , 226 , 180 , 255 , 213 , 195 , 125 , 12 , 85 , 111 , 137 , 123 , 242 , 116 , 93 , 190 , 114 , 177 , 150 , 22 , 59 , 254 , 177 , 222 , 128 , 53 , 18 , 199 , 37 , 167 , 6 , 220 , 155 , 148 , 38 , 105 , 207 , 116 , 241 , 155 , 193 , 210 , 74 , 241 , 158 , 193 , 105 , 155 , 228 , 227 , 37 , 79 , 56 , 134 , 71 , 190 , 239 , 181 , 213 , 140 , 139 , 198 , 157 , 193 , 15 , 101 , 156 , 172 , 119 , 204 , 161 , 12 , 36 , 117 , 2 , 43 , 89 , 111 , 44 , 233 , 45 , 131 , 228 , 166 , 110 , 170 , 132 , 116 , 74 , 212 , 251 , 65 , 189 , 220 , 169 , 176 , 92 , 181 , 83 , 17 , 131 , 218 , 136 , 249 , 118 , 171 , 223 , 102 , 238 , 82 , 81 , 62 , 152 , 16 , 50 , 180 , 45 , 109 , 198 , 49 , 168 , 63 , 33 , 251 , 152 , 200 , 39 , 3 , 176 , 228 , 14 , 239 , 190 , 199 , 127 , 89 , 191 , 194 , 143 , 168 , 61 , 243 , 11 , 224 , 198 , 37 , 167 , 10 , 147 , 71 , 145 , 167 , 213 , 111 , 130 , 3 , 224 , 81 , 99 , 202 , 6 , 112 , 110 , 14 , 10 , 103 , 41 , 41 , 20 , 252 , 47 , 210 , 70 , 133 , 10 , 183 , 39 , 38 , 201 , 38 , 92 , 56 , 33 , 27 , 46 , 237 , 42 , 196 , 90 , 252 , 109 , 44 , 77 , 223 , 179 , 149 , 157 , 19 , 13 , 56 , 83 , 222 , 99 , 175 , 139 , 84 , 115 , 10 , 101 , 168 , 178 , 119 , 60 , 187 , 10 , 106 , 118 , 230 , 174 , 237 , 71 , 46 , 201 , 194 , 129 , 59 , 53 , 130 , 20 , 133 , 44 , 114 , 146 , 100 , 3 , 241 , 76 , 161 , 232 , 191 , 162 , 1 , 48 , 66 , 188 , 75 , 102 , 26 , 168 , 145 , 151 , 248 , 208 , 112 , 139 , 75 , 194 , 48 , 190 , 84 , 6 , 163 , 81 , 108 , 199 , 24 , 82 , 239 , 214 , 25 , 232 , 146 , 209 , 16 , 169 , 101 , 85 , 36 , 6 , 153 , 214 , 42 , 32 , 113 , 87 , 133 , 53 , 14 , 244 , 184 , 209 , 187 , 50 , 112 , 160 , 106 , 16 , 200 , 208 , 210 , 184 , 22 , 193 , 164 , 25 , 83 , 171 , 65 , 81 , 8 , 108 , 55 , 30 , 153 , 235 , 142 , 223 , 76 , 119 , 72 , 39 , 168 , 72 , 155 , 225 , 181 , 188 , 176 , 52 , 99 , 90 , 201 , 197 , 179 , 12 , 28 , 57 , 203 , 138 , 65 , 227 , 74 , 170 , 216 , 78 , 115 , 227 , 99 , 119 , 79 , 202 , 156 , 91 , 163 , 184 , 178 , 214 , 243 , 111 , 46 , 104 , 252 , 178 , 239 , 93 , 238 , 130 , 143 , 116 , 96 , 47 , 23 , 67 , 111 , 99 , 165 , 120 , 114 , 171 , 240 , 161 , 20 , 120 , 200 , 132 , 236 , 57 , 100 , 26 , 8 , 2 , 199 , 140 , 40 , 30 , 99 , 35 , 250 , 255 , 190 , 144 , 233 , 189 , 130 , 222 , 235 , 108 , 80 , 164 , 21 , 121 , 198 , 178 , 247 , 163 , 249 , 190 , 43 , 83 , 114 , 227 , 242 , 120 , 113 , 198 , 156 , 97 , 38 , 234 , 206 , 62 , 39 , 202 , 7 , 194 , 192 , 33 , 199 , 184 , 134 , 209 , 30 , 235 , 224 , 205 , 214 , 125 , 218 , 234 , 120 , 209 , 110 , 238 , 127 , 79 , 125 , 245 , 186 , 111 , 23 , 114 , 170 , 103 , 240 , 6 , 166 , 152 , 200 , 162 , 197 , 125 , 99 , 10 , 174 , 13 , 249 , 190 , 4 , 152 , 63 , 17 , 27 , 71 , 28 , 19 , 53 , 11 , 113 , 27 , 132 , 125 , 4 , 35 , 245 , 119 , 219 , 40 , 147 , 36 , 199 , 64 , 123 , 171 , 202 , 50 , 188 , 190 , 201 , 21 , 10 , 190 , 158 , 60 , 76 , 13 , 16 , 156 , 196 , 103 , 29 , 67 , 182 , 66 , 62 , 203 , 190 , 212 , 197 , 76 , 42 , 126 , 101 , 252 , 156 , 41 , 127 , 89 , 236 , 250 , 214 , 58 , 171 , 111 , 203 , 95 , 23 , 88 , 71 , 74 , 140 , 25 , 68 , 108 , 8 , 201 , 188 , 243 , 103 , 230 , 9 , 106 , 59 , 167 , 202 , 132 , 133 , 174 , 103 , 187 , 43 , 248 , 148 , 254 , 114 , 243 , 110 , 60 , 241 , 54 , 29 , 95 , 58 , 245 , 79 , 165 , 209 , 130 , 230 , 173 , 127 , 82 , 14 , 81 , 31 , 108 , 62 , 43 , 140 , 104 , 5 , 155 , 107 , 189 , 65 , 251 , 171 , 217 , 131 , 31 , 121 , 33 , 126 , 19 , 25 , 205 , 224 , 91 , 133 , 59 , 140 , 1 , 189 , 241 , 36 , 255 , 248 , 37 , 195 , 1 , 96 , 220 , 55 , 0 , 183 , 76 , 62 , 255 , 195 , 66 , 61 , 0 , 50 , 76 , 164 , 1 , 225 , 164 , 76 , 255 , 76 , 61 , 163 , 255 , 117 , 62 , 31 , 0 , 81 , 145 , 64 , 255 , 118 , 65 , 14 , 0 , 162 , 115 , 214 , 255 , 6 , 138 , 46 , 0 , 124 , 230 , 244 , 255 , 10 , 138 , 143 , 0 , 52 , 26 , 194 , 0 , 184 , 244 , 76 , 0 , 129 , 143 , 41 , 1 , 190 , 244 , 19 , 255 , 123 , 170 , 122 , 255 , 98 , 129 , 68 , 0 , 121 , 213 , 147 , 0 , 86 , 101 , 30 , 255 , 161 , 103 , 155 , 0 , 140 , 89 , 67 , 255 , 239 , 229 , 190 , 1 , 67 , 11 , 181 , 0 , 198 , 240 , 137 , 254 , 238 , 69 , 188 , 255 , 67 , 151 , 238 , 0 , 19 , 42 , 108 , 255 , 229 , 85 , 113 , 1 , 50 , 68 , 135 , 255 , 17 , 106 , 9 , 0 , 50 , 103 , 1 , 255 , 80 , 1 , 168 , 1 , 35 , 152 , 30 , 255 , 16 , 168 , 185 , 1 , 56 , 89 , 232 , 255 , 101 , 210 , 252 , 0 , 41 , 250 , 71 , 0 , 204 , 170 , 79 , 255 , 14 , 46 , 239 , 255 , 80 , 77 , 239 , 0 , 189 , 214 , 75 , 255 , 17 , 141 , 249 , 0 , 38 , 80 , 76 , 255 , 190 , 85 , 117 , 0 , 86 , 228 , 170 , 0 , 156 , 216 , 208 , 1 , 195 , 207 , 164 , 255 , 150 , 66 , 76 , 255 , 175 , 225 , 16 , 255 , 141 , 80 , 98 , 1 , 76 , 219 , 242 , 0 , 198 , 162 , 114 , 0 , 46 , 218 , 152 , 0 , 155 , 43 , 241 , 254 , 155 , 160 , 104 , 255 , 51 , 187 , 165 , 0 , 2 , 17 , 175 , 0 , 66 , 84 , 160 , 1 , 247 , 58 , 30 , 0 , 35 , 65 , 53 , 254 , 69 , 236 , 191 , 0 , 45 , 134 , 245 , 1 , 163 , 123 , 221 , 0 , 32 , 110 , 20 , 255 , 52 , 23 , 165 , 0 , 186 , 214 , 71 , 0 , 233 , 176 , 96 , 0 , 242 , 239 , 54 , 1 , 57 , 89 , 138 , 0 , 83 , 0 , 84 , 255 , 136 , 160 , 100 , 0 , 92 , 142 , 120 , 254 , 104 , 1
, "i8" , ALLOC _NONE , Runtime . GLOBAL _BASE )
function runPostSets ( ) {
}
if ( ! awaitingMemoryInitializer ) runPostSets ( ) ;
var tempDoublePtr = Runtime . alignMemory ( allocate ( 12 , "i8" , ALLOC _STATIC ) , 8 ) ;
assert ( tempDoublePtr % 8 == 0 ) ;
function copyTempFloat ( ptr ) { // functions, because inlining this code increases code size too much
HEAP8 [ tempDoublePtr ] = HEAP8 [ ptr ] ;
HEAP8 [ tempDoublePtr + 1 ] = HEAP8 [ ptr + 1 ] ;
HEAP8 [ tempDoublePtr + 2 ] = HEAP8 [ ptr + 2 ] ;
HEAP8 [ tempDoublePtr + 3 ] = HEAP8 [ ptr + 3 ] ;
}
function copyTempDouble ( ptr ) {
HEAP8 [ tempDoublePtr ] = HEAP8 [ ptr ] ;
HEAP8 [ tempDoublePtr + 1 ] = HEAP8 [ ptr + 1 ] ;
HEAP8 [ tempDoublePtr + 2 ] = HEAP8 [ ptr + 2 ] ;
HEAP8 [ tempDoublePtr + 3 ] = HEAP8 [ ptr + 3 ] ;
HEAP8 [ tempDoublePtr + 4 ] = HEAP8 [ ptr + 4 ] ;
HEAP8 [ tempDoublePtr + 5 ] = HEAP8 [ ptr + 5 ] ;
HEAP8 [ tempDoublePtr + 6 ] = HEAP8 [ ptr + 6 ] ;
HEAP8 [ tempDoublePtr + 7 ] = HEAP8 [ ptr + 7 ] ;
}
2015-02-20 15:05:32 -08:00
Module [ "_memcpy" ] = _memcpy ;
2015-02-10 16:39:50 -08:00
Module [ "_memmove" ] = _memmove ; var _llvm _memmove _p0i8 _p0i8 _i32 = _memmove ;
var _llvm _memcpy _p0i8 _p0i8 _i32 = _memcpy ;
Module [ "_memset" ] = _memset ; var _llvm _memset _p0i8 _i32 = _memset ;
var _llvm _memset _p0i8 _i64 = _memset ;
function _llvm _lifetime _start ( ) { }
function _llvm _lifetime _end ( ) { }
function _malloc ( bytes ) {
/ * O v e r - a l l o c a t e t o m a k e s u r e i t i s b y t e - a l i g n e d b y 8 .
* This will leak memory , but this is only the dummy
* implementation ( replaced by dlmalloc normally ) so
* not an issue .
* /
var ptr = Runtime . dynamicAlloc ( bytes + 8 ) ;
return ( ptr + 8 ) & 0xFFFFFFF8 ;
}
Module [ "_malloc" ] = _malloc ;
function _free ( ) {
}
Module [ "_free" ] = _free ;
Module [ "_strlen" ] = _strlen ;
var Browser = { mainLoop : { scheduler : null , shouldPause : false , paused : false , queue : [ ] , pause : function ( ) {
Browser . mainLoop . shouldPause = true ;
} , resume : function ( ) {
if ( Browser . mainLoop . paused ) {
Browser . mainLoop . paused = false ;
Browser . mainLoop . scheduler ( ) ;
}
Browser . mainLoop . shouldPause = false ;
} , updateStatus : function ( ) {
if ( Module [ 'setStatus' ] ) {
var message = Module [ 'statusMessage' ] || 'Please wait...' ;
var remaining = Browser . mainLoop . remainingBlockers ;
var expected = Browser . mainLoop . expectedBlockers ;
if ( remaining ) {
if ( remaining < expected ) {
Module [ 'setStatus' ] ( message + ' (' + ( expected - remaining ) + '/' + expected + ')' ) ;
} else {
Module [ 'setStatus' ] ( message ) ;
}
} else {
Module [ 'setStatus' ] ( '' ) ;
}
}
} } , isFullScreen : false , pointerLock : false , moduleContextCreatedCallbacks : [ ] , workers : [ ] , init : function ( ) {
if ( Browser . initted ) return ;
Browser . initted = true ;
try {
new Blob ( ) ;
Browser . hasBlobConstructor = true ;
} catch ( e ) {
Browser . hasBlobConstructor = false ;
console . log ( "warning: no blob constructor, cannot create blobs with mimetypes" ) ;
}
Browser . BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : ( typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : ( ! Browser . hasBlobConstructor ? console . log ( "warning: no BlobBuilder" ) : null ) ) ;
Browser . URLObject = typeof window != "undefined" ? ( window . URL ? window . URL : window . webkitURL ) : console . log ( "warning: cannot create object URLs" ) ;
// Support for plugins that can process preloaded files. You can add more of these to
// your app by creating and appending to Module.preloadPlugins.
//
// Each plugin is asked if it can handle a file based on the file's name. If it can,
// it is given the file's raw data. When it is done, it calls a callback with the file's
// (possibly modified) data. For example, a plugin might decompress a file, or it
// might create some side data structure for use later (like an Image element, etc.).
function getMimetype ( name ) {
return {
'jpg' : 'image/jpeg' ,
'jpeg' : 'image/jpeg' ,
'png' : 'image/png' ,
'bmp' : 'image/bmp' ,
'ogg' : 'audio/ogg' ,
'wav' : 'audio/wav' ,
'mp3' : 'audio/mpeg'
} [ name . substr ( name . lastIndexOf ( '.' ) + 1 ) ] ;
}
if ( ! Module [ "preloadPlugins" ] ) Module [ "preloadPlugins" ] = [ ] ;
var imagePlugin = { } ;
imagePlugin [ 'canHandle' ] = function ( name ) {
return ! Module . noImageDecoding && /\.(jpg|jpeg|png|bmp)$/ . exec ( name ) ;
} ;
imagePlugin [ 'handle' ] = function ( byteArray , name , onload , onerror ) {
var b = null ;
if ( Browser . hasBlobConstructor ) {
try {
b = new Blob ( [ byteArray ] , { type : getMimetype ( name ) } ) ;
} catch ( e ) {
Runtime . warnOnce ( 'Blob constructor present but fails: ' + e + '; falling back to blob builder' ) ;
}
}
if ( ! b ) {
var bb = new Browser . BlobBuilder ( ) ;
bb . append ( ( new Uint8Array ( byteArray ) ) . buffer ) ; // we need to pass a buffer, and must copy the array to get the right data range
b = bb . getBlob ( ) ;
}
var url = Browser . URLObject . createObjectURL ( b ) ;
var img = new Image ( ) ;
img . onload = function ( ) {
assert ( img . complete , 'Image ' + name + ' could not be decoded' ) ;
var canvas = document . createElement ( 'canvas' ) ;
canvas . width = img . width ;
canvas . height = img . height ;
var ctx = canvas . getContext ( '2d' ) ;
ctx . drawImage ( img , 0 , 0 ) ;
Module [ "preloadedImages" ] [ name ] = canvas ;
Browser . URLObject . revokeObjectURL ( url ) ;
if ( onload ) onload ( byteArray ) ;
} ;
img . onerror = function ( event ) {
console . log ( 'Image ' + url + ' could not be decoded' ) ;
if ( onerror ) onerror ( ) ;
} ;
img . src = url ;
} ;
Module [ 'preloadPlugins' ] . push ( imagePlugin ) ;
var audioPlugin = { } ;
audioPlugin [ 'canHandle' ] = function ( name ) {
return ! Module . noAudioDecoding && name . substr ( - 4 ) in { '.ogg' : 1 , '.wav' : 1 , '.mp3' : 1 } ;
} ;
audioPlugin [ 'handle' ] = function ( byteArray , name , onload , onerror ) {
var done = false ;
function finish ( audio ) {
if ( done ) return ;
done = true ;
Module [ "preloadedAudios" ] [ name ] = audio ;
if ( onload ) onload ( byteArray ) ;
}
function fail ( ) {
if ( done ) return ;
done = true ;
Module [ "preloadedAudios" ] [ name ] = new Audio ( ) ; // empty shim
if ( onerror ) onerror ( ) ;
}
if ( Browser . hasBlobConstructor ) {
try {
var b = new Blob ( [ byteArray ] , { type : getMimetype ( name ) } ) ;
} catch ( e ) {
return fail ( ) ;
}
var url = Browser . URLObject . createObjectURL ( b ) ; // XXX we never revoke this!
var audio = new Audio ( ) ;
audio . addEventListener ( 'canplaythrough' , function ( ) { finish ( audio ) } , false ) ; // use addEventListener due to chromium bug 124926
audio . onerror = function ( event ) {
if ( done ) return ;
console . log ( 'warning: browser could not fully decode audio ' + name + ', trying slower base64 approach' ) ;
function encode64 ( data ) {
var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' ;
var PAD = '=' ;
var ret = '' ;
var leftchar = 0 ;
var leftbits = 0 ;
for ( var i = 0 ; i < data . length ; i ++ ) {
leftchar = ( leftchar << 8 ) | data [ i ] ;
leftbits += 8 ;
while ( leftbits >= 6 ) {
var curr = ( leftchar >> ( leftbits - 6 ) ) & 0x3f ;
leftbits -= 6 ;
ret += BASE [ curr ] ;
}
}
if ( leftbits == 2 ) {
ret += BASE [ ( leftchar & 3 ) << 4 ] ;
ret += PAD + PAD ;
} else if ( leftbits == 4 ) {
ret += BASE [ ( leftchar & 0xf ) << 2 ] ;
ret += PAD ;
}
return ret ;
}
audio . src = 'data:audio/x-' + name . substr ( - 3 ) + ';base64,' + encode64 ( byteArray ) ;
finish ( audio ) ; // we don't wait for confirmation this worked - but it's worth trying
} ;
audio . src = url ;
// workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
Browser . safeSetTimeout ( function ( ) {
finish ( audio ) ; // try to use it even though it is not necessarily ready to play
} , 10000 ) ;
} else {
return fail ( ) ;
}
} ;
Module [ 'preloadPlugins' ] . push ( audioPlugin ) ;
// Canvas event setup
var canvas = Module [ 'canvas' ] ;
canvas . requestPointerLock = canvas [ 'requestPointerLock' ] ||
canvas [ 'mozRequestPointerLock' ] ||
canvas [ 'webkitRequestPointerLock' ] ;
canvas . exitPointerLock = document [ 'exitPointerLock' ] ||
document [ 'mozExitPointerLock' ] ||
document [ 'webkitExitPointerLock' ] ||
function ( ) { } ; // no-op if function does not exist
canvas . exitPointerLock = canvas . exitPointerLock . bind ( document ) ;
function pointerLockChange ( ) {
Browser . pointerLock = document [ 'pointerLockElement' ] === canvas ||
document [ 'mozPointerLockElement' ] === canvas ||
document [ 'webkitPointerLockElement' ] === canvas ;
}
document . addEventListener ( 'pointerlockchange' , pointerLockChange , false ) ;
document . addEventListener ( 'mozpointerlockchange' , pointerLockChange , false ) ;
document . addEventListener ( 'webkitpointerlockchange' , pointerLockChange , false ) ;
if ( Module [ 'elementPointerLock' ] ) {
canvas . addEventListener ( "click" , function ( ev ) {
if ( ! Browser . pointerLock && canvas . requestPointerLock ) {
canvas . requestPointerLock ( ) ;
ev . preventDefault ( ) ;
}
} , false ) ;
}
} , createContext : function ( canvas , useWebGL , setInModule ) {
var ctx ;
try {
if ( useWebGL ) {
ctx = canvas . getContext ( 'experimental-webgl' , {
alpha : false
} ) ;
} else {
ctx = canvas . getContext ( '2d' ) ;
}
if ( ! ctx ) throw ':(' ;
} catch ( e ) {
Module . print ( 'Could not create canvas - ' + e ) ;
return null ;
}
if ( useWebGL ) {
// Set the background of the WebGL canvas to black
canvas . style . backgroundColor = "black" ;
// Warn on context loss
canvas . addEventListener ( 'webglcontextlost' , function ( event ) {
alert ( 'WebGL context lost. You will need to reload the page.' ) ;
} , false ) ;
}
if ( setInModule ) {
Module . ctx = ctx ;
Module . useWebGL = useWebGL ;
Browser . moduleContextCreatedCallbacks . forEach ( function ( callback ) { callback ( ) } ) ;
Browser . init ( ) ;
}
return ctx ;
} , destroyContext : function ( canvas , useWebGL , setInModule ) { } , fullScreenHandlersInstalled : false , lockPointer : undefined , resizeCanvas : undefined , requestFullScreen : function ( lockPointer , resizeCanvas ) {
Browser . lockPointer = lockPointer ;
Browser . resizeCanvas = resizeCanvas ;
if ( typeof Browser . lockPointer === 'undefined' ) Browser . lockPointer = true ;
if ( typeof Browser . resizeCanvas === 'undefined' ) Browser . resizeCanvas = false ;
var canvas = Module [ 'canvas' ] ;
function fullScreenChange ( ) {
Browser . isFullScreen = false ;
if ( ( document [ 'webkitFullScreenElement' ] || document [ 'webkitFullscreenElement' ] ||
document [ 'mozFullScreenElement' ] || document [ 'mozFullscreenElement' ] ||
document [ 'fullScreenElement' ] || document [ 'fullscreenElement' ] ) === canvas ) {
canvas . cancelFullScreen = document [ 'cancelFullScreen' ] ||
document [ 'mozCancelFullScreen' ] ||
document [ 'webkitCancelFullScreen' ] ;
canvas . cancelFullScreen = canvas . cancelFullScreen . bind ( document ) ;
if ( Browser . lockPointer ) canvas . requestPointerLock ( ) ;
Browser . isFullScreen = true ;
if ( Browser . resizeCanvas ) Browser . setFullScreenCanvasSize ( ) ;
} else if ( Browser . resizeCanvas ) {
Browser . setWindowedCanvasSize ( ) ;
}
if ( Module [ 'onFullScreen' ] ) Module [ 'onFullScreen' ] ( Browser . isFullScreen ) ;
}
if ( ! Browser . fullScreenHandlersInstalled ) {
Browser . fullScreenHandlersInstalled = true ;
document . addEventListener ( 'fullscreenchange' , fullScreenChange , false ) ;
document . addEventListener ( 'mozfullscreenchange' , fullScreenChange , false ) ;
document . addEventListener ( 'webkitfullscreenchange' , fullScreenChange , false ) ;
}
canvas . requestFullScreen = canvas [ 'requestFullScreen' ] ||
canvas [ 'mozRequestFullScreen' ] ||
( canvas [ 'webkitRequestFullScreen' ] ? function ( ) { canvas [ 'webkitRequestFullScreen' ] ( Element [ 'ALLOW_KEYBOARD_INPUT' ] ) } : null ) ;
canvas . requestFullScreen ( ) ;
} , requestAnimationFrame : function ( func ) {
if ( ! window . requestAnimationFrame ) {
window . requestAnimationFrame = window [ 'requestAnimationFrame' ] ||
window [ 'mozRequestAnimationFrame' ] ||
window [ 'webkitRequestAnimationFrame' ] ||
window [ 'msRequestAnimationFrame' ] ||
window [ 'oRequestAnimationFrame' ] ||
window [ 'setTimeout' ] ;
}
window . requestAnimationFrame ( func ) ;
} , safeCallback : function ( func ) {
return function ( ) {
if ( ! ABORT ) return func . apply ( null , arguments ) ;
} ;
} , safeRequestAnimationFrame : function ( func ) {
return Browser . requestAnimationFrame ( function ( ) {
if ( ! ABORT ) func ( ) ;
} ) ;
} , safeSetTimeout : function ( func , timeout ) {
return setTimeout ( function ( ) {
if ( ! ABORT ) func ( ) ;
} , timeout ) ;
} , safeSetInterval : function ( func , timeout ) {
return setInterval ( function ( ) {
if ( ! ABORT ) func ( ) ;
} , timeout ) ;
} , getUserMedia : function ( func ) {
if ( ! window . getUserMedia ) {
window . getUserMedia = navigator [ 'getUserMedia' ] ||
navigator [ 'mozGetUserMedia' ] ;
}
window . getUserMedia ( func ) ;
} , getMovementX : function ( event ) {
return event [ 'movementX' ] ||
event [ 'mozMovementX' ] ||
event [ 'webkitMovementX' ] ||
0 ;
} , getMovementY : function ( event ) {
return event [ 'movementY' ] ||
event [ 'mozMovementY' ] ||
event [ 'webkitMovementY' ] ||
0 ;
} , mouseX : 0 , mouseY : 0 , mouseMovementX : 0 , mouseMovementY : 0 , calculateMouseEvent : function ( event ) { // event should be mousemove, mousedown or mouseup
if ( Browser . pointerLock ) {
// When the pointer is locked, calculate the coordinates
// based on the movement of the mouse.
// Workaround for Firefox bug 764498
if ( event . type != 'mousemove' &&
( 'mozMovementX' in event ) ) {
Browser . mouseMovementX = Browser . mouseMovementY = 0 ;
} else {
Browser . mouseMovementX = Browser . getMovementX ( event ) ;
Browser . mouseMovementY = Browser . getMovementY ( event ) ;
}
Browser . mouseX = SDL . mouseX + Browser . mouseMovementX ;
Browser . mouseY = SDL . mouseY + Browser . mouseMovementY ;
} else {
// Otherwise, calculate the movement based on the changes
// in the coordinates.
var rect = Module [ "canvas" ] . getBoundingClientRect ( ) ;
var x = event . pageX - ( window . scrollX + rect . left ) ;
var y = event . pageY - ( window . scrollY + rect . top ) ;
// the canvas might be CSS-scaled compared to its backbuffer;
// SDL-using content will want mouse coordinates in terms
// of backbuffer units.
var cw = Module [ "canvas" ] . width ;
var ch = Module [ "canvas" ] . height ;
x = x * ( cw / rect . width ) ;
y = y * ( ch / rect . height ) ;
Browser . mouseMovementX = x - Browser . mouseX ;
Browser . mouseMovementY = y - Browser . mouseY ;
Browser . mouseX = x ;
Browser . mouseY = y ;
}
} , xhrLoad : function ( url , onload , onerror ) {
var xhr = new XMLHttpRequest ( ) ;
xhr . open ( 'GET' , url , true ) ;
xhr . responseType = 'arraybuffer' ;
xhr . onload = function ( ) {
if ( xhr . status == 200 || ( xhr . status == 0 && xhr . response ) ) { // file URLs can return 0
onload ( xhr . response ) ;
} else {
onerror ( ) ;
}
} ;
xhr . onerror = onerror ;
xhr . send ( null ) ;
} , asyncLoad : function ( url , onload , onerror , noRunDep ) {
Browser . xhrLoad ( url , function ( arrayBuffer ) {
assert ( arrayBuffer , 'Loading data file "' + url + '" failed (no arrayBuffer).' ) ;
onload ( new Uint8Array ( arrayBuffer ) ) ;
if ( ! noRunDep ) removeRunDependency ( 'al ' + url ) ;
} , function ( event ) {
if ( onerror ) {
onerror ( ) ;
} else {
throw 'Loading data file "' + url + '" failed.' ;
}
} ) ;
if ( ! noRunDep ) addRunDependency ( 'al ' + url ) ;
} , resizeListeners : [ ] , updateResizeListeners : function ( ) {
var canvas = Module [ 'canvas' ] ;
Browser . resizeListeners . forEach ( function ( listener ) {
listener ( canvas . width , canvas . height ) ;
} ) ;
} , setCanvasSize : function ( width , height , noUpdates ) {
var canvas = Module [ 'canvas' ] ;
canvas . width = width ;
canvas . height = height ;
if ( ! noUpdates ) Browser . updateResizeListeners ( ) ;
} , windowedWidth : 0 , windowedHeight : 0 , setFullScreenCanvasSize : function ( ) {
var canvas = Module [ 'canvas' ] ;
this . windowedWidth = canvas . width ;
this . windowedHeight = canvas . height ;
canvas . width = screen . width ;
canvas . height = screen . height ;
var flags = HEAPU32 [ ( ( SDL . screen + Runtime . QUANTUM _SIZE * 0 ) >> 2 ) ] ;
flags = flags | 0x00800000 ; // set SDL_FULLSCREEN flag
HEAP32 [ ( ( SDL . screen + Runtime . QUANTUM _SIZE * 0 ) >> 2 ) ] = flags
Browser . updateResizeListeners ( ) ;
} , setWindowedCanvasSize : function ( ) {
var canvas = Module [ 'canvas' ] ;
canvas . width = this . windowedWidth ;
canvas . height = this . windowedHeight ;
var flags = HEAPU32 [ ( ( SDL . screen + Runtime . QUANTUM _SIZE * 0 ) >> 2 ) ] ;
flags = flags & ~ 0x00800000 ; // clear SDL_FULLSCREEN flag
HEAP32 [ ( ( SDL . screen + Runtime . QUANTUM _SIZE * 0 ) >> 2 ) ] = flags
Browser . updateResizeListeners ( ) ;
} } ;
Module [ "requestFullScreen" ] = function ( lockPointer , resizeCanvas ) { Browser . requestFullScreen ( lockPointer , resizeCanvas ) } ;
Module [ "requestAnimationFrame" ] = function ( func ) { Browser . requestAnimationFrame ( func ) } ;
Module [ "pauseMainLoop" ] = function ( ) { Browser . mainLoop . pause ( ) } ;
Module [ "resumeMainLoop" ] = function ( ) { Browser . mainLoop . resume ( ) } ;
Module [ "getUserMedia" ] = function ( ) { Browser . getUserMedia ( ) }
STACK _BASE = STACKTOP = Runtime . alignMemory ( STATICTOP ) ;
staticSealed = true ; // seal the static portion of memory
STACK _MAX = STACK _BASE + 5242880 ;
DYNAMIC _BASE = DYNAMICTOP = Runtime . alignMemory ( STACK _MAX ) ;
assert ( DYNAMIC _BASE < TOTAL _MEMORY ) ; // Stack must fit in TOTAL_MEMORY; allocations from here on may enlarge TOTAL_MEMORY
var ctlz _i8 = allocate ( [ 8 , 7 , 6 , 6 , 5 , 5 , 5 , 5 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 3 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 2 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ] , "i8" , ALLOC _DYNAMIC ) ;
var cttz _i8 = allocate ( [ 8 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 4 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 5 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 4 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 6 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 4 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 5 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 4 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 7 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 4 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 5 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 4 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 6 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 4 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 5 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 4 , 0 , 1 , 0 , 2 , 0 , 1 , 0 , 3 , 0 , 1 , 0 , 2 , 0 , 1 , 0 ] , "i8" , ALLOC _DYNAMIC ) ;
var Math _min = Math . min ;
function invoke _ii ( index , a1 ) {
try {
return Module [ "dynCall_ii" ] ( index , a1 ) ;
} catch ( e ) {
if ( typeof e !== 'number' && e !== 'longjmp' ) throw e ;
asm [ "setThrew" ] ( 1 , 0 ) ;
}
}
function invoke _v ( index ) {
try {
Module [ "dynCall_v" ] ( index ) ;
} catch ( e ) {
if ( typeof e !== 'number' && e !== 'longjmp' ) throw e ;
asm [ "setThrew" ] ( 1 , 0 ) ;
}
}
function invoke _iii ( index , a1 , a2 ) {
try {
return Module [ "dynCall_iii" ] ( index , a1 , a2 ) ;
} catch ( e ) {
if ( typeof e !== 'number' && e !== 'longjmp' ) throw e ;
asm [ "setThrew" ] ( 1 , 0 ) ;
}
}
function invoke _vi ( index , a1 ) {
try {
Module [ "dynCall_vi" ] ( index , a1 ) ;
} catch ( e ) {
if ( typeof e !== 'number' && e !== 'longjmp' ) throw e ;
asm [ "setThrew" ] ( 1 , 0 ) ;
}
}
function asmPrintInt ( x , y ) {
Module . print ( 'int ' + x + ',' + y ) ; // + ' ' + new Error().stack);
}
function asmPrintFloat ( x , y ) {
Module . print ( 'float ' + x + ',' + y ) ; // + ' ' + new Error().stack);
}
// EMSCRIPTEN_START_ASM
var asm = ( function ( global , env , buffer ) { "use asm" ; var a = new global . Int8Array ( buffer ) ; var b = new global . Int16Array ( buffer ) ; var c = new global . Int32Array ( buffer ) ; var d = new global . Uint8Array ( buffer ) ; var e = new global . Uint16Array ( buffer ) ; var f = new global . Uint32Array ( buffer ) ; var g = new global . Float32Array ( buffer ) ; var h = new global . Float64Array ( buffer ) ; var i = env . STACKTOP | 0 ; var j = env . STACK _MAX | 0 ; var k = env . tempDoublePtr | 0 ; var l = env . ABORT | 0 ; var m = env . cttz _i8 | 0 ; var n = env . ctlz _i8 | 0 ; var o = + env . NaN ; var p = + env . Infinity ; var q = 0 ; var r = 0 ; var s = 0 ; var t = 0 ; var u = 0 , v = 0 , w = 0 , x = 0 , y = 0.0 , z = 0 , A = 0 , B = 0 , C = 0.0 ; var D = 0 ; var E = 0 ; var F = 0 ; var G = 0 ; var H = 0 ; var I = 0 ; var J = 0 ; var K = 0 ; var L = 0 ; var M = 0 ; var N = global . Math . floor ; var O = global . Math . abs ; var P = global . Math . sqrt ; var Q = global . Math . pow ; var R = global . Math . cos ; var S = global . Math . sin ; var T = global . Math . tan ; var U = global . Math . acos ; var V = global . Math . asin ; var W = global . Math . atan ; var X = global . Math . atan2 ; var Y = global . Math . exp ; var Z = global . Math . log ; var _ = global . Math . ceil ; var $ = global . Math . imul ; var aa = env . abort ; var ab = env . assert ; var ac = env . asmPrintInt ; var ad = env . asmPrintFloat ; var ae = env . copyTempDouble ; var af = env . copyTempFloat ; var ag = env . min ; var ah = env . invoke _ii ; var ai = env . invoke _v ; var aj = env . invoke _iii ; var ak = env . invoke _vi ; var al = env . _llvm _lifetime _end ; var am = env . _malloc ; var an = env . _free ; var ao = env . _llvm _lifetime _start ;
// EMSCRIPTEN_START_FUNCS
function at ( a ) { a = a | 0 ; var b = 0 ; b = i ; i = i + a | 0 ; i = i + 7 >> 3 << 3 ; return b | 0 } function au ( ) { return i | 0 } function av ( a ) { a = a | 0 ; i = a } function aw ( a , b ) { a = a | 0 ; b = b | 0 ; if ( ( q | 0 ) == 0 ) { q = a ; r = b } } function ax ( a ) { a = a | 0 ; D = a } function ay ( a ) { a = a | 0 ; E = a } function az ( a ) { a = a | 0 ; F = a } function aA ( a ) { a = a | 0 ; G = a } function aB ( a ) { a = a | 0 ; H = a } function aC ( a ) { a = a | 0 ; I = a } function aD ( a ) { a = a | 0 ; J = a } function aE ( a ) { a = a | 0 ; K = a } function aF ( a ) { a = a | 0 ; L = a } function aG ( a ) { a = a | 0 ; M = a } function aH ( b , c ) { b = b | 0 ; c = c | 0 ; return ( ( ( ( a [ c + 1 | 0 ] ^ a [ b + 1 | 0 ] | a [ c ] ^ a [ b ] | a [ c + 2 | 0 ] ^ a [ b + 2 | 0 ] | a [ c + 3 | 0 ] ^ a [ b + 3 | 0 ] | a [ c + 4 | 0 ] ^ a [ b + 4 | 0 ] | a [ c + 5 | 0 ] ^ a [ b + 5 | 0 ] | a [ c + 6 | 0 ] ^ a [ b + 6 | 0 ] | a [ c + 7 | 0 ] ^ a [ b + 7 | 0 ] | a [ c + 8 | 0 ] ^ a [ b + 8 | 0 ] | a [ c + 9 | 0 ] ^ a [ b + 9 | 0 ] | a [ c + 10 | 0 ] ^ a [ b + 10 | 0 ] | a [ c + 11 | 0 ] ^ a [ b + 11 | 0 ] | a [ c + 12 | 0 ] ^ a [ b + 12 | 0 ] | a [ c + 13 | 0 ] ^ a [ b + 13 | 0 ] | a [ c + 14 | 0 ] ^ a [ b + 14 | 0 ] | a [ c + 15 | 0 ] ^ a [ b + 15 | 0 ] | a [ c + 16 | 0 ] ^ a [ b + 16 | 0 ] | a [ c + 17 | 0 ] ^ a [ b + 17 | 0 ] | a [ c + 18 | 0 ] ^ a [ b + 18 | 0 ] | a [ c + 19 | 0 ] ^ a [ b + 19 | 0 ] | a [ c + 20 | 0 ] ^ a [ b + 20 | 0 ] | a [ c + 21 | 0 ] ^ a [ b + 21 | 0 ] | a [ c + 22 | 0 ] ^ a [ b + 22 | 0 ] | a [ c + 23 | 0 ] ^ a [ b + 23 | 0 ] | a [ c + 24 | 0 ] ^ a [ b + 24 | 0 ] | a [ c + 25 | 0 ] ^ a [ b + 25 | 0 ] | a [ c + 26 | 0 ] ^ a [ b + 26 | 0 ] | a [ c + 27 | 0 ] ^ a [ b + 27 | 0 ] | a [ c + 28 | 0 ] ^ a [ b + 28 | 0 ] | a [ c + 29 | 0 ] ^ a [ b + 29 | 0 ] | a [ c + 30 | 0 ] ^ a [ b + 30 | 0 ] | a [ c + 31 | 0 ] ^ a [ b + 31 | 0 ] ) & 255 ) + 511 | 0 ) >>> 8 & 1 ) - 1 | 0 } function aI ( b , d , e , f ) { b = b | 0 ; d = d | 0 ; e = e | 0 ; f = f | 0 ; var g = 0 , h = 0 , j = 0 , k = 0 , l = 0 , m = 0 , n = 0 , o = 0 ; g = i ; i = i + 384 | 0 ; h = g + 152 | 0 ; j = g + 312 | 0 ; k = g + 376 | 0 ; l = i ; i = i + ( f + 64 | 0 ) | 0 ; i = i + 7 >> 3 << 3 ; c [ k >> 2 ] = 0 ; c [ k + 4 >> 2 ] = 0 ; m = j | 0 ; bb ( m | 0 , d | 0 , 32 ) ; a2 ( h , d ) ; d = g + 32 | 0 ; aR ( d , h + 80 | 0 ) ; n = g + 72 | 0 ; aP ( n , h | 0 , d ) ; o = g + 112 | 0 ; aP ( o , h + 40 | 0 , d ) ; aU ( j + 32 | 0 , o ) ; o = g | 0 ; aU ( o , n ) ; n = j + 63 | 0 ; j = a [ n ] ^ a [ o ] << 7 ; a [ n ] = j ; aK ( l , k , e , f , 0 , m ) ; bb ( b | 0 , l | 0 , 64 ) ; l = b + 63 | 0 ; a [ l ] = a [ l ] | j & - 128 ; i = g ; return } function aJ ( b , d , e , f ) { b = b | 0 ; d = d | 0 ; e = e | 0 ; f = f | 0 ; var g = 0 , h = 0 , j = 0 , k = 0 , l = 0 , m = 0 , n = 0 , o = 0 , p = 0 , q = 0 , r = 0 , s = 0 , t = 0 , u = 0 , v = 0 , w = 0 , x = 0 , y = 0 ; g = i ; i = i + 240 | 0 ; h = g | 0 ; j = g + 40 | 0 ; k = g + 80 | 0 ; l = g + 200 | 0 ; m = f + 64 | 0 ; n = i ; i = i + m | 0 ; i = i + 7 >> 3 << 3 ; o = i ; i = i + m | 0 ; i = i + 7 >> 3 << 3 ; p = h | 0 ; aO ( p , d ) ; d = j | 0 ; q = c [ p >> 2 ] | 0 ; p = c [ h + 4 >> 2 ] | 0 ; r = c [ h + 8 >> 2 ] | 0 ; s = c [ h + 12 >> 2 ] | 0 ; t = c [ h + 16 >> 2 ] | 0 ; u = c [ h + 20 >> 2 ] | 0 ; v = c [ h + 24 >> 2 ] | 0 ; w = c [ h + 28 >> 2 ] | 0 ; x = c [ h + 32 >> 2 ] | 0 ; y = c [ h + 36 >> 2 ] | 0 ; c [ d >> 2 ] = q - 1 ; c [ j + 4 >> 2 ] = p ; c [ j + 8 >> 2 ] = r ; c [ j + 12 >> 2 ] = s ; c [ j + 16 >> 2 ] = t ; c [ j + 20 >> 2 ] = u ; c [ j + 24 >> 2 ] = v ; c [ j + 28 >> 2 ] = w ; c [ j + 32 >> 2 ] = x ; c [ j + 36 >> 2 ] = y ; j = k | 0 ; c [ j >> 2 ] = q + 1 ; c [ k + 4 >> 2 ] = p ; c [ k + 8 >> 2 ] = r ; c [ k + 12 >> 2 ] = s ; c [ k + 16 >> 2 ] = t ; c [ k + 20 >> 2 ] = u ; c [ k + 24 >> 2 ] = v ; c [ k + 28 >> 2 ] = w ; c [ k + 32 >> 2 ] = x ; c [ k + 36 >> 2 ] = y ; y = g + 120 | 0 ; aR ( y , j ) ; j = g + 160 | 0 ; aP ( j , d , y ) ; y = l | 0 ; aU ( y , j ) ; j = b + 63 | 0 ; d = a [ j ] | 0 ; k = l + 31 | 0 ; a [ k ] = a [ k ] | d & - 128 ; a [ j ] = d & 127 ; bb ( n | 0 , b | 0 , 64 ) ; bb ( n + 64 | 0 , e | 0 , f ) ; f = a5 ( o , g + 232 | 0 , n , m , 0 , y ) | 0 ; i = g ; return f | 0 } function aK ( b , d , e , f , g , h ) { b = b | 0 ; d = d | 0 ; e = e | 0 ; f = f | 0 ; g = g | 0 ; h = h | 0 ; var j = 0 , k = 0 , l = 0 , m = 0 , n = 0 , o = 0 , p = 0 , q = 0 , r = 0 , s = 0 , t = 0 , u = 0 , v = 0 , w = 0 , x = 0 , y = 0 , z = 0 , A = 0 , B = 0 ; j = i ; i = i + 872 | 0 ; k = j | 0 ; l = j + 200 | 0 ; m = j + 232 | 0 ; n = j + 272 | 0 ; o = j + 312 | 0 ; p = j + 352 | 0 ; q = j + 648 | 0 ; r = j + 712 | 0 ; s = j + 552 | 0 ; bb ( s | 0 , h + 32 | 0 , 32 ) ; t = bf ( f , g , 64 , 0 ) | 0 ; c [ d >> 2 ] = t ; c [ d + 4 >> 2 ] = D ; bc ( b + 64 | 0 , e | 0 , f | 0 ) ; e = b + 32 | 0 ; bc ( e | 0 , h | 0 , 32 ) ; d = j + 584 | 0 ; u = bf ( f , g , 32 , 0 ) | 0 ; g = p | 0 ; f = p + 128 | 0 ; bb ( f | 0 , 31520 , 64 ) ; v = p + 192 | 0 ; c [ v >> 2 ] = 0 ; c [ v + 4 >> 2 ] = 0 ; w = u ; if ( ( w | 0 ) != 0 ) { u = f ; f = w ; w = e ; x = 0 ; while ( 1 ) { y = 128 - x | 0 ; z = y >>> 0 > f >>> 0 ? f : y ; bb ( p + x | 0 , w | 0 , z ) ; y = z + x | 0 ; if ( ( y | 0 ) == 128 ) { a9 ( g , u ) ; A = 0 } else { A = y } y = bf ( c [ v >> 2 ] | 0 , c [ v + 4 >> 2 ] | 0 , z , 0 ) | 0 ; c [ v >> 2 ] = y ; c [ v + 4 >> 2 ] = D ; if ( ( f | 0 ) == ( z | 0 ) ) { break } else { f = f - z | 0 ; w = w + z | 0 ; x = A } } } ba ( g , 0 , 0 , d , 8 ) ; bb ( e | 0 , s | 0 , 32 ) ; a7 ( d ) ; a2 ( r , d ) ; s = m | 0 ; aR ( s , r + 80 | 0 ) ; m = n | 0 ; aP ( m , r | 0 , s ) ; n = o | 0 ; aP ( n , r + 40 | 0 , s ) ; aU ( b , n ) ; n = l | 0 ; aU ( n , m ) ; m = b + 31 | 0 ; a [ m ] = a [ m ] ^ a [ n ] << 7 ; n = q | 0 ; q = k | 0 ; m = k + 128 | 0 ; bb ( m | 0 , 31520 , 64 ) ; l = k + 192 | 0 ; c [ l >> 2 ] = 0 ; c [ l + 4 >> 2 ] = 0 ; s = t ; if ( ( s | 0 ) == 0 ) { ba ( q , 0 , 0 , n , 8 ) ; a7 ( n ) ; a6 ( e , n , h , d ) ; i = j ; return 0 } t = m ; m = s ; s = b ; b = 0 ; while ( 1 ) { r = 128 - b | 0 ; o = r >>> 0 > m >>> 0 ? m : r ; bb ( k + b | 0 , s | 0 , o ) ; r = o + b | 0 ; if ( ( r | 0 ) == 128 ) { a9 ( q , t ) ; B = 0 } else { B = r } r = bf ( c [ l >> 2 ] | 0 , c [ l + 4 >> 2 ] | 0 , o , 0 ) | 0 ; c [ l >> 2 ] = r ; c [ l + 4 >> 2 ] = D ; if ( ( m | 0 ) == ( o | 0 ) ) { break } else { m = m - o | 0 ; s = s + o | 0 ; b = B } } ba ( q , 0 , 0 , n , 8 ) ; a7 ( n ) ; a6 ( e , n , h , d ) ; i = j ; return 0 } function aL ( b , e , f ) { b = b | 0 ; e = e | 0 ; f = f | 0 ; var g = 0 , h = 0 , j = 0 , k = 0 , l = 0 , m = 0 , n = 0 , o = 0 , p = 0 , q = 0 , r = 0 , s = 0 , t = 0 , u = 0 , v = 0 , w = 0 , x = 0 , y = 0 , z = 0 , A = 0 , B = 0 , C = 0 , E = 0 , F = 0 , G = 0 , H = 0 , I = 0 , J = 0 , K = 0 , L = 0 , M = 0 , N = 0 , O = 0 , P = 0 , Q = 0 , R = 0 , S = 0 , T = 0 , U = 0 , V = 0 , W = 0 , X = 0 , Y = 0 , Z = 0 , _ = 0 , aa = 0 , ab = 0 , ac = 0 , ad = 0 , ae = 0 , af = 0 , ag = 0 , ah = 0 , ai = 0 , aj = 0 , ak = 0 , al = 0 , am = 0 , an = 0 , ao = 0 , ap = 0 , aq = 0 , ar = 0 , as = 0 , at = 0 , au = 0 , av = 0 , aw = 0 , ax = 0 , ay = 0 , az = 0 , aA = 0 , aB = 0 , aC = 0 , aD = 0 , aE = 0 , aF = 0 , aG = 0 , aH = 0 , aI = 0 , aJ = 0 , aK = 0 , aL = 0 , aO = 0 , aP = 0 , aR = 0 , aS = 0 , aT = 0 , aU = 0 , aV = 0 , aW = 0 , aX = 0 , aY = 0 , aZ = 0 , a _ = 0 , a$ = 0 , a0 = 0 , a1 = 0 , a2 = 0 , a3 = 0 , a4 = 0 , a5 = 0 , a6 = 0 , a7 = 0 , a8 = 0 , a9 = 0 , ba = 0 , bc = 0 , be = 0 , bh = 0 , bi = 0 , bj = 0 , bk
// EMSCRIPTEN_END_FUNCS
var ap = [ bx , bx ] ; var aq = [ by , by ] ; var ar = [ bz , bz ] ; var as = [ bA , bA ] ; return { _curve25519 _verify : aJ , _crypto _sign _ed25519 _ref10 _ge _scalarmult _base : a2 , _strlen : be , _memmove : bc , _sph _sha512 _init : a8 , _curve25519 _donna : aL , _memset : bd , _memcpy : bb , _curve25519 _sign : aI , stackAlloc : at , stackSave : au , stackRestore : av , setThrew : aw , setTempRet0 : ax , setTempRet1 : ay , setTempRet2 : az , setTempRet3 : aA , setTempRet4 : aB , setTempRet5 : aC , setTempRet6 : aD , setTempRet7 : aE , setTempRet8 : aF , setTempRet9 : aG , dynCall _ii : bt , dynCall _v : bu , dynCall _iii : bv , dynCall _vi : bw } } )
// EMSCRIPTEN_END_ASM
( { "Math" : Math , "Int8Array" : Int8Array , "Int16Array" : Int16Array , "Int32Array" : Int32Array , "Uint8Array" : Uint8Array , "Uint16Array" : Uint16Array , "Uint32Array" : Uint32Array , "Float32Array" : Float32Array , "Float64Array" : Float64Array } , { "abort" : abort , "assert" : assert , "asmPrintInt" : asmPrintInt , "asmPrintFloat" : asmPrintFloat , "copyTempDouble" : copyTempDouble , "copyTempFloat" : copyTempFloat , "min" : Math _min , "invoke_ii" : invoke _ii , "invoke_v" : invoke _v , "invoke_iii" : invoke _iii , "invoke_vi" : invoke _vi , "_llvm_lifetime_end" : _llvm _lifetime _end , "_malloc" : _malloc , "_free" : _free , "_llvm_lifetime_start" : _llvm _lifetime _start , "STACKTOP" : STACKTOP , "STACK_MAX" : STACK _MAX , "tempDoublePtr" : tempDoublePtr , "ABORT" : ABORT , "cttz_i8" : cttz _i8 , "ctlz_i8" : ctlz _i8 , "NaN" : NaN , "Infinity" : Infinity } , buffer ) ;
var _curve25519 _verify = Module [ "_curve25519_verify" ] = asm [ "_curve25519_verify" ] ;
var _crypto _sign _ed25519 _ref10 _ge _scalarmult _base = Module [ "_crypto_sign_ed25519_ref10_ge_scalarmult_base" ] = asm [ "_crypto_sign_ed25519_ref10_ge_scalarmult_base" ] ;
var _strlen = Module [ "_strlen" ] = asm [ "_strlen" ] ;
var _memmove = Module [ "_memmove" ] = asm [ "_memmove" ] ;
var _sph _sha512 _init = Module [ "_sph_sha512_init" ] = asm [ "_sph_sha512_init" ] ;
var _curve25519 _donna = Module [ "_curve25519_donna" ] = asm [ "_curve25519_donna" ] ;
var _memset = Module [ "_memset" ] = asm [ "_memset" ] ;
var _memcpy = Module [ "_memcpy" ] = asm [ "_memcpy" ] ;
var _curve25519 _sign = Module [ "_curve25519_sign" ] = asm [ "_curve25519_sign" ] ;
var dynCall _ii = Module [ "dynCall_ii" ] = asm [ "dynCall_ii" ] ;
var dynCall _v = Module [ "dynCall_v" ] = asm [ "dynCall_v" ] ;
var dynCall _iii = Module [ "dynCall_iii" ] = asm [ "dynCall_iii" ] ;
var dynCall _vi = Module [ "dynCall_vi" ] = asm [ "dynCall_vi" ] ;
Runtime . stackAlloc = function ( size ) { return asm [ 'stackAlloc' ] ( size ) } ;
Runtime . stackSave = function ( ) { return asm [ 'stackSave' ] ( ) } ;
Runtime . stackRestore = function ( top ) { asm [ 'stackRestore' ] ( top ) } ;
// TODO: strip out parts of this we do not need
//======= begin closure i64 code =======
// Copyright 2009 The Closure Library Authors. 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.
/ * *
* @ fileoverview Defines a Long class for representing a 64 - bit two ' s - complement
* integer value , which faithfully simulates the behavior of a Java "long" . This
* implementation is derived from LongLib in GWT .
*
* /
var i64Math = ( function ( ) { // Emscripten wrapper
var goog = { math : { } } ;
/ * *
* Constructs a 64 - bit two ' s - complement integer , given its low and high 32 - bit
* values as * signed * integers . See the from * functions below for more
* convenient ways of constructing Longs .
*
* The internal representation of a long is the two given signed , 32 - bit values .
* We use 32 - bit pieces because these are the size of integers on which
* Javascript performs bit - operations . For operations like addition and
* multiplication , we split each number into 16 - bit pieces , which can easily be
* multiplied within Javascript ' s floating - point representation without overflow
* or change in sign .
*
* In the algorithms below , we frequently reduce the negative case to the
* positive case by negating the input ( s ) and then post - processing the result .
* Note that we must ALWAYS check specially whether those values are MIN _VALUE
* ( - 2 ^ 63 ) because - MIN _VALUE == MIN _VALUE ( since 2 ^ 63 cannot be represented as
* a positive number , it overflows back into a negative ) . Not handling this
* case would often result in infinite recursion .
*
* @ param { number } low The low ( signed ) 32 bits of the long .
* @ param { number } high The high ( signed ) 32 bits of the long .
* @ constructor
* /
goog . math . Long = function ( low , high ) {
/ * *
* @ type { number }
* @ private
* /
this . low _ = low | 0 ; // force into 32 signed bits.
/ * *
* @ type { number }
* @ private
* /
this . high _ = high | 0 ; // force into 32 signed bits.
} ;
// NOTE: Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the
// from* methods on which they depend.
/ * *
* A cache of the Long representations of small integer values .
* @ type { ! Object }
* @ private
* /
goog . math . Long . IntCache _ = { } ;
/ * *
* Returns a Long representing the given ( 32 - bit ) integer value .
* @ param { number } value The 32 - bit integer in question .
* @ return { ! goog . math . Long } The corresponding Long value .
* /
goog . math . Long . fromInt = function ( value ) {
if ( - 128 <= value && value < 128 ) {
var cachedObj = goog . math . Long . IntCache _ [ value ] ;
if ( cachedObj ) {
return cachedObj ;
}
}
var obj = new goog . math . Long ( value | 0 , value < 0 ? - 1 : 0 ) ;
if ( - 128 <= value && value < 128 ) {
goog . math . Long . IntCache _ [ value ] = obj ;
}
return obj ;
} ;
/ * *
* Returns a Long representing the given value , provided that it is a finite
* number . Otherwise , zero is returned .
* @ param { number } value The number in question .
* @ return { ! goog . math . Long } The corresponding Long value .
* /
goog . math . Long . fromNumber = function ( value ) {
if ( isNaN ( value ) || ! isFinite ( value ) ) {
return goog . math . Long . ZERO ;
} else if ( value <= - goog . math . Long . TWO _PWR _63 _DBL _ ) {
return goog . math . Long . MIN _VALUE ;
} else if ( value + 1 >= goog . math . Long . TWO _PWR _63 _DBL _ ) {
return goog . math . Long . MAX _VALUE ;
} else if ( value < 0 ) {
return goog . math . Long . fromNumber ( - value ) . negate ( ) ;
} else {
return new goog . math . Long (
( value % goog . math . Long . TWO _PWR _32 _DBL _ ) | 0 ,
( value / goog . math . Long . TWO _PWR _32 _DBL _ ) | 0 ) ;
}
} ;
/ * *
* Returns a Long representing the 64 - bit integer that comes by concatenating
* the given high and low bits . Each is assumed to use 32 bits .
* @ param { number } lowBits The low 32 - bits .
* @ param { number } highBits The high 32 - bits .
* @ return { ! goog . math . Long } The corresponding Long value .
* /
goog . math . Long . fromBits = function ( lowBits , highBits ) {
return new goog . math . Long ( lowBits , highBits ) ;
} ;
/ * *
* Returns a Long representation of the given string , written using the given
* radix .
* @ param { string } str The textual representation of the Long .
* @ param { number = } opt _radix The radix in which the text is written .
* @ return { ! goog . math . Long } The corresponding Long value .
* /
goog . math . Long . fromString = function ( str , opt _radix ) {
if ( str . length == 0 ) {
throw Error ( 'number format error: empty string' ) ;
}
var radix = opt _radix || 10 ;
if ( radix < 2 || 36 < radix ) {
throw Error ( 'radix out of range: ' + radix ) ;
}
if ( str . charAt ( 0 ) == '-' ) {
return goog . math . Long . fromString ( str . substring ( 1 ) , radix ) . negate ( ) ;
} else if ( str . indexOf ( '-' ) >= 0 ) {
throw Error ( 'number format error: interior "-" character: ' + str ) ;
}
// Do several (8) digits each time through the loop, so as to
// minimize the calls to the very expensive emulated div.
var radixToPower = goog . math . Long . fromNumber ( Math . pow ( radix , 8 ) ) ;
var result = goog . math . Long . ZERO ;
for ( var i = 0 ; i < str . length ; i += 8 ) {
var size = Math . min ( 8 , str . length - i ) ;
var value = parseInt ( str . substring ( i , i + size ) , radix ) ;
if ( size < 8 ) {
var power = goog . math . Long . fromNumber ( Math . pow ( radix , size ) ) ;
result = result . multiply ( power ) . add ( goog . math . Long . fromNumber ( value ) ) ;
} else {
result = result . multiply ( radixToPower ) ;
result = result . add ( goog . math . Long . fromNumber ( value ) ) ;
}
}
return result ;
} ;
// NOTE: the compiler should inline these constant values below and then remove
// these variables, so there should be no runtime penalty for these.
/ * *
* Number used repeated below in calculations . This must appear before the
* first call to any from * function below .
* @ type { number }
* @ private
* /
goog . math . Long . TWO _PWR _16 _DBL _ = 1 << 16 ;
/ * *
* @ type { number }
* @ private
* /
goog . math . Long . TWO _PWR _24 _DBL _ = 1 << 24 ;
/ * *
* @ type { number }
* @ private
* /
goog . math . Long . TWO _PWR _32 _DBL _ =
goog . math . Long . TWO _PWR _16 _DBL _ * goog . math . Long . TWO _PWR _16 _DBL _ ;
/ * *
* @ type { number }
* @ private
* /
goog . math . Long . TWO _PWR _31 _DBL _ =
goog . math . Long . TWO _PWR _32 _DBL _ / 2 ;
/ * *
* @ type { number }
* @ private
* /
goog . math . Long . TWO _PWR _48 _DBL _ =
goog . math . Long . TWO _PWR _32 _DBL _ * goog . math . Long . TWO _PWR _16 _DBL _ ;
/ * *
* @ type { number }
* @ private
* /
goog . math . Long . TWO _PWR _64 _DBL _ =
goog . math . Long . TWO _PWR _32 _DBL _ * goog . math . Long . TWO _PWR _32 _DBL _ ;
/ * *
* @ type { number }
* @ private
* /
goog . math . Long . TWO _PWR _63 _DBL _ =
goog . math . Long . TWO _PWR _64 _DBL _ / 2 ;
/** @type {!goog.math.Long} */
goog . math . Long . ZERO = goog . math . Long . fromInt ( 0 ) ;
/** @type {!goog.math.Long} */
goog . math . Long . ONE = goog . math . Long . fromInt ( 1 ) ;
/** @type {!goog.math.Long} */
goog . math . Long . NEG _ONE = goog . math . Long . fromInt ( - 1 ) ;
/** @type {!goog.math.Long} */
goog . math . Long . MAX _VALUE =
goog . math . Long . fromBits ( 0xFFFFFFFF | 0 , 0x7FFFFFFF | 0 ) ;
/** @type {!goog.math.Long} */
goog . math . Long . MIN _VALUE = goog . math . Long . fromBits ( 0 , 0x80000000 | 0 ) ;
/ * *
* @ type { ! goog . math . Long }
* @ private
* /
goog . math . Long . TWO _PWR _24 _ = goog . math . Long . fromInt ( 1 << 24 ) ;
/** @return {number} The value, assuming it is a 32-bit integer. */
goog . math . Long . prototype . toInt = function ( ) {
return this . low _ ;
} ;
/** @return {number} The closest floating-point representation to this value. */
goog . math . Long . prototype . toNumber = function ( ) {
return this . high _ * goog . math . Long . TWO _PWR _32 _DBL _ +
this . getLowBitsUnsigned ( ) ;
} ;
/ * *
* @ param { number = } opt _radix The radix in which the text should be written .
* @ return { string } The textual representation of this value .
* /
goog . math . Long . prototype . toString = function ( opt _radix ) {
var radix = opt _radix || 10 ;
if ( radix < 2 || 36 < radix ) {
throw Error ( 'radix out of range: ' + radix ) ;
}
if ( this . isZero ( ) ) {
return '0' ;
}
if ( this . isNegative ( ) ) {
if ( this . equals ( goog . math . Long . MIN _VALUE ) ) {
// We need to change the Long value before it can be negated, so we remove
// the bottom-most digit in this base and then recurse to do the rest.
var radixLong = goog . math . Long . fromNumber ( radix ) ;
var div = this . div ( radixLong ) ;
var rem = div . multiply ( radixLong ) . subtract ( this ) ;
return div . toString ( radix ) + rem . toInt ( ) . toString ( radix ) ;
} else {
return '-' + this . negate ( ) . toString ( radix ) ;
}
}
// Do several (6) digits each time through the loop, so as to
// minimize the calls to the very expensive emulated div.
var radixToPower = goog . math . Long . fromNumber ( Math . pow ( radix , 6 ) ) ;
var rem = this ;
var result = '' ;
while ( true ) {
var remDiv = rem . div ( radixToPower ) ;
var intval = rem . subtract ( remDiv . multiply ( radixToPower ) ) . toInt ( ) ;
var digits = intval . toString ( radix ) ;
rem = remDiv ;
if ( rem . isZero ( ) ) {
return digits + result ;
} else {
while ( digits . length < 6 ) {
digits = '0' + digits ;
}
result = '' + digits + result ;
}
}
} ;
/** @return {number} The high 32-bits as a signed value. */
goog . math . Long . prototype . getHighBits = function ( ) {
return this . high _ ;
} ;
/** @return {number} The low 32-bits as a signed value. */
goog . math . Long . prototype . getLowBits = function ( ) {
return this . low _ ;
} ;
/** @return {number} The low 32-bits as an unsigned value. */
goog . math . Long . prototype . getLowBitsUnsigned = function ( ) {
return ( this . low _ >= 0 ) ?
this . low _ : goog . math . Long . TWO _PWR _32 _DBL _ + this . low _ ;
} ;
/ * *
* @ return { number } Returns the number of bits needed to represent the absolute
* value of this Long .
* /
goog . math . Long . prototype . getNumBitsAbs = function ( ) {
if ( this . isNegative ( ) ) {
if ( this . equals ( goog . math . Long . MIN _VALUE ) ) {
return 64 ;
} else {
return this . negate ( ) . getNumBitsAbs ( ) ;
}
} else {
var val = this . high _ != 0 ? this . high _ : this . low _ ;
for ( var bit = 31 ; bit > 0 ; bit -- ) {
if ( ( val & ( 1 << bit ) ) != 0 ) {
break ;
}
}
return this . high _ != 0 ? bit + 33 : bit + 1 ;
}
} ;
/** @return {boolean} Whether this value is zero. */
goog . math . Long . prototype . isZero = function ( ) {
return this . high _ == 0 && this . low _ == 0 ;
} ;
/** @return {boolean} Whether this value is negative. */
goog . math . Long . prototype . isNegative = function ( ) {
return this . high _ < 0 ;
} ;
/** @return {boolean} Whether this value is odd. */
goog . math . Long . prototype . isOdd = function ( ) {
return ( this . low _ & 1 ) == 1 ;
} ;
/ * *
* @ param { goog . math . Long } other Long to compare against .
* @ return { boolean } Whether this Long equals the other .
* /
goog . math . Long . prototype . equals = function ( other ) {
return ( this . high _ == other . high _ ) && ( this . low _ == other . low _ ) ;
} ;
/ * *
* @ param { goog . math . Long } other Long to compare against .
* @ return { boolean } Whether this Long does not equal the other .
* /
goog . math . Long . prototype . notEquals = function ( other ) {
return ( this . high _ != other . high _ ) || ( this . low _ != other . low _ ) ;
} ;
/ * *
* @ param { goog . math . Long } other Long to compare against .
* @ return { boolean } Whether this Long is less than the other .
* /
goog . math . Long . prototype . lessThan = function ( other ) {
return this . compare ( other ) < 0 ;
} ;
/ * *
* @ param { goog . math . Long } other Long to compare against .
* @ return { boolean } Whether this Long is less than or equal to the other .
* /
goog . math . Long . prototype . lessThanOrEqual = function ( other ) {
return this . compare ( other ) <= 0 ;
} ;
/ * *
* @ param { goog . math . Long } other Long to compare against .
* @ return { boolean } Whether this Long is greater than the other .
* /
goog . math . Long . prototype . greaterThan = function ( other ) {
return this . compare ( other ) > 0 ;
} ;
/ * *
* @ param { goog . math . Long } other Long to compare against .
* @ return { boolean } Whether this Long is greater than or equal to the other .
* /
goog . math . Long . prototype . greaterThanOrEqual = function ( other ) {
return this . compare ( other ) >= 0 ;
} ;
/ * *
* Compares this Long with the given one .
* @ param { goog . math . Long } other Long to compare against .
* @ return { number } 0 if they are the same , 1 if the this is greater , and - 1
* if the given one is greater .
* /
goog . math . Long . prototype . compare = function ( other ) {
if ( this . equals ( other ) ) {
return 0 ;
}
var thisNeg = this . isNegative ( ) ;
var otherNeg = other . isNegative ( ) ;
if ( thisNeg && ! otherNeg ) {
return - 1 ;
}
if ( ! thisNeg && otherNeg ) {
return 1 ;
}
// at this point, the signs are the same, so subtraction will not overflow
if ( this . subtract ( other ) . isNegative ( ) ) {
return - 1 ;
} else {
return 1 ;
}
} ;
/** @return {!goog.math.Long} The negation of this value. */
goog . math . Long . prototype . negate = function ( ) {
if ( this . equals ( goog . math . Long . MIN _VALUE ) ) {
return goog . math . Long . MIN _VALUE ;
} else {
return this . not ( ) . add ( goog . math . Long . ONE ) ;
}
} ;
/ * *
* Returns the sum of this and the given Long .
* @ param { goog . math . Long } other Long to add to this one .
* @ return { ! goog . math . Long } The sum of this and the given Long .
* /
goog . math . Long . prototype . add = function ( other ) {
// Divide each number into 4 chunks of 16 bits, and then sum the chunks.
var a48 = this . high _ >>> 16 ;
var a32 = this . high _ & 0xFFFF ;
var a16 = this . low _ >>> 16 ;
var a00 = this . low _ & 0xFFFF ;
var b48 = other . high _ >>> 16 ;
var b32 = other . high _ & 0xFFFF ;
var b16 = other . low _ >>> 16 ;
var b00 = other . low _ & 0xFFFF ;
var c48 = 0 , c32 = 0 , c16 = 0 , c00 = 0 ;
c00 += a00 + b00 ;
c16 += c00 >>> 16 ;
c00 &= 0xFFFF ;
c16 += a16 + b16 ;
c32 += c16 >>> 16 ;
c16 &= 0xFFFF ;
c32 += a32 + b32 ;
c48 += c32 >>> 16 ;
c32 &= 0xFFFF ;
c48 += a48 + b48 ;
c48 &= 0xFFFF ;
return goog . math . Long . fromBits ( ( c16 << 16 ) | c00 , ( c48 << 16 ) | c32 ) ;
} ;
/ * *
* Returns the difference of this and the given Long .
* @ param { goog . math . Long } other Long to subtract from this .
* @ return { ! goog . math . Long } The difference of this and the given Long .
* /
goog . math . Long . prototype . subtract = function ( other ) {
return this . add ( other . negate ( ) ) ;
} ;
/ * *
* Returns the product of this and the given long .
* @ param { goog . math . Long } other Long to multiply with this .
* @ return { ! goog . math . Long } The product of this and the other .
* /
goog . math . Long . prototype . multiply = function ( other ) {
if ( this . isZero ( ) ) {
return goog . math . Long . ZERO ;
} else if ( other . isZero ( ) ) {
return goog . math . Long . ZERO ;
}
if ( this . equals ( goog . math . Long . MIN _VALUE ) ) {
return other . isOdd ( ) ? goog . math . Long . MIN _VALUE : goog . math . Long . ZERO ;
} else if ( other . equals ( goog . math . Long . MIN _VALUE ) ) {
return this . isOdd ( ) ? goog . math . Long . MIN _VALUE : goog . math . Long . ZERO ;
}
if ( this . isNegative ( ) ) {
if ( other . isNegative ( ) ) {
return this . negate ( ) . multiply ( other . negate ( ) ) ;
} else {
return this . negate ( ) . multiply ( other ) . negate ( ) ;
}
} else if ( other . isNegative ( ) ) {
return this . multiply ( other . negate ( ) ) . negate ( ) ;
}
// If both longs are small, use float multiplication
if ( this . lessThan ( goog . math . Long . TWO _PWR _24 _ ) &&
other . lessThan ( goog . math . Long . TWO _PWR _24 _ ) ) {
return goog . math . Long . fromNumber ( this . toNumber ( ) * other . toNumber ( ) ) ;
}
// Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
// We can skip products that would overflow.
var a48 = this . high _ >>> 16 ;
var a32 = this . high _ & 0xFFFF ;
var a16 = this . low _ >>> 16 ;
var a00 = this . low _ & 0xFFFF ;
var b48 = other . high _ >>> 16 ;
var b32 = other . high _ & 0xFFFF ;
var b16 = other . low _ >>> 16 ;
var b00 = other . low _ & 0xFFFF ;
var c48 = 0 , c32 = 0 , c16 = 0 , c00 = 0 ;
c00 += a00 * b00 ;
c16 += c00 >>> 16 ;
c00 &= 0xFFFF ;
c16 += a16 * b00 ;
c32 += c16 >>> 16 ;
c16 &= 0xFFFF ;
c16 += a00 * b16 ;
c32 += c16 >>> 16 ;
c16 &= 0xFFFF ;
c32 += a32 * b00 ;
c48 += c32 >>> 16 ;
c32 &= 0xFFFF ;
c32 += a16 * b16 ;
c48 += c32 >>> 16 ;
c32 &= 0xFFFF ;
c32 += a00 * b32 ;
c48 += c32 >>> 16 ;
c32 &= 0xFFFF ;
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48 ;
c48 &= 0xFFFF ;
return goog . math . Long . fromBits ( ( c16 << 16 ) | c00 , ( c48 << 16 ) | c32 ) ;
} ;
/ * *
* Returns this Long divided by the given one .
* @ param { goog . math . Long } other Long by which to divide .
* @ return { ! goog . math . Long } This Long divided by the given one .
* /
goog . math . Long . prototype . div = function ( other ) {
if ( other . isZero ( ) ) {
throw Error ( 'division by zero' ) ;
} else if ( this . isZero ( ) ) {
return goog . math . Long . ZERO ;
}
if ( this . equals ( goog . math . Long . MIN _VALUE ) ) {
if ( other . equals ( goog . math . Long . ONE ) ||
other . equals ( goog . math . Long . NEG _ONE ) ) {
return goog . math . Long . MIN _VALUE ; // recall that -MIN_VALUE == MIN_VALUE
} else if ( other . equals ( goog . math . Long . MIN _VALUE ) ) {
return goog . math . Long . ONE ;
} else {
// At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
var halfThis = this . shiftRight ( 1 ) ;
var approx = halfThis . div ( other ) . shiftLeft ( 1 ) ;
if ( approx . equals ( goog . math . Long . ZERO ) ) {
return other . isNegative ( ) ? goog . math . Long . ONE : goog . math . Long . NEG _ONE ;
} else {
var rem = this . subtract ( other . multiply ( approx ) ) ;
var result = approx . add ( rem . div ( other ) ) ;
return result ;
}
}
} else if ( other . equals ( goog . math . Long . MIN _VALUE ) ) {
return goog . math . Long . ZERO ;
}
if ( this . isNegative ( ) ) {
if ( other . isNegative ( ) ) {
return this . negate ( ) . div ( other . negate ( ) ) ;
} else {
return this . negate ( ) . div ( other ) . negate ( ) ;
}
} else if ( other . isNegative ( ) ) {
return this . div ( other . negate ( ) ) . negate ( ) ;
}
// Repeat the following until the remainder is less than other: find a
// floating-point that approximates remainder / other *from below*, add this
// into the result, and subtract it from the remainder. It is critical that
// the approximate value is less than or equal to the real value so that the
// remainder never becomes negative.
var res = goog . math . Long . ZERO ;
var rem = this ;
while ( rem . greaterThanOrEqual ( other ) ) {
// Approximate the result of division. This may be a little greater or
// smaller than the actual value.
var approx = Math . max ( 1 , Math . floor ( rem . toNumber ( ) / other . toNumber ( ) ) ) ;
// We will tweak the approximate result by changing it in the 48-th digit or
// the smallest non-fractional digit, whichever is larger.
var log2 = Math . ceil ( Math . log ( approx ) / Math . LN2 ) ;
var delta = ( log2 <= 48 ) ? 1 : Math . pow ( 2 , log2 - 48 ) ;
// Decrease the approximation until it is smaller than the remainder. Note
// that if it is too large, the product overflows and is negative.
var approxRes = goog . math . Long . fromNumber ( approx ) ;
var approxRem = approxRes . multiply ( other ) ;
while ( approxRem . isNegative ( ) || approxRem . greaterThan ( rem ) ) {
approx -= delta ;
approxRes = goog . math . Long . fromNumber ( approx ) ;
approxRem = approxRes . multiply ( other ) ;
}
// We know the answer can't be zero... and actually, zero would cause
// infinite recursion since we would make no progress.
if ( approxRes . isZero ( ) ) {
approxRes = goog . math . Long . ONE ;
}
res = res . add ( approxRes ) ;
rem = rem . subtract ( approxRem ) ;
}
return res ;
} ;
/ * *
* Returns this Long modulo the given one .
* @ param { goog . math . Long } other Long by which to mod .
* @ return { ! goog . math . Long } This Long modulo the given one .
* /
goog . math . Long . prototype . modulo = function ( other ) {
return this . subtract ( this . div ( other ) . multiply ( other ) ) ;
} ;
/** @return {!goog.math.Long} The bitwise-NOT of this value. */
goog . math . Long . prototype . not = function ( ) {
return goog . math . Long . fromBits ( ~ this . low _ , ~ this . high _ ) ;
} ;
/ * *
* Returns the bitwise - AND of this Long and the given one .
* @ param { goog . math . Long } other The Long with which to AND .
* @ return { ! goog . math . Long } The bitwise - AND of this and the other .
* /
goog . math . Long . prototype . and = function ( other ) {
return goog . math . Long . fromBits ( this . low _ & other . low _ ,
this . high _ & other . high _ ) ;
} ;
/ * *
* Returns the bitwise - OR of this Long and the given one .
* @ param { goog . math . Long } other The Long with which to OR .
* @ return { ! goog . math . Long } The bitwise - OR of this and the other .
* /
goog . math . Long . prototype . or = function ( other ) {
return goog . math . Long . fromBits ( this . low _ | other . low _ ,
this . high _ | other . high _ ) ;
} ;
/ * *
* Returns the bitwise - XOR of this Long and the given one .
* @ param { goog . math . Long } other The Long with which to XOR .
* @ return { ! goog . math . Long } The bitwise - XOR of this and the other .
* /
goog . math . Long . prototype . xor = function ( other ) {
return goog . math . Long . fromBits ( this . low _ ^ other . low _ ,
this . high _ ^ other . high _ ) ;
} ;
/ * *
* Returns this Long with bits shifted to the left by the given amount .
* @ param { number } numBits The number of bits by which to shift .
* @ return { ! goog . math . Long } This shifted to the left by the given amount .
* /
goog . math . Long . prototype . shiftLeft = function ( numBits ) {
numBits &= 63 ;
if ( numBits == 0 ) {
return this ;
} else {
var low = this . low _ ;
if ( numBits < 32 ) {
var high = this . high _ ;
return goog . math . Long . fromBits (
low << numBits ,
( high << numBits ) | ( low >>> ( 32 - numBits ) ) ) ;
} else {
return goog . math . Long . fromBits ( 0 , low << ( numBits - 32 ) ) ;
}
}
} ;
/ * *
* Returns this Long with bits shifted to the right by the given amount .
* @ param { number } numBits The number of bits by which to shift .
* @ return { ! goog . math . Long } This shifted to the right by the given amount .
* /
goog . math . Long . prototype . shiftRight = function ( numBits ) {
numBits &= 63 ;
if ( numBits == 0 ) {
return this ;
} else {
var high = this . high _ ;
if ( numBits < 32 ) {
var low = this . low _ ;
return goog . math . Long . fromBits (
( low >>> numBits ) | ( high << ( 32 - numBits ) ) ,
high >> numBits ) ;
} else {
return goog . math . Long . fromBits (
high >> ( numBits - 32 ) ,
high >= 0 ? 0 : - 1 ) ;
}
}
} ;
/ * *
* Returns this Long with bits shifted to the right by the given amount , with
* the new top bits matching the current sign bit .
* @ param { number } numBits The number of bits by which to shift .
* @ return { ! goog . math . Long } This shifted to the right by the given amount , with
* zeros placed into the new leading bits .
* /
goog . math . Long . prototype . shiftRightUnsigned = function ( numBits ) {
numBits &= 63 ;
if ( numBits == 0 ) {
return this ;
} else {
var high = this . high _ ;
if ( numBits < 32 ) {
var low = this . low _ ;
return goog . math . Long . fromBits (
( low >>> numBits ) | ( high << ( 32 - numBits ) ) ,
high >>> numBits ) ;
} else if ( numBits == 32 ) {
return goog . math . Long . fromBits ( high , 0 ) ;
} else {
return goog . math . Long . fromBits ( high >>> ( numBits - 32 ) , 0 ) ;
}
}
} ;
//======= begin jsbn =======
var navigator = { appName : 'Modern Browser' } ; // polyfill a little
// Copyright (c) 2005 Tom Wu
// All Rights Reserved.
// http://www-cs-students.stanford.edu/~tjw/jsbn/
/ *
* Copyright ( c ) 2003 - 2005 Tom Wu
* All Rights Reserved .
*
* Permission is hereby granted , free of charge , to any person obtaining
* a copy of this software and associated documentation files ( the
* "Software" ) , to deal in the Software without restriction , including
* without limitation the rights to use , copy , modify , merge , publish ,
* distribute , sublicense , and / or sell copies of the Software , and to
* permit persons to whom the Software is furnished to do so , subject to
* the following conditions :
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software .
*
2015-02-20 15:05:32 -08:00
* THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND ,
* EXPRESS , IMPLIED OR OTHERWISE , INCLUDING WITHOUT LIMITATION , ANY
* WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE .
2015-02-10 16:39:50 -08:00
*
* IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL , INCIDENTAL ,
* INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND , OR ANY DAMAGES WHATSOEVER
* RESULTING FROM LOSS OF USE , DATA OR PROFITS , WHETHER OR NOT ADVISED OF
* THE POSSIBILITY OF DAMAGE , AND ON ANY THEORY OF LIABILITY , ARISING OUT
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
*
* In addition , the following condition applies :
*
* All redistributions must retain an intact copy of this copyright notice
* and disclaimer .
* /
// Basic JavaScript BN library - subset useful for RSA encryption.
// Bits per digit
var dbits ;
// JavaScript engine analysis
var canary = 0xdeadbeefcafe ;
var j _lm = ( ( canary & 0xffffff ) == 0xefcafe ) ;
// (public) Constructor
function BigInteger ( a , b , c ) {
if ( a != null )
if ( "number" == typeof a ) this . fromNumber ( a , b , c ) ;
else if ( b == null && "string" != typeof a ) this . fromString ( a , 256 ) ;
else this . fromString ( a , b ) ;
}
// return new, unset BigInteger
function nbi ( ) { return new BigInteger ( null ) ; }
// am: Compute w_j += (x*this_i), propagate carries,
// c is initial carry, returns final carry.
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
// We need to select the fastest one that works in this environment.
// am1: use a single mult and divide to get the high bits,
// max digit bits should be 26 because
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
function am1 ( i , x , w , j , c , n ) {
while ( -- n >= 0 ) {
var v = x * this [ i ++ ] + w [ j ] + c ;
c = Math . floor ( v / 0x4000000 ) ;
w [ j ++ ] = v & 0x3ffffff ;
}
return c ;
}
// am2 avoids a big mult-and-extract completely.
// Max digit bits should be <= 30 because we do bitwise ops
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
function am2 ( i , x , w , j , c , n ) {
var xl = x & 0x7fff , xh = x >> 15 ;
while ( -- n >= 0 ) {
var l = this [ i ] & 0x7fff ;
var h = this [ i ++ ] >> 15 ;
var m = xh * l + h * xl ;
l = xl * l + ( ( m & 0x7fff ) << 15 ) + w [ j ] + ( c & 0x3fffffff ) ;
c = ( l >>> 30 ) + ( m >>> 15 ) + xh * h + ( c >>> 30 ) ;
w [ j ++ ] = l & 0x3fffffff ;
}
return c ;
}
// Alternately, set max digit bits to 28 since some
// browsers slow down when dealing with 32-bit numbers.
function am3 ( i , x , w , j , c , n ) {
var xl = x & 0x3fff , xh = x >> 14 ;
while ( -- n >= 0 ) {
var l = this [ i ] & 0x3fff ;
var h = this [ i ++ ] >> 14 ;
var m = xh * l + h * xl ;
l = xl * l + ( ( m & 0x3fff ) << 14 ) + w [ j ] + c ;
c = ( l >> 28 ) + ( m >> 14 ) + xh * h ;
w [ j ++ ] = l & 0xfffffff ;
}
return c ;
}
if ( j _lm && ( navigator . appName == "Microsoft Internet Explorer" ) ) {
BigInteger . prototype . am = am2 ;
dbits = 30 ;
}
else if ( j _lm && ( navigator . appName != "Netscape" ) ) {
BigInteger . prototype . am = am1 ;
dbits = 26 ;
}
else { // Mozilla/Netscape seems to prefer am3
BigInteger . prototype . am = am3 ;
dbits = 28 ;
}
BigInteger . prototype . DB = dbits ;
BigInteger . prototype . DM = ( ( 1 << dbits ) - 1 ) ;
BigInteger . prototype . DV = ( 1 << dbits ) ;
var BI _FP = 52 ;
BigInteger . prototype . FV = Math . pow ( 2 , BI _FP ) ;
BigInteger . prototype . F1 = BI _FP - dbits ;
BigInteger . prototype . F2 = 2 * dbits - BI _FP ;
// Digit conversions
var BI _RM = "0123456789abcdefghijklmnopqrstuvwxyz" ;
var BI _RC = new Array ( ) ;
var rr , vv ;
rr = "0" . charCodeAt ( 0 ) ;
for ( vv = 0 ; vv <= 9 ; ++ vv ) BI _RC [ rr ++ ] = vv ;
rr = "a" . charCodeAt ( 0 ) ;
for ( vv = 10 ; vv < 36 ; ++ vv ) BI _RC [ rr ++ ] = vv ;
rr = "A" . charCodeAt ( 0 ) ;
for ( vv = 10 ; vv < 36 ; ++ vv ) BI _RC [ rr ++ ] = vv ;
function int2char ( n ) { return BI _RM . charAt ( n ) ; }
function intAt ( s , i ) {
var c = BI _RC [ s . charCodeAt ( i ) ] ;
return ( c == null ) ? - 1 : c ;
}
// (protected) copy this to r
function bnpCopyTo ( r ) {
for ( var i = this . t - 1 ; i >= 0 ; -- i ) r [ i ] = this [ i ] ;
r . t = this . t ;
r . s = this . s ;
}
// (protected) set from integer value x, -DV <= x < DV
function bnpFromInt ( x ) {
this . t = 1 ;
this . s = ( x < 0 ) ? - 1 : 0 ;
if ( x > 0 ) this [ 0 ] = x ;
else if ( x < - 1 ) this [ 0 ] = x + DV ;
else this . t = 0 ;
}
// return bigint initialized to value
function nbv ( i ) { var r = nbi ( ) ; r . fromInt ( i ) ; return r ; }
// (protected) set from string and radix
function bnpFromString ( s , b ) {
var k ;
if ( b == 16 ) k = 4 ;
else if ( b == 8 ) k = 3 ;
else if ( b == 256 ) k = 8 ; // byte array
else if ( b == 2 ) k = 1 ;
else if ( b == 32 ) k = 5 ;
else if ( b == 4 ) k = 2 ;
else { this . fromRadix ( s , b ) ; return ; }
this . t = 0 ;
this . s = 0 ;
var i = s . length , mi = false , sh = 0 ;
while ( -- i >= 0 ) {
var x = ( k == 8 ) ? s [ i ] & 0xff : intAt ( s , i ) ;
if ( x < 0 ) {
if ( s . charAt ( i ) == "-" ) mi = true ;
continue ;
}
mi = false ;
if ( sh == 0 )
this [ this . t ++ ] = x ;
else if ( sh + k > this . DB ) {
this [ this . t - 1 ] |= ( x & ( ( 1 << ( this . DB - sh ) ) - 1 ) ) << sh ;
this [ this . t ++ ] = ( x >> ( this . DB - sh ) ) ;
}
else
this [ this . t - 1 ] |= x << sh ;
sh += k ;
if ( sh >= this . DB ) sh -= this . DB ;
}
if ( k == 8 && ( s [ 0 ] & 0x80 ) != 0 ) {
this . s = - 1 ;
if ( sh > 0 ) this [ this . t - 1 ] |= ( ( 1 << ( this . DB - sh ) ) - 1 ) << sh ;
}
this . clamp ( ) ;
if ( mi ) BigInteger . ZERO . subTo ( this , this ) ;
}
// (protected) clamp off excess high words
function bnpClamp ( ) {
var c = this . s & this . DM ;
while ( this . t > 0 && this [ this . t - 1 ] == c ) -- this . t ;
}
// (public) return string representation in given radix
function bnToString ( b ) {
if ( this . s < 0 ) return "-" + this . negate ( ) . toString ( b ) ;
var k ;
if ( b == 16 ) k = 4 ;
else if ( b == 8 ) k = 3 ;
else if ( b == 2 ) k = 1 ;
else if ( b == 32 ) k = 5 ;
else if ( b == 4 ) k = 2 ;
else return this . toRadix ( b ) ;
var km = ( 1 << k ) - 1 , d , m = false , r = "" , i = this . t ;
var p = this . DB - ( i * this . DB ) % k ;
if ( i -- > 0 ) {
if ( p < this . DB && ( d = this [ i ] >> p ) > 0 ) { m = true ; r = int2char ( d ) ; }
while ( i >= 0 ) {
if ( p < k ) {
d = ( this [ i ] & ( ( 1 << p ) - 1 ) ) << ( k - p ) ;
d |= this [ -- i ] >> ( p += this . DB - k ) ;
}
else {
d = ( this [ i ] >> ( p -= k ) ) & km ;
if ( p <= 0 ) { p += this . DB ; -- i ; }
}
if ( d > 0 ) m = true ;
if ( m ) r += int2char ( d ) ;
}
}
return m ? r : "0" ;
}
// (public) -this
function bnNegate ( ) { var r = nbi ( ) ; BigInteger . ZERO . subTo ( this , r ) ; return r ; }
// (public) |this|
function bnAbs ( ) { return ( this . s < 0 ) ? this . negate ( ) : this ; }
// (public) return + if this > a, - if this < a, 0 if equal
function bnCompareTo ( a ) {
var r = this . s - a . s ;
if ( r != 0 ) return r ;
var i = this . t ;
r = i - a . t ;
if ( r != 0 ) return ( this . s < 0 ) ? - r : r ;
while ( -- i >= 0 ) if ( ( r = this [ i ] - a [ i ] ) != 0 ) return r ;
return 0 ;
}
// returns bit length of the integer x
function nbits ( x ) {
var r = 1 , t ;
if ( ( t = x >>> 16 ) != 0 ) { x = t ; r += 16 ; }
if ( ( t = x >> 8 ) != 0 ) { x = t ; r += 8 ; }
if ( ( t = x >> 4 ) != 0 ) { x = t ; r += 4 ; }
if ( ( t = x >> 2 ) != 0 ) { x = t ; r += 2 ; }
if ( ( t = x >> 1 ) != 0 ) { x = t ; r += 1 ; }
return r ;
}
// (public) return the number of bits in "this"
function bnBitLength ( ) {
if ( this . t <= 0 ) return 0 ;
return this . DB * ( this . t - 1 ) + nbits ( this [ this . t - 1 ] ^ ( this . s & this . DM ) ) ;
}
// (protected) r = this << n*DB
function bnpDLShiftTo ( n , r ) {
var i ;
for ( i = this . t - 1 ; i >= 0 ; -- i ) r [ i + n ] = this [ i ] ;
for ( i = n - 1 ; i >= 0 ; -- i ) r [ i ] = 0 ;
r . t = this . t + n ;
r . s = this . s ;
}
// (protected) r = this >> n*DB
function bnpDRShiftTo ( n , r ) {
for ( var i = n ; i < this . t ; ++ i ) r [ i - n ] = this [ i ] ;
r . t = Math . max ( this . t - n , 0 ) ;
r . s = this . s ;
}
// (protected) r = this << n
function bnpLShiftTo ( n , r ) {
var bs = n % this . DB ;
var cbs = this . DB - bs ;
var bm = ( 1 << cbs ) - 1 ;
var ds = Math . floor ( n / this . DB ) , c = ( this . s << bs ) & this . DM , i ;
for ( i = this . t - 1 ; i >= 0 ; -- i ) {
r [ i + ds + 1 ] = ( this [ i ] >> cbs ) | c ;
c = ( this [ i ] & bm ) << bs ;
}
for ( i = ds - 1 ; i >= 0 ; -- i ) r [ i ] = 0 ;
r [ ds ] = c ;
r . t = this . t + ds + 1 ;
r . s = this . s ;
r . clamp ( ) ;
}
// (protected) r = this >> n
function bnpRShiftTo ( n , r ) {
r . s = this . s ;
var ds = Math . floor ( n / this . DB ) ;
if ( ds >= this . t ) { r . t = 0 ; return ; }
var bs = n % this . DB ;
var cbs = this . DB - bs ;
var bm = ( 1 << bs ) - 1 ;
r [ 0 ] = this [ ds ] >> bs ;
for ( var i = ds + 1 ; i < this . t ; ++ i ) {
r [ i - ds - 1 ] |= ( this [ i ] & bm ) << cbs ;
r [ i - ds ] = this [ i ] >> bs ;
}
if ( bs > 0 ) r [ this . t - ds - 1 ] |= ( this . s & bm ) << cbs ;
r . t = this . t - ds ;
r . clamp ( ) ;
}
// (protected) r = this - a
function bnpSubTo ( a , r ) {
var i = 0 , c = 0 , m = Math . min ( a . t , this . t ) ;
while ( i < m ) {
c += this [ i ] - a [ i ] ;
r [ i ++ ] = c & this . DM ;
c >>= this . DB ;
}
if ( a . t < this . t ) {
c -= a . s ;
while ( i < this . t ) {
c += this [ i ] ;
r [ i ++ ] = c & this . DM ;
c >>= this . DB ;
}
c += this . s ;
}
else {
c += this . s ;
while ( i < a . t ) {
c -= a [ i ] ;
r [ i ++ ] = c & this . DM ;
c >>= this . DB ;
}
c -= a . s ;
}
r . s = ( c < 0 ) ? - 1 : 0 ;
if ( c < - 1 ) r [ i ++ ] = this . DV + c ;
else if ( c > 0 ) r [ i ++ ] = c ;
r . t = i ;
r . clamp ( ) ;
}
// (protected) r = this * a, r != this,a (HAC 14.12)
// "this" should be the larger one if appropriate.
function bnpMultiplyTo ( a , r ) {
var x = this . abs ( ) , y = a . abs ( ) ;
var i = x . t ;
r . t = i + y . t ;
while ( -- i >= 0 ) r [ i ] = 0 ;
for ( i = 0 ; i < y . t ; ++ i ) r [ i + x . t ] = x . am ( 0 , y [ i ] , r , i , 0 , x . t ) ;
r . s = 0 ;
r . clamp ( ) ;
if ( this . s != a . s ) BigInteger . ZERO . subTo ( r , r ) ;
}
// (protected) r = this^2, r != this (HAC 14.16)
function bnpSquareTo ( r ) {
var x = this . abs ( ) ;
var i = r . t = 2 * x . t ;
while ( -- i >= 0 ) r [ i ] = 0 ;
for ( i = 0 ; i < x . t - 1 ; ++ i ) {
var c = x . am ( i , x [ i ] , r , 2 * i , 0 , 1 ) ;
if ( ( r [ i + x . t ] += x . am ( i + 1 , 2 * x [ i ] , r , 2 * i + 1 , c , x . t - i - 1 ) ) >= x . DV ) {
r [ i + x . t ] -= x . DV ;
r [ i + x . t + 1 ] = 1 ;
}
}
if ( r . t > 0 ) r [ r . t - 1 ] += x . am ( i , x [ i ] , r , 2 * i , 0 , 1 ) ;
r . s = 0 ;
r . clamp ( ) ;
}
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
// r != q, this != m. q or r may be null.
function bnpDivRemTo ( m , q , r ) {
var pm = m . abs ( ) ;
if ( pm . t <= 0 ) return ;
var pt = this . abs ( ) ;
if ( pt . t < pm . t ) {
if ( q != null ) q . fromInt ( 0 ) ;
if ( r != null ) this . copyTo ( r ) ;
return ;
}
if ( r == null ) r = nbi ( ) ;
var y = nbi ( ) , ts = this . s , ms = m . s ;
var nsh = this . DB - nbits ( pm [ pm . t - 1 ] ) ; // normalize modulus
if ( nsh > 0 ) { pm . lShiftTo ( nsh , y ) ; pt . lShiftTo ( nsh , r ) ; }
else { pm . copyTo ( y ) ; pt . copyTo ( r ) ; }
var ys = y . t ;
var y0 = y [ ys - 1 ] ;
if ( y0 == 0 ) return ;
var yt = y0 * ( 1 << this . F1 ) + ( ( ys > 1 ) ? y [ ys - 2 ] >> this . F2 : 0 ) ;
var d1 = this . FV / yt , d2 = ( 1 << this . F1 ) / yt , e = 1 << this . F2 ;
var i = r . t , j = i - ys , t = ( q == null ) ? nbi ( ) : q ;
y . dlShiftTo ( j , t ) ;
if ( r . compareTo ( t ) >= 0 ) {
r [ r . t ++ ] = 1 ;
r . subTo ( t , r ) ;
}
BigInteger . ONE . dlShiftTo ( ys , t ) ;
t . subTo ( y , y ) ; // "negative" y so we can replace sub with am later
while ( y . t < ys ) y [ y . t ++ ] = 0 ;
while ( -- j >= 0 ) {
// Estimate quotient digit
var qd = ( r [ -- i ] == y0 ) ? this . DM : Math . floor ( r [ i ] * d1 + ( r [ i - 1 ] + e ) * d2 ) ;
if ( ( r [ i ] += y . am ( 0 , qd , r , j , 0 , ys ) ) < qd ) { // Try it out
y . dlShiftTo ( j , t ) ;
r . subTo ( t , r ) ;
while ( r [ i ] < -- qd ) r . subTo ( t , r ) ;
}
}
if ( q != null ) {
r . drShiftTo ( ys , q ) ;
if ( ts != ms ) BigInteger . ZERO . subTo ( q , q ) ;
}
r . t = ys ;
r . clamp ( ) ;
if ( nsh > 0 ) r . rShiftTo ( nsh , r ) ; // Denormalize remainder
if ( ts < 0 ) BigInteger . ZERO . subTo ( r , r ) ;
}
// (public) this mod a
function bnMod ( a ) {
var r = nbi ( ) ;
this . abs ( ) . divRemTo ( a , null , r ) ;
if ( this . s < 0 && r . compareTo ( BigInteger . ZERO ) > 0 ) a . subTo ( r , r ) ;
return r ;
}
// Modular reduction using "classic" algorithm
function Classic ( m ) { this . m = m ; }
function cConvert ( x ) {
if ( x . s < 0 || x . compareTo ( this . m ) >= 0 ) return x . mod ( this . m ) ;
else return x ;
}
function cRevert ( x ) { return x ; }
function cReduce ( x ) { x . divRemTo ( this . m , null , x ) ; }
function cMulTo ( x , y , r ) { x . multiplyTo ( y , r ) ; this . reduce ( r ) ; }
function cSqrTo ( x , r ) { x . squareTo ( r ) ; this . reduce ( r ) ; }
Classic . prototype . convert = cConvert ;
Classic . prototype . revert = cRevert ;
Classic . prototype . reduce = cReduce ;
Classic . prototype . mulTo = cMulTo ;
Classic . prototype . sqrTo = cSqrTo ;
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
// justification:
// xy == 1 (mod m)
// xy = 1+km
// xy(2-xy) = (1+km)(1-km)
// x[y(2-xy)] = 1-k^2m^2
// x[y(2-xy)] == 1 (mod m^2)
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
// JS multiply "overflows" differently from C/C++, so care is needed here.
function bnpInvDigit ( ) {
if ( this . t < 1 ) return 0 ;
var x = this [ 0 ] ;
if ( ( x & 1 ) == 0 ) return 0 ;
var y = x & 3 ; // y == 1/x mod 2^2
y = ( y * ( 2 - ( x & 0xf ) * y ) ) & 0xf ; // y == 1/x mod 2^4
y = ( y * ( 2 - ( x & 0xff ) * y ) ) & 0xff ; // y == 1/x mod 2^8
y = ( y * ( 2 - ( ( ( x & 0xffff ) * y ) & 0xffff ) ) ) & 0xffff ; // y == 1/x mod 2^16
// last step - calculate inverse mod DV directly;
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
y = ( y * ( 2 - x * y % this . DV ) ) % this . DV ; // y == 1/x mod 2^dbits
// we really want the negative inverse, and -DV < y < DV
return ( y > 0 ) ? this . DV - y : - y ;
}
// Montgomery reduction
function Montgomery ( m ) {
this . m = m ;
this . mp = m . invDigit ( ) ;
this . mpl = this . mp & 0x7fff ;
this . mph = this . mp >> 15 ;
this . um = ( 1 << ( m . DB - 15 ) ) - 1 ;
this . mt2 = 2 * m . t ;
}
// xR mod m
function montConvert ( x ) {
var r = nbi ( ) ;
x . abs ( ) . dlShiftTo ( this . m . t , r ) ;
r . divRemTo ( this . m , null , r ) ;
if ( x . s < 0 && r . compareTo ( BigInteger . ZERO ) > 0 ) this . m . subTo ( r , r ) ;
return r ;
}
// x/R mod m
function montRevert ( x ) {
var r = nbi ( ) ;
x . copyTo ( r ) ;
this . reduce ( r ) ;
return r ;
}
// x = x/R mod m (HAC 14.32)
function montReduce ( x ) {
while ( x . t <= this . mt2 ) // pad x so am has enough room later
x [ x . t ++ ] = 0 ;
for ( var i = 0 ; i < this . m . t ; ++ i ) {
// faster way of calculating u0 = x[i]*mp mod DV
var j = x [ i ] & 0x7fff ;
var u0 = ( j * this . mpl + ( ( ( j * this . mph + ( x [ i ] >> 15 ) * this . mpl ) & this . um ) << 15 ) ) & x . DM ;
// use am to combine the multiply-shift-add into one call
j = i + this . m . t ;
x [ j ] += this . m . am ( 0 , u0 , x , i , 0 , this . m . t ) ;
// propagate carry
while ( x [ j ] >= x . DV ) { x [ j ] -= x . DV ; x [ ++ j ] ++ ; }
}
x . clamp ( ) ;
x . drShiftTo ( this . m . t , x ) ;
if ( x . compareTo ( this . m ) >= 0 ) x . subTo ( this . m , x ) ;
}
// r = "x^2/R mod m"; x != r
function montSqrTo ( x , r ) { x . squareTo ( r ) ; this . reduce ( r ) ; }
// r = "xy/R mod m"; x,y != r
function montMulTo ( x , y , r ) { x . multiplyTo ( y , r ) ; this . reduce ( r ) ; }
Montgomery . prototype . convert = montConvert ;
Montgomery . prototype . revert = montRevert ;
Montgomery . prototype . reduce = montReduce ;
Montgomery . prototype . mulTo = montMulTo ;
Montgomery . prototype . sqrTo = montSqrTo ;
// (protected) true iff this is even
function bnpIsEven ( ) { return ( ( this . t > 0 ) ? ( this [ 0 ] & 1 ) : this . s ) == 0 ; }
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
function bnpExp ( e , z ) {
if ( e > 0xffffffff || e < 1 ) return BigInteger . ONE ;
var r = nbi ( ) , r2 = nbi ( ) , g = z . convert ( this ) , i = nbits ( e ) - 1 ;
g . copyTo ( r ) ;
while ( -- i >= 0 ) {
z . sqrTo ( r , r2 ) ;
if ( ( e & ( 1 << i ) ) > 0 ) z . mulTo ( r2 , g , r ) ;
else { var t = r ; r = r2 ; r2 = t ; }
}
return z . revert ( r ) ;
}
// (public) this^e % m, 0 <= e < 2^32
function bnModPowInt ( e , m ) {
var z ;
if ( e < 256 || m . isEven ( ) ) z = new Classic ( m ) ; else z = new Montgomery ( m ) ;
return this . exp ( e , z ) ;
}
// protected
BigInteger . prototype . copyTo = bnpCopyTo ;
BigInteger . prototype . fromInt = bnpFromInt ;
BigInteger . prototype . fromString = bnpFromString ;
BigInteger . prototype . clamp = bnpClamp ;
BigInteger . prototype . dlShiftTo = bnpDLShiftTo ;
BigInteger . prototype . drShiftTo = bnpDRShiftTo ;
BigInteger . prototype . lShiftTo = bnpLShiftTo ;
BigInteger . prototype . rShiftTo = bnpRShiftTo ;
BigInteger . prototype . subTo = bnpSubTo ;
BigInteger . prototype . multiplyTo = bnpMultiplyTo ;
BigInteger . prototype . squareTo = bnpSquareTo ;
BigInteger . prototype . divRemTo = bnpDivRemTo ;
BigInteger . prototype . invDigit = bnpInvDigit ;
BigInteger . prototype . isEven = bnpIsEven ;
BigInteger . prototype . exp = bnpExp ;
// public
BigInteger . prototype . toString = bnToString ;
BigInteger . prototype . negate = bnNegate ;
BigInteger . prototype . abs = bnAbs ;
BigInteger . prototype . compareTo = bnCompareTo ;
BigInteger . prototype . bitLength = bnBitLength ;
BigInteger . prototype . mod = bnMod ;
BigInteger . prototype . modPowInt = bnModPowInt ;
// "constants"
BigInteger . ZERO = nbv ( 0 ) ;
BigInteger . ONE = nbv ( 1 ) ;
// jsbn2 stuff
// (protected) convert from radix string
function bnpFromRadix ( s , b ) {
this . fromInt ( 0 ) ;
if ( b == null ) b = 10 ;
var cs = this . chunkSize ( b ) ;
var d = Math . pow ( b , cs ) , mi = false , j = 0 , w = 0 ;
for ( var i = 0 ; i < s . length ; ++ i ) {
var x = intAt ( s , i ) ;
if ( x < 0 ) {
if ( s . charAt ( i ) == "-" && this . signum ( ) == 0 ) mi = true ;
continue ;
}
w = b * w + x ;
if ( ++ j >= cs ) {
this . dMultiply ( d ) ;
this . dAddOffset ( w , 0 ) ;
j = 0 ;
w = 0 ;
}
}
if ( j > 0 ) {
this . dMultiply ( Math . pow ( b , j ) ) ;
this . dAddOffset ( w , 0 ) ;
}
if ( mi ) BigInteger . ZERO . subTo ( this , this ) ;
}
// (protected) return x s.t. r^x < DV
function bnpChunkSize ( r ) { return Math . floor ( Math . LN2 * this . DB / Math . log ( r ) ) ; }
// (public) 0 if this == 0, 1 if this > 0
function bnSigNum ( ) {
if ( this . s < 0 ) return - 1 ;
else if ( this . t <= 0 || ( this . t == 1 && this [ 0 ] <= 0 ) ) return 0 ;
else return 1 ;
}
// (protected) this *= n, this >= 0, 1 < n < DV
function bnpDMultiply ( n ) {
this [ this . t ] = this . am ( 0 , n - 1 , this , 0 , 0 , this . t ) ;
++ this . t ;
this . clamp ( ) ;
}
// (protected) this += n << w words, this >= 0
function bnpDAddOffset ( n , w ) {
if ( n == 0 ) return ;
while ( this . t <= w ) this [ this . t ++ ] = 0 ;
this [ w ] += n ;
while ( this [ w ] >= this . DV ) {
this [ w ] -= this . DV ;
if ( ++ w >= this . t ) this [ this . t ++ ] = 0 ;
++ this [ w ] ;
}
}
// (protected) convert to radix string
function bnpToRadix ( b ) {
if ( b == null ) b = 10 ;
if ( this . signum ( ) == 0 || b < 2 || b > 36 ) return "0" ;
var cs = this . chunkSize ( b ) ;
var a = Math . pow ( b , cs ) ;
var d = nbv ( a ) , y = nbi ( ) , z = nbi ( ) , r = "" ;
this . divRemTo ( d , y , z ) ;
while ( y . signum ( ) > 0 ) {
r = ( a + z . intValue ( ) ) . toString ( b ) . substr ( 1 ) + r ;
y . divRemTo ( d , y , z ) ;
}
return z . intValue ( ) . toString ( b ) + r ;
}
// (public) return value as integer
function bnIntValue ( ) {
if ( this . s < 0 ) {
if ( this . t == 1 ) return this [ 0 ] - this . DV ;
else if ( this . t == 0 ) return - 1 ;
}
else if ( this . t == 1 ) return this [ 0 ] ;
else if ( this . t == 0 ) return 0 ;
// assumes 16 < DB < 32
return ( ( this [ 1 ] & ( ( 1 << ( 32 - this . DB ) ) - 1 ) ) << this . DB ) | this [ 0 ] ;
}
// (protected) r = this + a
function bnpAddTo ( a , r ) {
var i = 0 , c = 0 , m = Math . min ( a . t , this . t ) ;
while ( i < m ) {
c += this [ i ] + a [ i ] ;
r [ i ++ ] = c & this . DM ;
c >>= this . DB ;
}
if ( a . t < this . t ) {
c += a . s ;
while ( i < this . t ) {
c += this [ i ] ;
r [ i ++ ] = c & this . DM ;
c >>= this . DB ;
}
c += this . s ;
}
else {
c += this . s ;
while ( i < a . t ) {
c += a [ i ] ;
r [ i ++ ] = c & this . DM ;
c >>= this . DB ;
}
c += a . s ;
}
r . s = ( c < 0 ) ? - 1 : 0 ;
if ( c > 0 ) r [ i ++ ] = c ;
else if ( c < - 1 ) r [ i ++ ] = this . DV + c ;
r . t = i ;
r . clamp ( ) ;
}
BigInteger . prototype . fromRadix = bnpFromRadix ;
BigInteger . prototype . chunkSize = bnpChunkSize ;
BigInteger . prototype . signum = bnSigNum ;
BigInteger . prototype . dMultiply = bnpDMultiply ;
BigInteger . prototype . dAddOffset = bnpDAddOffset ;
BigInteger . prototype . toRadix = bnpToRadix ;
BigInteger . prototype . intValue = bnIntValue ;
BigInteger . prototype . addTo = bnpAddTo ;
//======= end jsbn =======
// Emscripten wrapper
var Wrapper = {
abs : function ( l , h ) {
var x = new goog . math . Long ( l , h ) ;
var ret ;
if ( x . isNegative ( ) ) {
ret = x . negate ( ) ;
} else {
ret = x ;
}
HEAP32 [ tempDoublePtr >> 2 ] = ret . low _ ;
HEAP32 [ tempDoublePtr + 4 >> 2 ] = ret . high _ ;
} ,
ensureTemps : function ( ) {
if ( Wrapper . ensuredTemps ) return ;
Wrapper . ensuredTemps = true ;
Wrapper . two32 = new BigInteger ( ) ;
Wrapper . two32 . fromString ( '4294967296' , 10 ) ;
Wrapper . two64 = new BigInteger ( ) ;
Wrapper . two64 . fromString ( '18446744073709551616' , 10 ) ;
Wrapper . temp1 = new BigInteger ( ) ;
Wrapper . temp2 = new BigInteger ( ) ;
} ,
lh2bignum : function ( l , h ) {
var a = new BigInteger ( ) ;
a . fromString ( h . toString ( ) , 10 ) ;
var b = new BigInteger ( ) ;
a . multiplyTo ( Wrapper . two32 , b ) ;
var c = new BigInteger ( ) ;
c . fromString ( l . toString ( ) , 10 ) ;
var d = new BigInteger ( ) ;
c . addTo ( b , d ) ;
return d ;
} ,
stringify : function ( l , h , unsigned ) {
var ret = new goog . math . Long ( l , h ) . toString ( ) ;
if ( unsigned && ret [ 0 ] == '-' ) {
// unsign slowly using jsbn bignums
Wrapper . ensureTemps ( ) ;
var bignum = new BigInteger ( ) ;
bignum . fromString ( ret , 10 ) ;
ret = new BigInteger ( ) ;
Wrapper . two64 . addTo ( bignum , ret ) ;
ret = ret . toString ( 10 ) ;
}
return ret ;
} ,
fromString : function ( str , base , min , max , unsigned ) {
Wrapper . ensureTemps ( ) ;
var bignum = new BigInteger ( ) ;
bignum . fromString ( str , base ) ;
var bigmin = new BigInteger ( ) ;
bigmin . fromString ( min , 10 ) ;
var bigmax = new BigInteger ( ) ;
bigmax . fromString ( max , 10 ) ;
if ( unsigned && bignum . compareTo ( BigInteger . ZERO ) < 0 ) {
var temp = new BigInteger ( ) ;
bignum . addTo ( Wrapper . two64 , temp ) ;
bignum = temp ;
}
var error = false ;
if ( bignum . compareTo ( bigmin ) < 0 ) {
bignum = bigmin ;
error = true ;
} else if ( bignum . compareTo ( bigmax ) > 0 ) {
bignum = bigmax ;
error = true ;
}
var ret = goog . math . Long . fromString ( bignum . toString ( ) ) ; // min-max checks should have clamped this to a range goog.math.Long can handle well
HEAP32 [ tempDoublePtr >> 2 ] = ret . low _ ;
HEAP32 [ tempDoublePtr + 4 >> 2 ] = ret . high _ ;
if ( error ) throw 'range error' ;
}
} ;
return Wrapper ;
} ) ( ) ;
//======= end closure i64 code =======
// === Auto-generated postamble setup entry stuff ===
Module [ 'callMain' ] = function callMain ( args ) {
assert ( runDependencies == 0 , 'cannot call main when async dependencies remain! (listen on __ATMAIN__)' ) ;
assert ( ! Module [ 'preRun' ] || Module [ 'preRun' ] . length == 0 , 'cannot call main when preRun functions remain to be called' ) ;
args = args || [ ] ;
ensureInitRuntime ( ) ;
var argc = args . length + 1 ;
function pad ( ) {
for ( var i = 0 ; i < 4 - 1 ; i ++ ) {
argv . push ( 0 ) ;
}
}
var argv = [ allocate ( intArrayFromString ( "/bin/this.program" ) , 'i8' , ALLOC _NORMAL ) ] ;
pad ( ) ;
for ( var i = 0 ; i < argc - 1 ; i = i + 1 ) {
argv . push ( allocate ( intArrayFromString ( args [ i ] ) , 'i8' , ALLOC _NORMAL ) ) ;
pad ( ) ;
}
argv . push ( 0 ) ;
argv = allocate ( argv , 'i32' , ALLOC _NORMAL ) ;
var ret ;
var initialStackTop = STACKTOP ;
try {
ret = Module [ '_main' ] ( argc , argv , 0 ) ;
}
catch ( e ) {
if ( e . name == 'ExitStatus' ) {
return e . status ;
} else if ( e == 'SimulateInfiniteLoop' ) {
Module [ 'noExitRuntime' ] = true ;
} else {
throw e ;
}
} finally {
STACKTOP = initialStackTop ;
}
return ret ;
}
function run ( args ) {
args = args || Module [ 'arguments' ] ;
if ( runDependencies > 0 ) {
Module . printErr ( 'run() called, but dependencies remain, so not running' ) ;
return 0 ;
}
if ( Module [ 'preRun' ] ) {
if ( typeof Module [ 'preRun' ] == 'function' ) Module [ 'preRun' ] = [ Module [ 'preRun' ] ] ;
var toRun = Module [ 'preRun' ] ;
Module [ 'preRun' ] = [ ] ;
for ( var i = toRun . length - 1 ; i >= 0 ; i -- ) {
toRun [ i ] ( ) ;
}
if ( runDependencies > 0 ) {
// a preRun added a dependency, run will be called later
return 0 ;
}
}
function doRun ( ) {
ensureInitRuntime ( ) ;
preMain ( ) ;
var ret = 0 ;
calledRun = true ;
if ( Module [ '_main' ] && shouldRunNow ) {
ret = Module [ 'callMain' ] ( args ) ;
if ( ! Module [ 'noExitRuntime' ] ) {
exitRuntime ( ) ;
}
}
if ( Module [ 'postRun' ] ) {
if ( typeof Module [ 'postRun' ] == 'function' ) Module [ 'postRun' ] = [ Module [ 'postRun' ] ] ;
while ( Module [ 'postRun' ] . length > 0 ) {
Module [ 'postRun' ] . pop ( ) ( ) ;
}
}
return ret ;
}
if ( Module [ 'setStatus' ] ) {
Module [ 'setStatus' ] ( 'Running...' ) ;
setTimeout ( function ( ) {
setTimeout ( function ( ) {
Module [ 'setStatus' ] ( '' ) ;
} , 1 ) ;
if ( ! ABORT ) doRun ( ) ;
} , 1 ) ;
return 0 ;
} else {
return doRun ( ) ;
}
}
Module [ 'run' ] = Module . run = run ;
// {{PRE_RUN_ADDITIONS}}
if ( Module [ 'preInit' ] ) {
if ( typeof Module [ 'preInit' ] == 'function' ) Module [ 'preInit' ] = [ Module [ 'preInit' ] ] ;
while ( Module [ 'preInit' ] . length > 0 ) {
Module [ 'preInit' ] . pop ( ) ( ) ;
}
}
// shouldRunNow refers to calling main(), not run().
var shouldRunNow = true ;
if ( Module [ 'noInitialRun' ] ) {
shouldRunNow = false ;
}
run ( ) ;
// {{POST_RUN_ADDITIONS}}
// {{MODULE_ADDITIONS}}
/ * v i m : t s = 4 : s w = 4 : e x p a n d t a b
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
; ( function ( ) {
'use strict' ;
// Insert some bytes into the emscripten memory and return a pointer
function _allocate ( bytes ) {
var address = Module . _malloc ( bytes . length ) ;
Module . HEAPU8 . set ( bytes , address ) ;
return address ;
}
function _readBytes ( address , length , array ) {
array . set ( Module . HEAPU8 . subarray ( address , address + length ) ) ;
}
var basepoint = new Uint8Array ( 32 ) ;
basepoint [ 0 ] = 9 ;
window . curve25519 = {
keyPair : function ( privKey ) {
var priv = new Uint8Array ( privKey ) ;
priv [ 0 ] &= 248 ;
priv [ 31 ] &= 127 ;
priv [ 31 ] |= 64
// Where to store the result
var publicKey _ptr = Module . _malloc ( 32 ) ;
// Get a pointer to the private key
var privateKey _ptr = _allocate ( priv ) ;
// The basepoint for generating public keys
var basepoint _ptr = _allocate ( basepoint ) ;
// The return value is just 0, the operation is done in place
var err = Module . _curve25519 _donna ( publicKey _ptr ,
privateKey _ptr ,
basepoint _ptr ) ;
var res = new Uint8Array ( 32 ) ;
_readBytes ( publicKey _ptr , 32 , res ) ;
Module . _free ( publicKey _ptr ) ;
Module . _free ( privateKey _ptr ) ;
Module . _free ( basepoint _ptr ) ;
return Promise . resolve ( { pubKey : res . buffer , privKey : privKey } ) ;
} ,
sharedSecret : function ( pubKey , privKey ) {
// Where to store the result
var sharedKey _ptr = Module . _malloc ( 32 ) ;
// Get a pointer to our private key
var privateKey _ptr = _allocate ( new Uint8Array ( privKey ) ) ;
// Get a pointer to their public key, the basepoint when you're
// generating a shared secret
var basepoint _ptr = _allocate ( new Uint8Array ( pubKey ) ) ;
// Return value is 0 here too of course
var err = Module . _curve25519 _donna ( sharedKey _ptr ,
privateKey _ptr ,
basepoint _ptr ) ;
var res = new Uint8Array ( 32 ) ;
_readBytes ( sharedKey _ptr , 32 , res ) ;
Module . _free ( sharedKey _ptr ) ;
Module . _free ( privateKey _ptr ) ;
Module . _free ( basepoint _ptr ) ;
return Promise . resolve ( res . buffer ) ;
} ,
sign : function ( privKey , message ) {
// Where to store the result
var signature _ptr = Module . _malloc ( 64 ) ;
// Get a pointer to our private key
var privateKey _ptr = _allocate ( new Uint8Array ( privKey ) ) ;
// Get a pointer to the message
var message _ptr = _allocate ( new Uint8Array ( message ) ) ;
var err = Module . _curve25519 _sign ( signature _ptr ,
privateKey _ptr ,
message _ptr ,
message . byteLength ) ;
var res = new Uint8Array ( 64 ) ;
_readBytes ( signature _ptr , 64 , res ) ;
Module . _free ( signature _ptr ) ;
Module . _free ( privateKey _ptr ) ;
Module . _free ( message _ptr ) ;
return Promise . resolve ( res . buffer ) ;
} ,
verify : function ( pubKey , message , sig ) {
// Get a pointer to their public key
var publicKey _ptr = _allocate ( new Uint8Array ( pubKey ) ) ;
// Get a pointer to the signature
var signature _ptr = _allocate ( new Uint8Array ( sig ) ) ;
// Get a pointer to the message
var message _ptr = _allocate ( new Uint8Array ( message ) ) ;
var res = Module . _curve25519 _verify ( signature _ptr ,
publicKey _ptr ,
message _ptr ,
message . byteLength ) ;
Module . _free ( publicKey _ptr ) ;
Module . _free ( signature _ptr ) ;
Module . _free ( message _ptr ) ;
return new Promise ( function ( resolve , reject ) {
if ( res !== 0 ) {
reject ( new Error ( "Invalid signature" ) ) ;
} else {
resolve ( ) ;
}
} ) ;
}
} ;
} ) ( ) ;
} ) ( ) ;
; ( function ( ) {
2015-02-20 15:05:32 -08:00
/ * *
* CryptoJS core components .
* /
var CryptoJS = CryptoJS || ( function ( Math , undefined ) {
/ * *
* CryptoJS namespace .
* /
var C = { } ;
/ * *
* Library namespace .
* /
var C _lib = C . lib = { } ;
/ * *
* Base object for prototypal inheritance .
* /
var Base = C _lib . Base = ( function ( ) {
function F ( ) { }
return {
/ * *
* Creates a new object that inherits from this object .
*
* @ param { Object } overrides Properties to copy into the new object .
*
* @ return { Object } The new object .
*
* @ static
*
* @ example
*
* var MyType = CryptoJS . lib . Base . extend ( {
* field : 'value' ,
*
* method : function ( ) {
* }
* } ) ;
* /
extend : function ( overrides ) {
// Spawn
F . prototype = this ;
var subtype = new F ( ) ;
// Augment
if ( overrides ) {
subtype . mixIn ( overrides ) ;
}
// Create default initializer
if ( ! subtype . hasOwnProperty ( 'init' ) ) {
subtype . init = function ( ) {
subtype . $super . init . apply ( this , arguments ) ;
} ;
}
// Initializer's prototype is the subtype object
subtype . init . prototype = subtype ;
// Reference supertype
subtype . $super = this ;
return subtype ;
} ,
/ * *
* Extends this object and runs the init method .
* Arguments to create ( ) will be passed to init ( ) .
*
* @ return { Object } The new object .
*
* @ static
*
* @ example
*
* var instance = MyType . create ( ) ;
* /
create : function ( ) {
var instance = this . extend ( ) ;
instance . init . apply ( instance , arguments ) ;
return instance ;
} ,
/ * *
* Initializes a newly created object .
* Override this method to add some logic when your objects are created .
*
* @ example
*
* var MyType = CryptoJS . lib . Base . extend ( {
* init : function ( ) {
* // ...
* }
* } ) ;
* /
init : function ( ) {
} ,
/ * *
* Copies properties into this object .
*
* @ param { Object } properties The properties to mix in .
*
* @ example
*
* MyType . mixIn ( {
* field : 'value'
* } ) ;
* /
mixIn : function ( properties ) {
for ( var propertyName in properties ) {
if ( properties . hasOwnProperty ( propertyName ) ) {
this [ propertyName ] = properties [ propertyName ] ;
}
}
// IE won't copy toString using the loop above
if ( properties . hasOwnProperty ( 'toString' ) ) {
this . toString = properties . toString ;
}
} ,
/ * *
* Creates a copy of this object .
*
* @ return { Object } The clone .
*
* @ example
*
* var clone = instance . clone ( ) ;
* /
clone : function ( ) {
return this . init . prototype . extend ( this ) ;
}
} ;
} ( ) ) ;
/ * *
* An array of 32 - bit words .
*
* @ property { Array } words The array of 32 - bit words .
* @ property { number } sigBytes The number of significant bytes in this word array .
* /
var WordArray = C _lib . WordArray = Base . extend ( {
/ * *
* Initializes a newly created word array .
*
* @ param { Array } words ( Optional ) An array of 32 - bit words .
* @ param { number } sigBytes ( Optional ) The number of significant bytes in the words .
*
* @ example
*
* var wordArray = CryptoJS . lib . WordArray . create ( ) ;
* var wordArray = CryptoJS . lib . WordArray . create ( [ 0x00010203 , 0x04050607 ] ) ;
* var wordArray = CryptoJS . lib . WordArray . create ( [ 0x00010203 , 0x04050607 ] , 6 ) ;
* /
init : function ( words , sigBytes ) {
words = this . words = words || [ ] ;
if ( sigBytes != undefined ) {
this . sigBytes = sigBytes ;
} else {
this . sigBytes = words . length * 4 ;
}
} ,
/ * *
* Converts this word array to a string .
*
* @ param { Encoder } encoder ( Optional ) The encoding strategy to use . Default : CryptoJS . enc . Hex
*
* @ return { string } The stringified word array .
*
* @ example
*
* var string = wordArray + '' ;
* var string = wordArray . toString ( ) ;
* var string = wordArray . toString ( CryptoJS . enc . Utf8 ) ;
* /
toString : function ( encoder ) {
return ( encoder || Hex ) . stringify ( this ) ;
} ,
/ * *
* Concatenates a word array to this word array .
*
* @ param { WordArray } wordArray The word array to append .
*
* @ return { WordArray } This word array .
*
* @ example
*
* wordArray1 . concat ( wordArray2 ) ;
* /
concat : function ( wordArray ) {
// Shortcuts
var thisWords = this . words ;
var thatWords = wordArray . words ;
var thisSigBytes = this . sigBytes ;
var thatSigBytes = wordArray . sigBytes ;
// Clamp excess bits
this . clamp ( ) ;
// Concat
if ( thisSigBytes % 4 ) {
// Copy one byte at a time
for ( var i = 0 ; i < thatSigBytes ; i ++ ) {
var thatByte = ( thatWords [ i >>> 2 ] >>> ( 24 - ( i % 4 ) * 8 ) ) & 0xff ;
thisWords [ ( thisSigBytes + i ) >>> 2 ] |= thatByte << ( 24 - ( ( thisSigBytes + i ) % 4 ) * 8 ) ;
}
} else if ( thatWords . length > 0xffff ) {
// Copy one word at a time
for ( var i = 0 ; i < thatSigBytes ; i += 4 ) {
thisWords [ ( thisSigBytes + i ) >>> 2 ] = thatWords [ i >>> 2 ] ;
}
} else {
// Copy all words at once
thisWords . push . apply ( thisWords , thatWords ) ;
}
this . sigBytes += thatSigBytes ;
// Chainable
return this ;
} ,
/ * *
* Removes insignificant bits .
*
* @ example
*
* wordArray . clamp ( ) ;
* /
clamp : function ( ) {
// Shortcuts
var words = this . words ;
var sigBytes = this . sigBytes ;
// Clamp
words [ sigBytes >>> 2 ] &= 0xffffffff << ( 32 - ( sigBytes % 4 ) * 8 ) ;
words . length = Math . ceil ( sigBytes / 4 ) ;
} ,
/ * *
* Creates a copy of this word array .
*
* @ return { WordArray } The clone .
*
* @ example
*
* var clone = wordArray . clone ( ) ;
* /
clone : function ( ) {
var clone = Base . clone . call ( this ) ;
clone . words = this . words . slice ( 0 ) ;
return clone ;
} ,
/ * *
* Creates a word array filled with random bytes .
*
* @ param { number } nBytes The number of random bytes to generate .
*
* @ return { WordArray } The random word array .
*
* @ static
*
* @ example
*
* var wordArray = CryptoJS . lib . WordArray . random ( 16 ) ;
* /
random : function ( nBytes ) {
var words = [ ] ;
for ( var i = 0 ; i < nBytes ; i += 4 ) {
words . push ( ( Math . random ( ) * 0x100000000 ) | 0 ) ;
}
return new WordArray . init ( words , nBytes ) ;
}
} ) ;
/ * *
* Encoder namespace .
* /
var C _enc = C . enc = { } ;
/ * *
* Hex encoding strategy .
* /
var Hex = C _enc . Hex = {
/ * *
* Converts a word array to a hex string .
*
* @ param { WordArray } wordArray The word array .
*
* @ return { string } The hex string .
*
* @ static
*
* @ example
*
* var hexString = CryptoJS . enc . Hex . stringify ( wordArray ) ;
* /
stringify : function ( wordArray ) {
// Shortcuts
var words = wordArray . words ;
var sigBytes = wordArray . sigBytes ;
// Convert
var hexChars = [ ] ;
for ( var i = 0 ; i < sigBytes ; i ++ ) {
var bite = ( words [ i >>> 2 ] >>> ( 24 - ( i % 4 ) * 8 ) ) & 0xff ;
hexChars . push ( ( bite >>> 4 ) . toString ( 16 ) ) ;
hexChars . push ( ( bite & 0x0f ) . toString ( 16 ) ) ;
}
return hexChars . join ( '' ) ;
} ,
/ * *
* Converts a hex string to a word array .
*
* @ param { string } hexStr The hex string .
*
* @ return { WordArray } The word array .
*
* @ static
*
* @ example
*
* var wordArray = CryptoJS . enc . Hex . parse ( hexString ) ;
* /
parse : function ( hexStr ) {
// Shortcut
var hexStrLength = hexStr . length ;
// Convert
var words = [ ] ;
for ( var i = 0 ; i < hexStrLength ; i += 2 ) {
words [ i >>> 3 ] |= parseInt ( hexStr . substr ( i , 2 ) , 16 ) << ( 24 - ( i % 8 ) * 4 ) ;
}
return new WordArray . init ( words , hexStrLength / 2 ) ;
}
} ;
/ * *
* Latin1 encoding strategy .
* /
var Latin1 = C _enc . Latin1 = {
/ * *
* Converts a word array to a Latin1 string .
*
* @ param { WordArray } wordArray The word array .
*
* @ return { string } The Latin1 string .
*
* @ static
*
* @ example
*
* var latin1String = CryptoJS . enc . Latin1 . stringify ( wordArray ) ;
* /
stringify : function ( wordArray ) {
// Shortcuts
var words = wordArray . words ;
var sigBytes = wordArray . sigBytes ;
// Convert
var latin1Chars = [ ] ;
for ( var i = 0 ; i < sigBytes ; i ++ ) {
var bite = ( words [ i >>> 2 ] >>> ( 24 - ( i % 4 ) * 8 ) ) & 0xff ;
latin1Chars . push ( String . fromCharCode ( bite ) ) ;
}
return latin1Chars . join ( '' ) ;
} ,
/ * *
* Converts a Latin1 string to a word array .
*
* @ param { string } latin1Str The Latin1 string .
*
* @ return { WordArray } The word array .
*
* @ static
*
* @ example
*
* var wordArray = CryptoJS . enc . Latin1 . parse ( latin1String ) ;
* /
parse : function ( latin1Str ) {
// Shortcut
var latin1StrLength = latin1Str . length ;
// Convert
var words = [ ] ;
for ( var i = 0 ; i < latin1StrLength ; i ++ ) {
words [ i >>> 2 ] |= ( latin1Str . charCodeAt ( i ) & 0xff ) << ( 24 - ( i % 4 ) * 8 ) ;
}
return new WordArray . init ( words , latin1StrLength ) ;
}
} ;
/ * *
* UTF - 8 encoding strategy .
* /
var Utf8 = C _enc . Utf8 = {
/ * *
* Converts a word array to a UTF - 8 string .
*
* @ param { WordArray } wordArray The word array .
*
* @ return { string } The UTF - 8 string .
*
* @ static
*
* @ example
*
* var utf8String = CryptoJS . enc . Utf8 . stringify ( wordArray ) ;
* /
stringify : function ( wordArray ) {
try {
return decodeURIComponent ( escape ( Latin1 . stringify ( wordArray ) ) ) ;
} catch ( e ) {
throw new Error ( 'Malformed UTF-8 data' ) ;
}
} ,
/ * *
* Converts a UTF - 8 string to a word array .
*
* @ param { string } utf8Str The UTF - 8 string .
*
* @ return { WordArray } The word array .
*
* @ static
*
* @ example
*
* var wordArray = CryptoJS . enc . Utf8 . parse ( utf8String ) ;
* /
parse : function ( utf8Str ) {
return Latin1 . parse ( unescape ( encodeURIComponent ( utf8Str ) ) ) ;
}
} ;
/ * *
* Abstract buffered block algorithm template .
*
* The property blockSize must be implemented in a concrete subtype .
*
* @ property { number } _minBufferSize The number of blocks that should be kept unprocessed in the buffer . Default : 0
* /
var BufferedBlockAlgorithm = C _lib . BufferedBlockAlgorithm = Base . extend ( {
/ * *
* Resets this block algorithm ' s data buffer to its initial state .
*
* @ example
*
* bufferedBlockAlgorithm . reset ( ) ;
* /
reset : function ( ) {
// Initial values
this . _data = new WordArray . init ( ) ;
this . _nDataBytes = 0 ;
} ,
/ * *
* Adds new data to this block algorithm ' s buffer .
*
* @ param { WordArray | string } data The data to append . Strings are converted to a WordArray using UTF - 8.
*
* @ example
*
* bufferedBlockAlgorithm . _append ( 'data' ) ;
* bufferedBlockAlgorithm . _append ( wordArray ) ;
* /
_append : function ( data ) {
// Convert string to WordArray, else assume WordArray already
if ( typeof data == 'string' ) {
data = Utf8 . parse ( data ) ;
}
// Append
this . _data . concat ( data ) ;
this . _nDataBytes += data . sigBytes ;
} ,
/ * *
* Processes available data blocks .
*
* This method invokes _doProcessBlock ( offset ) , which must be implemented by a concrete subtype .
*
* @ param { boolean } doFlush Whether all blocks and partial blocks should be processed .
*
* @ return { WordArray } The processed data .
*
* @ example
*
* var processedData = bufferedBlockAlgorithm . _process ( ) ;
* var processedData = bufferedBlockAlgorithm . _process ( ! ! 'flush' ) ;
* /
_process : function ( doFlush ) {
// Shortcuts
var data = this . _data ;
var dataWords = data . words ;
var dataSigBytes = data . sigBytes ;
var blockSize = this . blockSize ;
var blockSizeBytes = blockSize * 4 ;
// Count blocks ready
var nBlocksReady = dataSigBytes / blockSizeBytes ;
if ( doFlush ) {
// Round up to include partial blocks
nBlocksReady = Math . ceil ( nBlocksReady ) ;
} else {
// Round down to include only full blocks,
// less the number of blocks that must remain in the buffer
nBlocksReady = Math . max ( ( nBlocksReady | 0 ) - this . _minBufferSize , 0 ) ;
}
// Count words ready
var nWordsReady = nBlocksReady * blockSize ;
// Count bytes ready
var nBytesReady = Math . min ( nWordsReady * 4 , dataSigBytes ) ;
// Process blocks
if ( nWordsReady ) {
for ( var offset = 0 ; offset < nWordsReady ; offset += blockSize ) {
// Perform concrete-algorithm logic
this . _doProcessBlock ( dataWords , offset ) ;
}
// Remove processed words
var processedWords = dataWords . splice ( 0 , nWordsReady ) ;
data . sigBytes -= nBytesReady ;
}
// Return processed words
return new WordArray . init ( processedWords , nBytesReady ) ;
} ,
/ * *
* Creates a copy of this object .
*
* @ return { Object } The clone .
*
* @ example
*
* var clone = bufferedBlockAlgorithm . clone ( ) ;
* /
clone : function ( ) {
var clone = Base . clone . call ( this ) ;
clone . _data = this . _data . clone ( ) ;
return clone ;
} ,
_minBufferSize : 0
} ) ;
/ * *
* Abstract hasher template .
*
* @ property { number } blockSize The number of 32 - bit words this hasher operates on . Default : 16 ( 512 bits )
* /
var Hasher = C _lib . Hasher = BufferedBlockAlgorithm . extend ( {
/ * *
* Configuration options .
* /
cfg : Base . extend ( ) ,
/ * *
* Initializes a newly created hasher .
*
* @ param { Object } cfg ( Optional ) The configuration options to use for this hash computation .
*
* @ example
*
* var hasher = CryptoJS . algo . SHA256 . create ( ) ;
* /
init : function ( cfg ) {
// Apply config defaults
this . cfg = this . cfg . extend ( cfg ) ;
// Set initial values
this . reset ( ) ;
} ,
/ * *
* Resets this hasher to its initial state .
*
* @ example
*
* hasher . reset ( ) ;
* /
reset : function ( ) {
// Reset data buffer
BufferedBlockAlgorithm . reset . call ( this ) ;
// Perform concrete-hasher logic
this . _doReset ( ) ;
} ,
/ * *
* Updates this hasher with a message .
*
* @ param { WordArray | string } messageUpdate The message to append .
*
* @ return { Hasher } This hasher .
*
* @ example
*
* hasher . update ( 'message' ) ;
* hasher . update ( wordArray ) ;
* /
update : function ( messageUpdate ) {
// Append
this . _append ( messageUpdate ) ;
// Update the hash
this . _process ( ) ;
// Chainable
return this ;
} ,
/ * *
* Finalizes the hash computation .
* Note that the finalize operation is effectively a destructive , read - once operation .
*
* @ param { WordArray | string } messageUpdate ( Optional ) A final message update .
*
* @ return { WordArray } The hash .
*
* @ example
*
* var hash = hasher . finalize ( ) ;
* var hash = hasher . finalize ( 'message' ) ;
* var hash = hasher . finalize ( wordArray ) ;
* /
finalize : function ( messageUpdate ) {
// Final message update
if ( messageUpdate ) {
this . _append ( messageUpdate ) ;
}
// Perform concrete-hasher logic
var hash = this . _doFinalize ( ) ;
return hash ;
} ,
blockSize : 512 / 32 ,
/ * *
* Creates a shortcut function to a hasher ' s object interface .
*
* @ param { Hasher } hasher The hasher to create a helper for .
*
* @ return { Function } The shortcut function .
*
* @ static
*
* @ example
*
* var SHA256 = CryptoJS . lib . Hasher . _createHelper ( CryptoJS . algo . SHA256 ) ;
* /
_createHelper : function ( hasher ) {
return function ( message , cfg ) {
return new hasher . init ( cfg ) . finalize ( message ) ;
} ;
} ,
/ * *
* Creates a shortcut function to the HMAC ' s object interface .
*
* @ param { Hasher } hasher The hasher to use in this HMAC helper .
*
* @ return { Function } The shortcut function .
*
* @ static
*
* @ example
*
* var HmacSHA256 = CryptoJS . lib . Hasher . _createHmacHelper ( CryptoJS . algo . SHA256 ) ;
* /
_createHmacHelper : function ( hasher ) {
return function ( message , key ) {
return new C _algo . HMAC . init ( hasher , key ) . finalize ( message ) ;
} ;
}
} ) ;
/ * *
* Algorithm namespace .
* /
var C _algo = C . algo = { } ;
return C ;
} ( Math ) ) ;
( function ( Math ) {
// Shortcuts
var C = CryptoJS ;
var C _lib = C . lib ;
var WordArray = C _lib . WordArray ;
var Hasher = C _lib . Hasher ;
var C _algo = C . algo ;
// Initialization and round constants tables
var H = [ ] ;
var K = [ ] ;
// Compute constants
( function ( ) {
function isPrime ( n ) {
var sqrtN = Math . sqrt ( n ) ;
for ( var factor = 2 ; factor <= sqrtN ; factor ++ ) {
if ( ! ( n % factor ) ) {
return false ;
}
}
return true ;
}
function getFractionalBits ( n ) {
return ( ( n - ( n | 0 ) ) * 0x100000000 ) | 0 ;
}
var n = 2 ;
var nPrime = 0 ;
while ( nPrime < 64 ) {
if ( isPrime ( n ) ) {
if ( nPrime < 8 ) {
H [ nPrime ] = getFractionalBits ( Math . pow ( n , 1 / 2 ) ) ;
}
K [ nPrime ] = getFractionalBits ( Math . pow ( n , 1 / 3 ) ) ;
nPrime ++ ;
}
n ++ ;
}
} ( ) ) ;
// Reusable object
var W = [ ] ;
/ * *
* SHA - 256 hash algorithm .
* /
var SHA256 = C _algo . SHA256 = Hasher . extend ( {
_doReset : function ( ) {
this . _hash = new WordArray . init ( H . slice ( 0 ) ) ;
} ,
_doProcessBlock : function ( M , offset ) {
// Shortcut
var H = this . _hash . words ;
// Working variables
var a = H [ 0 ] ;
var b = H [ 1 ] ;
var c = H [ 2 ] ;
var d = H [ 3 ] ;
var e = H [ 4 ] ;
var f = H [ 5 ] ;
var g = H [ 6 ] ;
var h = H [ 7 ] ;
// Computation
for ( var i = 0 ; i < 64 ; i ++ ) {
if ( i < 16 ) {
W [ i ] = M [ offset + i ] | 0 ;
} else {
var gamma0x = W [ i - 15 ] ;
var gamma0 = ( ( gamma0x << 25 ) | ( gamma0x >>> 7 ) ) ^
( ( gamma0x << 14 ) | ( gamma0x >>> 18 ) ) ^
( gamma0x >>> 3 ) ;
var gamma1x = W [ i - 2 ] ;
var gamma1 = ( ( gamma1x << 15 ) | ( gamma1x >>> 17 ) ) ^
( ( gamma1x << 13 ) | ( gamma1x >>> 19 ) ) ^
( gamma1x >>> 10 ) ;
W [ i ] = gamma0 + W [ i - 7 ] + gamma1 + W [ i - 16 ] ;
}
var ch = ( e & f ) ^ ( ~ e & g ) ;
var maj = ( a & b ) ^ ( a & c ) ^ ( b & c ) ;
var sigma0 = ( ( a << 30 ) | ( a >>> 2 ) ) ^ ( ( a << 19 ) | ( a >>> 13 ) ) ^ ( ( a << 10 ) | ( a >>> 22 ) ) ;
var sigma1 = ( ( e << 26 ) | ( e >>> 6 ) ) ^ ( ( e << 21 ) | ( e >>> 11 ) ) ^ ( ( e << 7 ) | ( e >>> 25 ) ) ;
var t1 = h + sigma1 + ch + K [ i ] + W [ i ] ;
var t2 = sigma0 + maj ;
h = g ;
g = f ;
f = e ;
e = ( d + t1 ) | 0 ;
d = c ;
c = b ;
b = a ;
a = ( t1 + t2 ) | 0 ;
}
// Intermediate hash value
H [ 0 ] = ( H [ 0 ] + a ) | 0 ;
H [ 1 ] = ( H [ 1 ] + b ) | 0 ;
H [ 2 ] = ( H [ 2 ] + c ) | 0 ;
H [ 3 ] = ( H [ 3 ] + d ) | 0 ;
H [ 4 ] = ( H [ 4 ] + e ) | 0 ;
H [ 5 ] = ( H [ 5 ] + f ) | 0 ;
H [ 6 ] = ( H [ 6 ] + g ) | 0 ;
H [ 7 ] = ( H [ 7 ] + h ) | 0 ;
} ,
_doFinalize : function ( ) {
// Shortcuts
var data = this . _data ;
var dataWords = data . words ;
var nBitsTotal = this . _nDataBytes * 8 ;
var nBitsLeft = data . sigBytes * 8 ;
// Add padding
dataWords [ nBitsLeft >>> 5 ] |= 0x80 << ( 24 - nBitsLeft % 32 ) ;
dataWords [ ( ( ( nBitsLeft + 64 ) >>> 9 ) << 4 ) + 14 ] = Math . floor ( nBitsTotal / 0x100000000 ) ;
dataWords [ ( ( ( nBitsLeft + 64 ) >>> 9 ) << 4 ) + 15 ] = nBitsTotal ;
data . sigBytes = dataWords . length * 4 ;
// Hash final blocks
this . _process ( ) ;
// Return final computed hash
return this . _hash ;
} ,
clone : function ( ) {
var clone = Hasher . clone . call ( this ) ;
clone . _hash = this . _hash . clone ( ) ;
return clone ;
}
} ) ;
/ * *
* Shortcut function to the hasher ' s object interface .
*
* @ param { WordArray | string } message The message to hash .
*
* @ return { WordArray } The hash .
*
* @ static
*
* @ example
*
* var hash = CryptoJS . SHA256 ( 'message' ) ;
* var hash = CryptoJS . SHA256 ( wordArray ) ;
* /
C . SHA256 = Hasher . _createHelper ( SHA256 ) ;
/ * *
* Shortcut function to the HMAC ' s object interface .
*
* @ param { WordArray | string } message The message to hash .
* @ param { WordArray | string } key The secret key .
*
* @ return { WordArray } The HMAC .
*
* @ static
*
* @ example
*
* var hmac = CryptoJS . HmacSHA256 ( message , key ) ;
* /
C . HmacSHA256 = Hasher . _createHmacHelper ( SHA256 ) ;
} ( Math ) ) ;
( function ( ) {
// Shortcuts
var C = CryptoJS ;
var C _lib = C . lib ;
var Base = C _lib . Base ;
var C _enc = C . enc ;
var Utf8 = C _enc . Utf8 ;
var C _algo = C . algo ;
/ * *
* HMAC algorithm .
* /
var HMAC = C _algo . HMAC = Base . extend ( {
/ * *
* Initializes a newly created HMAC .
*
* @ param { Hasher } hasher The hash algorithm to use .
* @ param { WordArray | string } key The secret key .
*
* @ example
*
* var hmacHasher = CryptoJS . algo . HMAC . create ( CryptoJS . algo . SHA256 , key ) ;
* /
init : function ( hasher , key ) {
// Init hasher
hasher = this . _hasher = new hasher . init ( ) ;
// Convert string to WordArray, else assume WordArray already
if ( typeof key == 'string' ) {
key = Utf8 . parse ( key ) ;
}
// Shortcuts
var hasherBlockSize = hasher . blockSize ;
var hasherBlockSizeBytes = hasherBlockSize * 4 ;
// Allow arbitrary length keys
if ( key . sigBytes > hasherBlockSizeBytes ) {
key = hasher . finalize ( key ) ;
}
// Clamp excess bits
key . clamp ( ) ;
// Clone key for inner and outer pads
var oKey = this . _oKey = key . clone ( ) ;
var iKey = this . _iKey = key . clone ( ) ;
// Shortcuts
var oKeyWords = oKey . words ;
var iKeyWords = iKey . words ;
// XOR keys with pad constants
for ( var i = 0 ; i < hasherBlockSize ; i ++ ) {
oKeyWords [ i ] ^= 0x5c5c5c5c ;
iKeyWords [ i ] ^= 0x36363636 ;
}
oKey . sigBytes = iKey . sigBytes = hasherBlockSizeBytes ;
// Set initial values
this . reset ( ) ;
} ,
/ * *
* Resets this HMAC to its initial state .
*
* @ example
*
* hmacHasher . reset ( ) ;
* /
reset : function ( ) {
// Shortcut
var hasher = this . _hasher ;
// Reset
hasher . reset ( ) ;
hasher . update ( this . _iKey ) ;
} ,
/ * *
* Updates this HMAC with a message .
*
* @ param { WordArray | string } messageUpdate The message to append .
*
* @ return { HMAC } This HMAC instance .
*
* @ example
*
* hmacHasher . update ( 'message' ) ;
* hmacHasher . update ( wordArray ) ;
* /
update : function ( messageUpdate ) {
this . _hasher . update ( messageUpdate ) ;
// Chainable
return this ;
} ,
/ * *
* Finalizes the HMAC computation .
* Note that the finalize operation is effectively a destructive , read - once operation .
*
* @ param { WordArray | string } messageUpdate ( Optional ) A final message update .
*
* @ return { WordArray } The HMAC .
*
* @ example
*
* var hmac = hmacHasher . finalize ( ) ;
* var hmac = hmacHasher . finalize ( 'message' ) ;
* var hmac = hmacHasher . finalize ( wordArray ) ;
* /
finalize : function ( messageUpdate ) {
// Shortcut
var hasher = this . _hasher ;
// Compute HMAC
var innerHash = hasher . finalize ( messageUpdate ) ;
hasher . reset ( ) ;
var hmac = hasher . finalize ( this . _oKey . clone ( ) . concat ( innerHash ) ) ;
return hmac ;
}
} ) ;
} ( ) ) ;
2015-02-10 16:39:50 -08:00
2015-02-20 15:05:32 -08:00
( function ( ) {
// Shortcuts
var C = CryptoJS ;
var C _lib = C . lib ;
var WordArray = C _lib . WordArray ;
var C _enc = C . enc ;
2015-02-10 16:39:50 -08:00
/ * *
2015-02-20 15:05:32 -08:00
* Base64 encoding strategy .
2015-02-10 16:39:50 -08:00
* /
2015-02-20 15:05:32 -08:00
var Base64 = C _enc . Base64 = {
2015-02-10 16:39:50 -08:00
/ * *
2015-02-20 15:05:32 -08:00
* Converts a word array to a Base64 string .
2015-02-10 16:39:50 -08:00
*
* @ param { WordArray } wordArray The word array .
*
2015-02-20 15:05:32 -08:00
* @ return { string } The Base64 string .
2015-02-10 16:39:50 -08:00
*
* @ static
*
* @ example
*
2015-02-20 15:05:32 -08:00
* var base64String = CryptoJS . enc . Base64 . stringify ( wordArray ) ;
2015-02-10 16:39:50 -08:00
* /
stringify : function ( wordArray ) {
// Shortcuts
var words = wordArray . words ;
var sigBytes = wordArray . sigBytes ;
2015-02-20 15:05:32 -08:00
var map = this . _map ;
2015-02-10 16:39:50 -08:00
2015-02-20 15:05:32 -08:00
// Clamp excess bits
wordArray . clamp ( ) ;
2015-02-10 16:39:50 -08:00
// Convert
2015-02-20 15:05:32 -08:00
var base64Chars = [ ] ;
for ( var i = 0 ; i < sigBytes ; i += 3 ) {
var byte1 = ( words [ i >>> 2 ] >>> ( 24 - ( i % 4 ) * 8 ) ) & 0xff ;
var byte2 = ( words [ ( i + 1 ) >>> 2 ] >>> ( 24 - ( ( i + 1 ) % 4 ) * 8 ) ) & 0xff ;
var byte3 = ( words [ ( i + 2 ) >>> 2 ] >>> ( 24 - ( ( i + 2 ) % 4 ) * 8 ) ) & 0xff ;
2015-02-10 16:39:50 -08:00
2015-02-20 15:05:32 -08:00
var triplet = ( byte1 << 16 ) | ( byte2 << 8 ) | byte3 ;
2015-02-10 16:39:50 -08:00
2015-02-20 15:05:32 -08:00
for ( var j = 0 ; ( j < 4 ) && ( i + j * 0.75 < sigBytes ) ; j ++ ) {
base64Chars . push ( map . charAt ( ( triplet >>> ( 6 * ( 3 - j ) ) ) & 0x3f ) ) ;
}
}
2015-02-10 16:39:50 -08:00
2015-02-20 15:05:32 -08:00
// Add padding
var paddingChar = map . charAt ( 64 ) ;
if ( paddingChar ) {
while ( base64Chars . length % 4 ) {
base64Chars . push ( paddingChar ) ;
}
2015-02-10 16:39:50 -08:00
}
2015-02-20 15:05:32 -08:00
return base64Chars . join ( '' ) ;
2015-02-10 16:39:50 -08:00
} ,
/ * *
2015-02-20 15:05:32 -08:00
* Converts a Base64 string to a word array .
2015-02-10 16:39:50 -08:00
*
2015-02-20 15:05:32 -08:00
* @ param { string } base64Str The Base64 string .
2015-02-10 16:39:50 -08:00
*
* @ return { WordArray } The word array .
*
* @ static
*
* @ example
*
2015-02-20 15:05:32 -08:00
* var wordArray = CryptoJS . enc . Base64 . parse ( base64String ) ;
2015-02-10 16:39:50 -08:00
* /
2015-02-20 15:05:32 -08:00
parse : function ( base64Str ) {
// Shortcuts
var base64StrLength = base64Str . length ;
var map = this . _map ;
// Ignore padding
var paddingChar = map . charAt ( 64 ) ;
if ( paddingChar ) {
var paddingIndex = base64Str . indexOf ( paddingChar ) ;
if ( paddingIndex != - 1 ) {
base64StrLength = paddingIndex ;
}
}
2015-02-10 16:39:50 -08:00
// Convert
var words = [ ] ;
2015-02-20 15:05:32 -08:00
var nBytes = 0 ;
for ( var i = 0 ; i < base64StrLength ; i ++ ) {
if ( i % 4 ) {
var bits1 = map . indexOf ( base64Str . charAt ( i - 1 ) ) << ( ( i % 4 ) * 2 ) ;
var bits2 = map . indexOf ( base64Str . charAt ( i ) ) >>> ( 6 - ( i % 4 ) * 2 ) ;
words [ nBytes >>> 2 ] |= ( bits1 | bits2 ) << ( 24 - ( nBytes % 4 ) * 8 ) ;
nBytes ++ ;
}
2015-02-10 16:39:50 -08:00
}
2015-02-20 15:05:32 -08:00
return WordArray . create ( words , nBytes ) ;
2015-02-10 16:39:50 -08:00
} ,
2015-02-20 15:05:32 -08:00
_map : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
2015-02-10 16:39:50 -08:00
} ;
2015-02-20 15:05:32 -08:00
} ( ) ) ;
2015-02-10 16:39:50 -08:00
2015-02-20 15:05:32 -08:00
( function ( Math ) {
// Shortcuts
var C = CryptoJS ;
var C _lib = C . lib ;
var WordArray = C _lib . WordArray ;
var Hasher = C _lib . Hasher ;
var C _algo = C . algo ;
// Constants table
var T = [ ] ;
// Compute constants
( function ( ) {
for ( var i = 0 ; i < 64 ; i ++ ) {
T [ i ] = ( Math . abs ( Math . sin ( i + 1 ) ) * 0x100000000 ) | 0 ;
}
} ( ) ) ;
/ * *
* MD5 hash algorithm .
* /
var MD5 = C _algo . MD5 = Hasher . extend ( {
_doReset : function ( ) {
this . _hash = new WordArray . init ( [
0x67452301 , 0xefcdab89 ,
0x98badcfe , 0x10325476
] ) ;
} ,
_doProcessBlock : function ( M , offset ) {
// Swap endian
for ( var i = 0 ; i < 16 ; i ++ ) {
// Shortcuts
var offset _i = offset + i ;
var M _offset _i = M [ offset _i ] ;
M [ offset _i ] = (
( ( ( M _offset _i << 8 ) | ( M _offset _i >>> 24 ) ) & 0x00ff00ff ) |
( ( ( M _offset _i << 24 ) | ( M _offset _i >>> 8 ) ) & 0xff00ff00 )
) ;
}
// Shortcuts
var H = this . _hash . words ;
var M _offset _0 = M [ offset + 0 ] ;
var M _offset _1 = M [ offset + 1 ] ;
var M _offset _2 = M [ offset + 2 ] ;
var M _offset _3 = M [ offset + 3 ] ;
var M _offset _4 = M [ offset + 4 ] ;
var M _offset _5 = M [ offset + 5 ] ;
var M _offset _6 = M [ offset + 6 ] ;
var M _offset _7 = M [ offset + 7 ] ;
var M _offset _8 = M [ offset + 8 ] ;
var M _offset _9 = M [ offset + 9 ] ;
var M _offset _10 = M [ offset + 10 ] ;
var M _offset _11 = M [ offset + 11 ] ;
var M _offset _12 = M [ offset + 12 ] ;
var M _offset _13 = M [ offset + 13 ] ;
var M _offset _14 = M [ offset + 14 ] ;
var M _offset _15 = M [ offset + 15 ] ;
// Working varialbes
var a = H [ 0 ] ;
var b = H [ 1 ] ;
var c = H [ 2 ] ;
var d = H [ 3 ] ;
// Computation
a = FF ( a , b , c , d , M _offset _0 , 7 , T [ 0 ] ) ;
d = FF ( d , a , b , c , M _offset _1 , 12 , T [ 1 ] ) ;
c = FF ( c , d , a , b , M _offset _2 , 17 , T [ 2 ] ) ;
b = FF ( b , c , d , a , M _offset _3 , 22 , T [ 3 ] ) ;
a = FF ( a , b , c , d , M _offset _4 , 7 , T [ 4 ] ) ;
d = FF ( d , a , b , c , M _offset _5 , 12 , T [ 5 ] ) ;
c = FF ( c , d , a , b , M _offset _6 , 17 , T [ 6 ] ) ;
b = FF ( b , c , d , a , M _offset _7 , 22 , T [ 7 ] ) ;
a = FF ( a , b , c , d , M _offset _8 , 7 , T [ 8 ] ) ;
d = FF ( d , a , b , c , M _offset _9 , 12 , T [ 9 ] ) ;
c = FF ( c , d , a , b , M _offset _10 , 17 , T [ 10 ] ) ;
b = FF ( b , c , d , a , M _offset _11 , 22 , T [ 11 ] ) ;
a = FF ( a , b , c , d , M _offset _12 , 7 , T [ 12 ] ) ;
d = FF ( d , a , b , c , M _offset _13 , 12 , T [ 13 ] ) ;
c = FF ( c , d , a , b , M _offset _14 , 17 , T [ 14 ] ) ;
b = FF ( b , c , d , a , M _offset _15 , 22 , T [ 15 ] ) ;
a = GG ( a , b , c , d , M _offset _1 , 5 , T [ 16 ] ) ;
d = GG ( d , a , b , c , M _offset _6 , 9 , T [ 17 ] ) ;
c = GG ( c , d , a , b , M _offset _11 , 14 , T [ 18 ] ) ;
b = GG ( b , c , d , a , M _offset _0 , 20 , T [ 19 ] ) ;
a = GG ( a , b , c , d , M _offset _5 , 5 , T [ 20 ] ) ;
d = GG ( d , a , b , c , M _offset _10 , 9 , T [ 21 ] ) ;
c = GG ( c , d , a , b , M _offset _15 , 14 , T [ 22 ] ) ;
b = GG ( b , c , d , a , M _offset _4 , 20 , T [ 23 ] ) ;
a = GG ( a , b , c , d , M _offset _9 , 5 , T [ 24 ] ) ;
d = GG ( d , a , b , c , M _offset _14 , 9 , T [ 25 ] ) ;
c = GG ( c , d , a , b , M _offset _3 , 14 , T [ 26 ] ) ;
b = GG ( b , c , d , a , M _offset _8 , 20 , T [ 27 ] ) ;
a = GG ( a , b , c , d , M _offset _13 , 5 , T [ 28 ] ) ;
d = GG ( d , a , b , c , M _offset _2 , 9 , T [ 29 ] ) ;
c = GG ( c , d , a , b , M _offset _7 , 14 , T [ 30 ] ) ;
b = GG ( b , c , d , a , M _offset _12 , 20 , T [ 31 ] ) ;
a = HH ( a , b , c , d , M _offset _5 , 4 , T [ 32 ] ) ;
d = HH ( d , a , b , c , M _offset _8 , 11 , T [ 33 ] ) ;
c = HH ( c , d , a , b , M _offset _11 , 16 , T [ 34 ] ) ;
b = HH ( b , c , d , a , M _offset _14 , 23 , T [ 35 ] ) ;
a = HH ( a , b , c , d , M _offset _1 , 4 , T [ 36 ] ) ;
d = HH ( d , a , b , c , M _offset _4 , 11 , T [ 37 ] ) ;
c = HH ( c , d , a , b , M _offset _7 , 16 , T [ 38 ] ) ;
b = HH ( b , c , d , a , M _offset _10 , 23 , T [ 39 ] ) ;
a = HH ( a , b , c , d , M _offset _13 , 4 , T [ 40 ] ) ;
d = HH ( d , a , b , c , M _offset _0 , 11 , T [ 41 ] ) ;
c = HH ( c , d , a , b , M _offset _3 , 16 , T [ 42 ] ) ;
b = HH ( b , c , d , a , M _offset _6 , 23 , T [ 43 ] ) ;
a = HH ( a , b , c , d , M _offset _9 , 4 , T [ 44 ] ) ;
d = HH ( d , a , b , c , M _offset _12 , 11 , T [ 45 ] ) ;
c = HH ( c , d , a , b , M _offset _15 , 16 , T [ 46 ] ) ;
b = HH ( b , c , d , a , M _offset _2 , 23 , T [ 47 ] ) ;
a = II ( a , b , c , d , M _offset _0 , 6 , T [ 48 ] ) ;
d = II ( d , a , b , c , M _offset _7 , 10 , T [ 49 ] ) ;
c = II ( c , d , a , b , M _offset _14 , 15 , T [ 50 ] ) ;
b = II ( b , c , d , a , M _offset _5 , 21 , T [ 51 ] ) ;
a = II ( a , b , c , d , M _offset _12 , 6 , T [ 52 ] ) ;
d = II ( d , a , b , c , M _offset _3 , 10 , T [ 53 ] ) ;
c = II ( c , d , a , b , M _offset _10 , 15 , T [ 54 ] ) ;
b = II ( b , c , d , a , M _offset _1 , 21 , T [ 55 ] ) ;
a = II ( a , b , c , d , M _offset _8 , 6 , T [ 56 ] ) ;
d = II ( d , a , b , c , M _offset _15 , 10 , T [ 57 ] ) ;
c = II ( c , d , a , b , M _offset _6 , 15 , T [ 58 ] ) ;
b = II ( b , c , d , a , M _offset _13 , 21 , T [ 59 ] ) ;
a = II ( a , b , c , d , M _offset _4 , 6 , T [ 60 ] ) ;
d = II ( d , a , b , c , M _offset _11 , 10 , T [ 61 ] ) ;
c = II ( c , d , a , b , M _offset _2 , 15 , T [ 62 ] ) ;
b = II ( b , c , d , a , M _offset _9 , 21 , T [ 63 ] ) ;
// Intermediate hash value
H [ 0 ] = ( H [ 0 ] + a ) | 0 ;
H [ 1 ] = ( H [ 1 ] + b ) | 0 ;
H [ 2 ] = ( H [ 2 ] + c ) | 0 ;
H [ 3 ] = ( H [ 3 ] + d ) | 0 ;
} ,
_doFinalize : function ( ) {
// Shortcuts
var data = this . _data ;
var dataWords = data . words ;
var nBitsTotal = this . _nDataBytes * 8 ;
var nBitsLeft = data . sigBytes * 8 ;
// Add padding
dataWords [ nBitsLeft >>> 5 ] |= 0x80 << ( 24 - nBitsLeft % 32 ) ;
var nBitsTotalH = Math . floor ( nBitsTotal / 0x100000000 ) ;
var nBitsTotalL = nBitsTotal ;
dataWords [ ( ( ( nBitsLeft + 64 ) >>> 9 ) << 4 ) + 15 ] = (
( ( ( nBitsTotalH << 8 ) | ( nBitsTotalH >>> 24 ) ) & 0x00ff00ff ) |
( ( ( nBitsTotalH << 24 ) | ( nBitsTotalH >>> 8 ) ) & 0xff00ff00 )
) ;
dataWords [ ( ( ( nBitsLeft + 64 ) >>> 9 ) << 4 ) + 14 ] = (
( ( ( nBitsTotalL << 8 ) | ( nBitsTotalL >>> 24 ) ) & 0x00ff00ff ) |
( ( ( nBitsTotalL << 24 ) | ( nBitsTotalL >>> 8 ) ) & 0xff00ff00 )
) ;
data . sigBytes = ( dataWords . length + 1 ) * 4 ;
// Hash final blocks
this . _process ( ) ;
// Shortcuts
var hash = this . _hash ;
var H = hash . words ;
// Swap endian
for ( var i = 0 ; i < 4 ; i ++ ) {
// Shortcut
var H _i = H [ i ] ;
H [ i ] = ( ( ( H _i << 8 ) | ( H _i >>> 24 ) ) & 0x00ff00ff ) |
( ( ( H _i << 24 ) | ( H _i >>> 8 ) ) & 0xff00ff00 ) ;
}
// Return final computed hash
return hash ;
} ,
clone : function ( ) {
var clone = Hasher . clone . call ( this ) ;
clone . _hash = this . _hash . clone ( ) ;
return clone ;
}
} ) ;
function FF ( a , b , c , d , x , s , t ) {
var n = a + ( ( b & c ) | ( ~ b & d ) ) + x + t ;
return ( ( n << s ) | ( n >>> ( 32 - s ) ) ) + b ;
}
function GG ( a , b , c , d , x , s , t ) {
var n = a + ( ( b & d ) | ( c & ~ d ) ) + x + t ;
return ( ( n << s ) | ( n >>> ( 32 - s ) ) ) + b ;
}
function HH ( a , b , c , d , x , s , t ) {
var n = a + ( b ^ c ^ d ) + x + t ;
return ( ( n << s ) | ( n >>> ( 32 - s ) ) ) + b ;
}
function II ( a , b , c , d , x , s , t ) {
var n = a + ( c ^ ( b | ~ d ) ) + x + t ;
return ( ( n << s ) | ( n >>> ( 32 - s ) ) ) + b ;
}
/ * *
* Shortcut function to the hasher ' s object interface .
*
* @ param { WordArray | string } message The message to hash .
*
* @ return { WordArray } The hash .
*
* @ static
*
* @ example
*
* var hash = CryptoJS . MD5 ( 'message' ) ;
* var hash = CryptoJS . MD5 ( wordArray ) ;
* /
C . MD5 = Hasher . _createHelper ( MD5 ) ;
/ * *
* Shortcut function to the HMAC ' s object interface .
*
* @ param { WordArray | string } message The message to hash .
* @ param { WordArray | string } key The secret key .
*
* @ return { WordArray } The HMAC .
*
* @ static
*
* @ example
*
* var hmac = CryptoJS . HmacMD5 ( message , key ) ;
* /
C . HmacMD5 = Hasher . _createHmacHelper ( MD5 ) ;
} ( Math ) ) ;
( function ( ) {
// Shortcuts
var C = CryptoJS ;
var C _lib = C . lib ;
var Base = C _lib . Base ;
var WordArray = C _lib . WordArray ;
var C _algo = C . algo ;
var MD5 = C _algo . MD5 ;
/ * *
* This key derivation function is meant to conform with EVP _BytesToKey .
* www . openssl . org / docs / crypto / EVP _BytesToKey . html
* /
var EvpKDF = C _algo . EvpKDF = Base . extend ( {
/ * *
* Configuration options .
*
* @ property { number } keySize The key size in words to generate . Default : 4 ( 128 bits )
* @ property { Hasher } hasher The hash algorithm to use . Default : MD5
* @ property { number } iterations The number of iterations to perform . Default : 1
* /
cfg : Base . extend ( {
keySize : 128 / 32 ,
hasher : MD5 ,
iterations : 1
} ) ,
/ * *
* Initializes a newly created key derivation function .
*
* @ param { Object } cfg ( Optional ) The configuration options to use for the derivation .
*
* @ example
*
* var kdf = CryptoJS . algo . EvpKDF . create ( ) ;
* var kdf = CryptoJS . algo . EvpKDF . create ( { keySize : 8 } ) ;
* var kdf = CryptoJS . algo . EvpKDF . create ( { keySize : 8 , iterations : 1000 } ) ;
* /
init : function ( cfg ) {
this . cfg = this . cfg . extend ( cfg ) ;
} ,
/ * *
* Derives a key from a password .
*
* @ param { WordArray | string } password The password .
* @ param { WordArray | string } salt A salt .
*
* @ return { WordArray } The derived key .
*
* @ example
*
* var key = kdf . compute ( password , salt ) ;
* /
compute : function ( password , salt ) {
// Shortcut
var cfg = this . cfg ;
// Init hasher
var hasher = cfg . hasher . create ( ) ;
// Initial values
var derivedKey = WordArray . create ( ) ;
// Shortcuts
var derivedKeyWords = derivedKey . words ;
var keySize = cfg . keySize ;
var iterations = cfg . iterations ;
// Generate key
while ( derivedKeyWords . length < keySize ) {
if ( block ) {
hasher . update ( block ) ;
}
var block = hasher . update ( password ) . finalize ( salt ) ;
hasher . reset ( ) ;
// Iterations
for ( var i = 1 ; i < iterations ; i ++ ) {
block = hasher . finalize ( block ) ;
hasher . reset ( ) ;
}
derivedKey . concat ( block ) ;
}
derivedKey . sigBytes = keySize * 4 ;
return derivedKey ;
}
} ) ;
/ * *
* Derives a key from a password .
*
* @ param { WordArray | string } password The password .
* @ param { WordArray | string } salt A salt .
* @ param { Object } cfg ( Optional ) The configuration options to use for this computation .
*
* @ return { WordArray } The derived key .
*
* @ static
*
* @ example
*
* var key = CryptoJS . EvpKDF ( password , salt ) ;
* var key = CryptoJS . EvpKDF ( password , salt , { keySize : 8 } ) ;
* var key = CryptoJS . EvpKDF ( password , salt , { keySize : 8 , iterations : 1000 } ) ;
* /
C . EvpKDF = function ( password , salt , cfg ) {
return EvpKDF . create ( cfg ) . compute ( password , salt ) ;
} ;
} ( ) ) ;
/ * *
* Cipher core components .
* /
CryptoJS . lib . Cipher || ( function ( undefined ) {
// Shortcuts
var C = CryptoJS ;
var C _lib = C . lib ;
var Base = C _lib . Base ;
var WordArray = C _lib . WordArray ;
var BufferedBlockAlgorithm = C _lib . BufferedBlockAlgorithm ;
var C _enc = C . enc ;
var Utf8 = C _enc . Utf8 ;
var Base64 = C _enc . Base64 ;
var C _algo = C . algo ;
var EvpKDF = C _algo . EvpKDF ;
/ * *
* Abstract base cipher template .
*
* @ property { number } keySize This cipher ' s key size . Default : 4 ( 128 bits )
* @ property { number } ivSize This cipher ' s IV size . Default : 4 ( 128 bits )
* @ property { number } _ENC _XFORM _MODE A constant representing encryption mode .
* @ property { number } _DEC _XFORM _MODE A constant representing decryption mode .
* /
var Cipher = C _lib . Cipher = BufferedBlockAlgorithm . extend ( {
/ * *
* Configuration options .
*
* @ property { WordArray } iv The IV to use for this operation .
* /
cfg : Base . extend ( ) ,
/ * *
* Creates this cipher in encryption mode .
*
* @ param { WordArray } key The key .
* @ param { Object } cfg ( Optional ) The configuration options to use for this operation .
*
* @ return { Cipher } A cipher instance .
*
* @ static
*
* @ example
*
* var cipher = CryptoJS . algo . AES . createEncryptor ( keyWordArray , { iv : ivWordArray } ) ;
* /
createEncryptor : function ( key , cfg ) {
return this . create ( this . _ENC _XFORM _MODE , key , cfg ) ;
} ,
/ * *
* Creates this cipher in decryption mode .
*
* @ param { WordArray } key The key .
* @ param { Object } cfg ( Optional ) The configuration options to use for this operation .
*
* @ return { Cipher } A cipher instance .
*
* @ static
*
* @ example
*
* var cipher = CryptoJS . algo . AES . createDecryptor ( keyWordArray , { iv : ivWordArray } ) ;
* /
createDecryptor : function ( key , cfg ) {
return this . create ( this . _DEC _XFORM _MODE , key , cfg ) ;
} ,
/ * *
* Initializes a newly created cipher .
*
* @ param { number } xformMode Either the encryption or decryption transormation mode constant .
* @ param { WordArray } key The key .
* @ param { Object } cfg ( Optional ) The configuration options to use for this operation .
*
* @ example
*
* var cipher = CryptoJS . algo . AES . create ( CryptoJS . algo . AES . _ENC _XFORM _MODE , keyWordArray , { iv : ivWordArray } ) ;
* /
init : function ( xformMode , key , cfg ) {
// Apply config defaults
this . cfg = this . cfg . extend ( cfg ) ;
// Store transform mode and key
this . _xformMode = xformMode ;
this . _key = key ;
// Set initial values
this . reset ( ) ;
} ,
/ * *
* Resets this cipher to its initial state .
*
* @ example
*
* cipher . reset ( ) ;
* /
reset : function ( ) {
// Reset data buffer
BufferedBlockAlgorithm . reset . call ( this ) ;
// Perform concrete-cipher logic
this . _doReset ( ) ;
} ,
/ * *
* Adds data to be encrypted or decrypted .
*
* @ param { WordArray | string } dataUpdate The data to encrypt or decrypt .
*
* @ return { WordArray } The data after processing .
*
* @ example
*
* var encrypted = cipher . process ( 'data' ) ;
* var encrypted = cipher . process ( wordArray ) ;
* /
process : function ( dataUpdate ) {
// Append
this . _append ( dataUpdate ) ;
// Process available blocks
return this . _process ( ) ;
} ,
/ * *
* Finalizes the encryption or decryption process .
* Note that the finalize operation is effectively a destructive , read - once operation .
*
* @ param { WordArray | string } dataUpdate The final data to encrypt or decrypt .
*
* @ return { WordArray } The data after final processing .
*
* @ example
*
* var encrypted = cipher . finalize ( ) ;
* var encrypted = cipher . finalize ( 'data' ) ;
* var encrypted = cipher . finalize ( wordArray ) ;
* /
finalize : function ( dataUpdate ) {
// Final data update
if ( dataUpdate ) {
this . _append ( dataUpdate ) ;
}
// Perform concrete-cipher logic
var finalProcessedData = this . _doFinalize ( ) ;
return finalProcessedData ;
} ,
keySize : 128 / 32 ,
ivSize : 128 / 32 ,
_ENC _XFORM _MODE : 1 ,
_DEC _XFORM _MODE : 2 ,
/ * *
* Creates shortcut functions to a cipher ' s object interface .
*
* @ param { Cipher } cipher The cipher to create a helper for .
*
* @ return { Object } An object with encrypt and decrypt shortcut functions .
*
* @ static
*
* @ example
*
* var AES = CryptoJS . lib . Cipher . _createHelper ( CryptoJS . algo . AES ) ;
* /
_createHelper : ( function ( ) {
function selectCipherStrategy ( key ) {
if ( typeof key == 'string' ) {
return PasswordBasedCipher ;
} else {
return SerializableCipher ;
}
}
return function ( cipher ) {
return {
encrypt : function ( message , key , cfg ) {
return selectCipherStrategy ( key ) . encrypt ( cipher , message , key , cfg ) ;
} ,
decrypt : function ( ciphertext , key , cfg ) {
return selectCipherStrategy ( key ) . decrypt ( cipher , ciphertext , key , cfg ) ;
}
} ;
} ;
} ( ) )
} ) ;
/ * *
* Abstract base stream cipher template .
*
* @ property { number } blockSize The number of 32 - bit words this cipher operates on . Default : 1 ( 32 bits )
* /
var StreamCipher = C _lib . StreamCipher = Cipher . extend ( {
_doFinalize : function ( ) {
// Process partial blocks
var finalProcessedBlocks = this . _process ( ! ! 'flush' ) ;
return finalProcessedBlocks ;
} ,
blockSize : 1
} ) ;
/ * *
* Mode namespace .
* /
var C _mode = C . mode = { } ;
/ * *
* Abstract base block cipher mode template .
* /
var BlockCipherMode = C _lib . BlockCipherMode = Base . extend ( {
/ * *
* Creates this mode for encryption .
*
* @ param { Cipher } cipher A block cipher instance .
* @ param { Array } iv The IV words .
*
* @ static
*
* @ example
*
* var mode = CryptoJS . mode . CBC . createEncryptor ( cipher , iv . words ) ;
* /
createEncryptor : function ( cipher , iv ) {
return this . Encryptor . create ( cipher , iv ) ;
} ,
/ * *
* Creates this mode for decryption .
*
* @ param { Cipher } cipher A block cipher instance .
* @ param { Array } iv The IV words .
*
* @ static
*
* @ example
*
* var mode = CryptoJS . mode . CBC . createDecryptor ( cipher , iv . words ) ;
* /
createDecryptor : function ( cipher , iv ) {
return this . Decryptor . create ( cipher , iv ) ;
} ,
/ * *
* Initializes a newly created mode .
*
* @ param { Cipher } cipher A block cipher instance .
* @ param { Array } iv The IV words .
*
* @ example
*
* var mode = CryptoJS . mode . CBC . Encryptor . create ( cipher , iv . words ) ;
* /
init : function ( cipher , iv ) {
this . _cipher = cipher ;
this . _iv = iv ;
}
} ) ;
/ * *
* Cipher Block Chaining mode .
* /
var CBC = C _mode . CBC = ( function ( ) {
/ * *
* Abstract base CBC mode .
* /
var CBC = BlockCipherMode . extend ( ) ;
/ * *
* CBC encryptor .
* /
CBC . Encryptor = CBC . extend ( {
/ * *
* Processes the data block at offset .
*
* @ param { Array } words The data words to operate on .
* @ param { number } offset The offset where the block starts .
*
* @ example
*
* mode . processBlock ( data . words , offset ) ;
* /
processBlock : function ( words , offset ) {
// Shortcuts
var cipher = this . _cipher ;
var blockSize = cipher . blockSize ;
// XOR and encrypt
xorBlock . call ( this , words , offset , blockSize ) ;
cipher . encryptBlock ( words , offset ) ;
// Remember this block to use with next block
this . _prevBlock = words . slice ( offset , offset + blockSize ) ;
}
} ) ;
/ * *
* CBC decryptor .
* /
CBC . Decryptor = CBC . extend ( {
/ * *
* Processes the data block at offset .
*
* @ param { Array } words The data words to operate on .
* @ param { number } offset The offset where the block starts .
*
* @ example
*
* mode . processBlock ( data . words , offset ) ;
* /
processBlock : function ( words , offset ) {
// Shortcuts
var cipher = this . _cipher ;
var blockSize = cipher . blockSize ;
// Remember this block to use with next block
var thisBlock = words . slice ( offset , offset + blockSize ) ;
// Decrypt and XOR
cipher . decryptBlock ( words , offset ) ;
xorBlock . call ( this , words , offset , blockSize ) ;
// This block becomes the previous block
this . _prevBlock = thisBlock ;
}
} ) ;
function xorBlock ( words , offset , blockSize ) {
// Shortcut
var iv = this . _iv ;
// Choose mixing block
if ( iv ) {
var block = iv ;
// Remove IV for subsequent blocks
this . _iv = undefined ;
} else {
var block = this . _prevBlock ;
}
// XOR blocks
for ( var i = 0 ; i < blockSize ; i ++ ) {
words [ offset + i ] ^= block [ i ] ;
}
}
return CBC ;
} ( ) ) ;
/ * *
* Padding namespace .
* /
var C _pad = C . pad = { } ;
/ * *
* PKCS # 5 / 7 padding strategy .
* /
var Pkcs7 = C _pad . Pkcs7 = {
/ * *
* Pads data using the algorithm defined in PKCS # 5 / 7.
*
* @ param { WordArray } data The data to pad .
* @ param { number } blockSize The multiple that the data should be padded to .
*
* @ static
*
* @ example
*
* CryptoJS . pad . Pkcs7 . pad ( wordArray , 4 ) ;
* /
pad : function ( data , blockSize ) {
// Shortcut
var blockSizeBytes = blockSize * 4 ;
// Count padding bytes
var nPaddingBytes = blockSizeBytes - data . sigBytes % blockSizeBytes ;
// Create padding word
var paddingWord = ( nPaddingBytes << 24 ) | ( nPaddingBytes << 16 ) | ( nPaddingBytes << 8 ) | nPaddingBytes ;
// Create padding
var paddingWords = [ ] ;
for ( var i = 0 ; i < nPaddingBytes ; i += 4 ) {
paddingWords . push ( paddingWord ) ;
}
var padding = WordArray . create ( paddingWords , nPaddingBytes ) ;
// Add padding
data . concat ( padding ) ;
} ,
/ * *
* Unpads data that had been padded using the algorithm defined in PKCS # 5 / 7.
*
* @ param { WordArray } data The data to unpad .
*
* @ static
*
* @ example
*
* CryptoJS . pad . Pkcs7 . unpad ( wordArray ) ;
* /
unpad : function ( data ) {
// Get number of padding bytes from last byte
var nPaddingBytes = data . words [ ( data . sigBytes - 1 ) >>> 2 ] & 0xff ;
// Remove padding
data . sigBytes -= nPaddingBytes ;
}
} ;
/ * *
* Abstract base block cipher template .
*
* @ property { number } blockSize The number of 32 - bit words this cipher operates on . Default : 4 ( 128 bits )
* /
var BlockCipher = C _lib . BlockCipher = Cipher . extend ( {
/ * *
* Configuration options .
*
* @ property { Mode } mode The block mode to use . Default : CBC
* @ property { Padding } padding The padding strategy to use . Default : Pkcs7
* /
cfg : Cipher . cfg . extend ( {
mode : CBC ,
padding : Pkcs7
} ) ,
reset : function ( ) {
// Reset cipher
Cipher . reset . call ( this ) ;
// Shortcuts
var cfg = this . cfg ;
var iv = cfg . iv ;
var mode = cfg . mode ;
// Reset block mode
if ( this . _xformMode == this . _ENC _XFORM _MODE ) {
var modeCreator = mode . createEncryptor ;
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
var modeCreator = mode . createDecryptor ;
// Keep at least one block in the buffer for unpadding
this . _minBufferSize = 1 ;
}
this . _mode = modeCreator . call ( mode , this , iv && iv . words ) ;
} ,
_doProcessBlock : function ( words , offset ) {
this . _mode . processBlock ( words , offset ) ;
} ,
_doFinalize : function ( ) {
// Shortcut
var padding = this . cfg . padding ;
// Finalize
if ( this . _xformMode == this . _ENC _XFORM _MODE ) {
// Pad data
padding . pad ( this . _data , this . blockSize ) ;
// Process final blocks
var finalProcessedBlocks = this . _process ( ! ! 'flush' ) ;
} else /* if (this._xformMode == this._DEC_XFORM_MODE) */ {
// Process final blocks
var finalProcessedBlocks = this . _process ( ! ! 'flush' ) ;
// Unpad data
padding . unpad ( finalProcessedBlocks ) ;
}
return finalProcessedBlocks ;
} ,
blockSize : 128 / 32
} ) ;
/ * *
* A collection of cipher parameters .
*
* @ property { WordArray } ciphertext The raw ciphertext .
* @ property { WordArray } key The key to this ciphertext .
* @ property { WordArray } iv The IV used in the ciphering operation .
* @ property { WordArray } salt The salt used with a key derivation function .
* @ property { Cipher } algorithm The cipher algorithm .
* @ property { Mode } mode The block mode used in the ciphering operation .
* @ property { Padding } padding The padding scheme used in the ciphering operation .
* @ property { number } blockSize The block size of the cipher .
* @ property { Format } formatter The default formatting strategy to convert this cipher params object to a string .
* /
var CipherParams = C _lib . CipherParams = Base . extend ( {
/ * *
* Initializes a newly created cipher params object .
*
* @ param { Object } cipherParams An object with any of the possible cipher parameters .
*
* @ example
*
* var cipherParams = CryptoJS . lib . CipherParams . create ( {
* ciphertext : ciphertextWordArray ,
* key : keyWordArray ,
* iv : ivWordArray ,
* salt : saltWordArray ,
* algorithm : CryptoJS . algo . AES ,
* mode : CryptoJS . mode . CBC ,
* padding : CryptoJS . pad . PKCS7 ,
* blockSize : 4 ,
* formatter : CryptoJS . format . OpenSSL
* } ) ;
* /
init : function ( cipherParams ) {
this . mixIn ( cipherParams ) ;
} ,
/ * *
* Converts this cipher params object to a string .
*
* @ param { Format } formatter ( Optional ) The formatting strategy to use .
*
* @ return { string } The stringified cipher params .
*
* @ throws Error If neither the formatter nor the default formatter is set .
*
* @ example
*
* var string = cipherParams + '' ;
* var string = cipherParams . toString ( ) ;
* var string = cipherParams . toString ( CryptoJS . format . OpenSSL ) ;
* /
toString : function ( formatter ) {
return ( formatter || this . formatter ) . stringify ( this ) ;
}
} ) ;
/ * *
* Format namespace .
* /
var C _format = C . format = { } ;
/ * *
* OpenSSL formatting strategy .
* /
var OpenSSLFormatter = C _format . OpenSSL = {
/ * *
* Converts a cipher params object to an OpenSSL - compatible string .
*
* @ param { CipherParams } cipherParams The cipher params object .
*
* @ return { string } The OpenSSL - compatible string .
*
* @ static
*
* @ example
*
* var openSSLString = CryptoJS . format . OpenSSL . stringify ( cipherParams ) ;
* /
stringify : function ( cipherParams ) {
// Shortcuts
var ciphertext = cipherParams . ciphertext ;
var salt = cipherParams . salt ;
// Format
if ( salt ) {
var wordArray = WordArray . create ( [ 0x53616c74 , 0x65645f5f ] ) . concat ( salt ) . concat ( ciphertext ) ;
} else {
var wordArray = ciphertext ;
}
return wordArray . toString ( Base64 ) ;
} ,
/ * *
* Converts an OpenSSL - compatible string to a cipher params object .
*
* @ param { string } openSSLStr The OpenSSL - compatible string .
*
* @ return { CipherParams } The cipher params object .
*
* @ static
*
* @ example
*
* var cipherParams = CryptoJS . format . OpenSSL . parse ( openSSLString ) ;
* /
parse : function ( openSSLStr ) {
// Parse base64
var ciphertext = Base64 . parse ( openSSLStr ) ;
// Shortcut
var ciphertextWords = ciphertext . words ;
// Test for salt
if ( ciphertextWords [ 0 ] == 0x53616c74 && ciphertextWords [ 1 ] == 0x65645f5f ) {
// Extract salt
var salt = WordArray . create ( ciphertextWords . slice ( 2 , 4 ) ) ;
// Remove salt from ciphertext
ciphertextWords . splice ( 0 , 4 ) ;
ciphertext . sigBytes -= 16 ;
}
return CipherParams . create ( { ciphertext : ciphertext , salt : salt } ) ;
}
} ;
/ * *
* A cipher wrapper that returns ciphertext as a serializable cipher params object .
* /
var SerializableCipher = C _lib . SerializableCipher = Base . extend ( {
/ * *
* Configuration options .
*
* @ property { Formatter } format The formatting strategy to convert cipher param objects to and from a string . Default : OpenSSL
* /
cfg : Base . extend ( {
format : OpenSSLFormatter
} ) ,
/ * *
* Encrypts a message .
*
* @ param { Cipher } cipher The cipher algorithm to use .
* @ param { WordArray | string } message The message to encrypt .
* @ param { WordArray } key The key .
* @ param { Object } cfg ( Optional ) The configuration options to use for this operation .
*
* @ return { CipherParams } A cipher params object .
*
* @ static
*
* @ example
*
* var ciphertextParams = CryptoJS . lib . SerializableCipher . encrypt ( CryptoJS . algo . AES , message , key ) ;
* var ciphertextParams = CryptoJS . lib . SerializableCipher . encrypt ( CryptoJS . algo . AES , message , key , { iv : iv } ) ;
* var ciphertextParams = CryptoJS . lib . SerializableCipher . encrypt ( CryptoJS . algo . AES , message , key , { iv : iv , format : CryptoJS . format . OpenSSL } ) ;
* /
encrypt : function ( cipher , message , key , cfg ) {
// Apply config defaults
cfg = this . cfg . extend ( cfg ) ;
// Encrypt
var encryptor = cipher . createEncryptor ( key , cfg ) ;
var ciphertext = encryptor . finalize ( message ) ;
// Shortcut
var cipherCfg = encryptor . cfg ;
// Create and return serializable cipher params
return CipherParams . create ( {
ciphertext : ciphertext ,
key : key ,
iv : cipherCfg . iv ,
algorithm : cipher ,
mode : cipherCfg . mode ,
padding : cipherCfg . padding ,
blockSize : cipher . blockSize ,
formatter : cfg . format
} ) ;
} ,
/ * *
* Decrypts serialized ciphertext .
*
* @ param { Cipher } cipher The cipher algorithm to use .
* @ param { CipherParams | string } ciphertext The ciphertext to decrypt .
* @ param { WordArray } key The key .
* @ param { Object } cfg ( Optional ) The configuration options to use for this operation .
*
* @ return { WordArray } The plaintext .
*
* @ static
*
* @ example
*
* var plaintext = CryptoJS . lib . SerializableCipher . decrypt ( CryptoJS . algo . AES , formattedCiphertext , key , { iv : iv , format : CryptoJS . format . OpenSSL } ) ;
* var plaintext = CryptoJS . lib . SerializableCipher . decrypt ( CryptoJS . algo . AES , ciphertextParams , key , { iv : iv , format : CryptoJS . format . OpenSSL } ) ;
* /
decrypt : function ( cipher , ciphertext , key , cfg ) {
// Apply config defaults
cfg = this . cfg . extend ( cfg ) ;
// Convert string to CipherParams
ciphertext = this . _parse ( ciphertext , cfg . format ) ;
// Decrypt
var plaintext = cipher . createDecryptor ( key , cfg ) . finalize ( ciphertext . ciphertext ) ;
return plaintext ;
} ,
/ * *
* Converts serialized ciphertext to CipherParams ,
* else assumed CipherParams already and returns ciphertext unchanged .
*
* @ param { CipherParams | string } ciphertext The ciphertext .
* @ param { Formatter } format The formatting strategy to use to parse serialized ciphertext .
*
* @ return { CipherParams } The unserialized ciphertext .
*
* @ static
*
* @ example
*
* var ciphertextParams = CryptoJS . lib . SerializableCipher . _parse ( ciphertextStringOrParams , format ) ;
* /
_parse : function ( ciphertext , format ) {
if ( typeof ciphertext == 'string' ) {
return format . parse ( ciphertext , this ) ;
} else {
return ciphertext ;
}
}
} ) ;
/ * *
* Key derivation function namespace .
* /
var C _kdf = C . kdf = { } ;
/ * *
* OpenSSL key derivation function .
* /
var OpenSSLKdf = C _kdf . OpenSSL = {
/ * *
* Derives a key and IV from a password .
*
* @ param { string } password The password to derive from .
* @ param { number } keySize The size in words of the key to generate .
* @ param { number } ivSize The size in words of the IV to generate .
* @ param { WordArray | string } salt ( Optional ) A 64 - bit salt to use . If omitted , a salt will be generated randomly .
*
* @ return { CipherParams } A cipher params object with the key , IV , and salt .
*
* @ static
*
* @ example
*
* var derivedParams = CryptoJS . kdf . OpenSSL . execute ( 'Password' , 256 / 32 , 128 / 32 ) ;
* var derivedParams = CryptoJS . kdf . OpenSSL . execute ( 'Password' , 256 / 32 , 128 / 32 , 'saltsalt' ) ;
* /
execute : function ( password , keySize , ivSize , salt ) {
// Generate random salt
if ( ! salt ) {
salt = WordArray . random ( 64 / 8 ) ;
}
// Derive key and IV
var key = EvpKDF . create ( { keySize : keySize + ivSize } ) . compute ( password , salt ) ;
// Separate key and IV
var iv = WordArray . create ( key . words . slice ( keySize ) , ivSize * 4 ) ;
key . sigBytes = keySize * 4 ;
// Return params
return CipherParams . create ( { key : key , iv : iv , salt : salt } ) ;
}
} ;
/ * *
* A serializable cipher wrapper that derives the key from a password ,
* and returns ciphertext as a serializable cipher params object .
* /
var PasswordBasedCipher = C _lib . PasswordBasedCipher = SerializableCipher . extend ( {
/ * *
* Configuration options .
*
* @ property { KDF } kdf The key derivation function to use to generate a key and IV from a password . Default : OpenSSL
* /
cfg : SerializableCipher . cfg . extend ( {
kdf : OpenSSLKdf
} ) ,
/ * *
* Encrypts a message using a password .
*
* @ param { Cipher } cipher The cipher algorithm to use .
* @ param { WordArray | string } message The message to encrypt .
* @ param { string } password The password .
* @ param { Object } cfg ( Optional ) The configuration options to use for this operation .
*
* @ return { CipherParams } A cipher params object .
*
* @ static
*
* @ example
*
* var ciphertextParams = CryptoJS . lib . PasswordBasedCipher . encrypt ( CryptoJS . algo . AES , message , 'password' ) ;
* var ciphertextParams = CryptoJS . lib . PasswordBasedCipher . encrypt ( CryptoJS . algo . AES , message , 'password' , { format : CryptoJS . format . OpenSSL } ) ;
* /
encrypt : function ( cipher , message , password , cfg ) {
// Apply config defaults
cfg = this . cfg . extend ( cfg ) ;
// Derive key and other params
var derivedParams = cfg . kdf . execute ( password , cipher . keySize , cipher . ivSize ) ;
// Add IV to config
cfg . iv = derivedParams . iv ;
// Encrypt
var ciphertext = SerializableCipher . encrypt . call ( this , cipher , message , derivedParams . key , cfg ) ;
// Mix in derived params
ciphertext . mixIn ( derivedParams ) ;
return ciphertext ;
} ,
/ * *
* Decrypts serialized ciphertext using a password .
*
* @ param { Cipher } cipher The cipher algorithm to use .
* @ param { CipherParams | string } ciphertext The ciphertext to decrypt .
* @ param { string } password The password .
* @ param { Object } cfg ( Optional ) The configuration options to use for this operation .
*
* @ return { WordArray } The plaintext .
*
* @ static
*
* @ example
*
* var plaintext = CryptoJS . lib . PasswordBasedCipher . decrypt ( CryptoJS . algo . AES , formattedCiphertext , 'password' , { format : CryptoJS . format . OpenSSL } ) ;
* var plaintext = CryptoJS . lib . PasswordBasedCipher . decrypt ( CryptoJS . algo . AES , ciphertextParams , 'password' , { format : CryptoJS . format . OpenSSL } ) ;
* /
decrypt : function ( cipher , ciphertext , password , cfg ) {
// Apply config defaults
cfg = this . cfg . extend ( cfg ) ;
// Convert string to CipherParams
ciphertext = this . _parse ( ciphertext , cfg . format ) ;
// Derive key and other params
var derivedParams = cfg . kdf . execute ( password , cipher . keySize , cipher . ivSize , ciphertext . salt ) ;
// Add IV to config
cfg . iv = derivedParams . iv ;
// Decrypt
var plaintext = SerializableCipher . decrypt . call ( this , cipher , ciphertext , derivedParams . key , cfg ) ;
return plaintext ;
}
} ) ;
} ( ) ) ;
( function ( ) {
// Shortcuts
var C = CryptoJS ;
var C _lib = C . lib ;
var BlockCipher = C _lib . BlockCipher ;
var C _algo = C . algo ;
// Lookup tables
var SBOX = [ ] ;
var INV _SBOX = [ ] ;
var SUB _MIX _0 = [ ] ;
var SUB _MIX _1 = [ ] ;
var SUB _MIX _2 = [ ] ;
var SUB _MIX _3 = [ ] ;
var INV _SUB _MIX _0 = [ ] ;
var INV _SUB _MIX _1 = [ ] ;
var INV _SUB _MIX _2 = [ ] ;
var INV _SUB _MIX _3 = [ ] ;
// Compute lookup tables
( function ( ) {
// Compute double table
var d = [ ] ;
for ( var i = 0 ; i < 256 ; i ++ ) {
if ( i < 128 ) {
d [ i ] = i << 1 ;
} else {
d [ i ] = ( i << 1 ) ^ 0x11b ;
}
}
// Walk GF(2^8)
var x = 0 ;
var xi = 0 ;
for ( var i = 0 ; i < 256 ; i ++ ) {
// Compute sbox
var sx = xi ^ ( xi << 1 ) ^ ( xi << 2 ) ^ ( xi << 3 ) ^ ( xi << 4 ) ;
sx = ( sx >>> 8 ) ^ ( sx & 0xff ) ^ 0x63 ;
SBOX [ x ] = sx ;
INV _SBOX [ sx ] = x ;
// Compute multiplication
var x2 = d [ x ] ;
var x4 = d [ x2 ] ;
var x8 = d [ x4 ] ;
// Compute sub bytes, mix columns tables
var t = ( d [ sx ] * 0x101 ) ^ ( sx * 0x1010100 ) ;
SUB _MIX _0 [ x ] = ( t << 24 ) | ( t >>> 8 ) ;
SUB _MIX _1 [ x ] = ( t << 16 ) | ( t >>> 16 ) ;
SUB _MIX _2 [ x ] = ( t << 8 ) | ( t >>> 24 ) ;
SUB _MIX _3 [ x ] = t ;
// Compute inv sub bytes, inv mix columns tables
var t = ( x8 * 0x1010101 ) ^ ( x4 * 0x10001 ) ^ ( x2 * 0x101 ) ^ ( x * 0x1010100 ) ;
INV _SUB _MIX _0 [ sx ] = ( t << 24 ) | ( t >>> 8 ) ;
INV _SUB _MIX _1 [ sx ] = ( t << 16 ) | ( t >>> 16 ) ;
INV _SUB _MIX _2 [ sx ] = ( t << 8 ) | ( t >>> 24 ) ;
INV _SUB _MIX _3 [ sx ] = t ;
// Compute next counter
if ( ! x ) {
x = xi = 1 ;
} else {
x = x2 ^ d [ d [ d [ x8 ^ x2 ] ] ] ;
xi ^= d [ d [ xi ] ] ;
}
}
} ( ) ) ;
// Precomputed Rcon lookup
var RCON = [ 0x00 , 0x01 , 0x02 , 0x04 , 0x08 , 0x10 , 0x20 , 0x40 , 0x80 , 0x1b , 0x36 ] ;
/ * *
* AES block cipher algorithm .
* /
var AES = C _algo . AES = BlockCipher . extend ( {
_doReset : function ( ) {
// Shortcuts
var key = this . _key ;
var keyWords = key . words ;
var keySize = key . sigBytes / 4 ;
// Compute number of rounds
var nRounds = this . _nRounds = keySize + 6
// Compute number of key schedule rows
var ksRows = ( nRounds + 1 ) * 4 ;
// Compute key schedule
var keySchedule = this . _keySchedule = [ ] ;
for ( var ksRow = 0 ; ksRow < ksRows ; ksRow ++ ) {
if ( ksRow < keySize ) {
keySchedule [ ksRow ] = keyWords [ ksRow ] ;
} else {
var t = keySchedule [ ksRow - 1 ] ;
if ( ! ( ksRow % keySize ) ) {
// Rot word
t = ( t << 8 ) | ( t >>> 24 ) ;
// Sub word
t = ( SBOX [ t >>> 24 ] << 24 ) | ( SBOX [ ( t >>> 16 ) & 0xff ] << 16 ) | ( SBOX [ ( t >>> 8 ) & 0xff ] << 8 ) | SBOX [ t & 0xff ] ;
// Mix Rcon
t ^= RCON [ ( ksRow / keySize ) | 0 ] << 24 ;
} else if ( keySize > 6 && ksRow % keySize == 4 ) {
// Sub word
t = ( SBOX [ t >>> 24 ] << 24 ) | ( SBOX [ ( t >>> 16 ) & 0xff ] << 16 ) | ( SBOX [ ( t >>> 8 ) & 0xff ] << 8 ) | SBOX [ t & 0xff ] ;
}
keySchedule [ ksRow ] = keySchedule [ ksRow - keySize ] ^ t ;
}
}
// Compute inv key schedule
var invKeySchedule = this . _invKeySchedule = [ ] ;
for ( var invKsRow = 0 ; invKsRow < ksRows ; invKsRow ++ ) {
var ksRow = ksRows - invKsRow ;
if ( invKsRow % 4 ) {
var t = keySchedule [ ksRow ] ;
} else {
var t = keySchedule [ ksRow - 4 ] ;
}
if ( invKsRow < 4 || ksRow <= 4 ) {
invKeySchedule [ invKsRow ] = t ;
} else {
invKeySchedule [ invKsRow ] = INV _SUB _MIX _0 [ SBOX [ t >>> 24 ] ] ^ INV _SUB _MIX _1 [ SBOX [ ( t >>> 16 ) & 0xff ] ] ^
INV _SUB _MIX _2 [ SBOX [ ( t >>> 8 ) & 0xff ] ] ^ INV _SUB _MIX _3 [ SBOX [ t & 0xff ] ] ;
}
}
} ,
encryptBlock : function ( M , offset ) {
this . _doCryptBlock ( M , offset , this . _keySchedule , SUB _MIX _0 , SUB _MIX _1 , SUB _MIX _2 , SUB _MIX _3 , SBOX ) ;
} ,
decryptBlock : function ( M , offset ) {
// Swap 2nd and 4th rows
var t = M [ offset + 1 ] ;
M [ offset + 1 ] = M [ offset + 3 ] ;
M [ offset + 3 ] = t ;
this . _doCryptBlock ( M , offset , this . _invKeySchedule , INV _SUB _MIX _0 , INV _SUB _MIX _1 , INV _SUB _MIX _2 , INV _SUB _MIX _3 , INV _SBOX ) ;
// Inv swap 2nd and 4th rows
var t = M [ offset + 1 ] ;
M [ offset + 1 ] = M [ offset + 3 ] ;
M [ offset + 3 ] = t ;
} ,
_doCryptBlock : function ( M , offset , keySchedule , SUB _MIX _0 , SUB _MIX _1 , SUB _MIX _2 , SUB _MIX _3 , SBOX ) {
// Shortcut
var nRounds = this . _nRounds ;
// Get input, add round key
var s0 = M [ offset ] ^ keySchedule [ 0 ] ;
var s1 = M [ offset + 1 ] ^ keySchedule [ 1 ] ;
var s2 = M [ offset + 2 ] ^ keySchedule [ 2 ] ;
var s3 = M [ offset + 3 ] ^ keySchedule [ 3 ] ;
// Key schedule row counter
var ksRow = 4 ;
// Rounds
for ( var round = 1 ; round < nRounds ; round ++ ) {
// Shift rows, sub bytes, mix columns, add round key
var t0 = SUB _MIX _0 [ s0 >>> 24 ] ^ SUB _MIX _1 [ ( s1 >>> 16 ) & 0xff ] ^ SUB _MIX _2 [ ( s2 >>> 8 ) & 0xff ] ^ SUB _MIX _3 [ s3 & 0xff ] ^ keySchedule [ ksRow ++ ] ;
var t1 = SUB _MIX _0 [ s1 >>> 24 ] ^ SUB _MIX _1 [ ( s2 >>> 16 ) & 0xff ] ^ SUB _MIX _2 [ ( s3 >>> 8 ) & 0xff ] ^ SUB _MIX _3 [ s0 & 0xff ] ^ keySchedule [ ksRow ++ ] ;
var t2 = SUB _MIX _0 [ s2 >>> 24 ] ^ SUB _MIX _1 [ ( s3 >>> 16 ) & 0xff ] ^ SUB _MIX _2 [ ( s0 >>> 8 ) & 0xff ] ^ SUB _MIX _3 [ s1 & 0xff ] ^ keySchedule [ ksRow ++ ] ;
var t3 = SUB _MIX _0 [ s3 >>> 24 ] ^ SUB _MIX _1 [ ( s0 >>> 16 ) & 0xff ] ^ SUB _MIX _2 [ ( s1 >>> 8 ) & 0xff ] ^ SUB _MIX _3 [ s2 & 0xff ] ^ keySchedule [ ksRow ++ ] ;
// Update state
s0 = t0 ;
s1 = t1 ;
s2 = t2 ;
s3 = t3 ;
}
// Shift rows, sub bytes, add round key
var t0 = ( ( SBOX [ s0 >>> 24 ] << 24 ) | ( SBOX [ ( s1 >>> 16 ) & 0xff ] << 16 ) | ( SBOX [ ( s2 >>> 8 ) & 0xff ] << 8 ) | SBOX [ s3 & 0xff ] ) ^ keySchedule [ ksRow ++ ] ;
var t1 = ( ( SBOX [ s1 >>> 24 ] << 24 ) | ( SBOX [ ( s2 >>> 16 ) & 0xff ] << 16 ) | ( SBOX [ ( s3 >>> 8 ) & 0xff ] << 8 ) | SBOX [ s0 & 0xff ] ) ^ keySchedule [ ksRow ++ ] ;
var t2 = ( ( SBOX [ s2 >>> 24 ] << 24 ) | ( SBOX [ ( s3 >>> 16 ) & 0xff ] << 16 ) | ( SBOX [ ( s0 >>> 8 ) & 0xff ] << 8 ) | SBOX [ s1 & 0xff ] ) ^ keySchedule [ ksRow ++ ] ;
var t3 = ( ( SBOX [ s3 >>> 24 ] << 24 ) | ( SBOX [ ( s0 >>> 16 ) & 0xff ] << 16 ) | ( SBOX [ ( s1 >>> 8 ) & 0xff ] << 8 ) | SBOX [ s2 & 0xff ] ) ^ keySchedule [ ksRow ++ ] ;
// Set output
M [ offset ] = t0 ;
M [ offset + 1 ] = t1 ;
M [ offset + 2 ] = t2 ;
M [ offset + 3 ] = t3 ;
} ,
keySize : 256 / 32
} ) ;
/ * *
* Shortcut functions to the cipher ' s object interface .
*
* @ example
*
* var ciphertext = CryptoJS . AES . encrypt ( message , key , cfg ) ;
* var plaintext = CryptoJS . AES . decrypt ( ciphertext , key , cfg ) ;
* /
C . AES = BlockCipher . _createHelper ( AES ) ;
} ( ) ) ;
2015-02-10 16:39:50 -08:00
/ *
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
; ( function ( ) {
'use strict' ;
// Test for webcrypto support, polyfill if needed.
if ( window . crypto . subtle === undefined || window . crypto . subtle === null ) {
window . crypto . subtle = ( function ( ) {
var StaticArrayBufferProto = new ArrayBuffer ( ) . _ _proto _ _ ;
function assertIsArrayBuffer ( thing ) {
if ( thing !== Object ( thing ) || thing . _ _proto _ _ != StaticArrayBufferProto )
throw new Error ( "Needed a ArrayBuffer" ) ;
}
// Synchronous implementation functions for polyfilling webcrypto
// All inputs/outputs are arraybuffers!
function HmacSHA256 ( key , input ) {
assertIsArrayBuffer ( key ) ;
assertIsArrayBuffer ( input ) ;
return CryptoJS . HmacSHA256 (
CryptoJS . enc . Latin1 . parse ( getString ( input ) ) ,
CryptoJS . enc . Latin1 . parse ( getString ( key ) )
) ;
} ;
function encryptAESCBC ( plaintext , key , iv ) {
assertIsArrayBuffer ( plaintext ) ;
assertIsArrayBuffer ( key ) ;
assertIsArrayBuffer ( iv ) ;
return CryptoJS . AES . encrypt (
CryptoJS . enc . Latin1 . parse ( getString ( plaintext ) ) ,
CryptoJS . enc . Latin1 . parse ( getString ( key ) ) ,
{ iv : CryptoJS . enc . Latin1 . parse ( getString ( iv ) ) }
) . ciphertext ;
} ;
function decryptAESCBC ( ciphertext , key , iv ) {
assertIsArrayBuffer ( ciphertext ) ;
assertIsArrayBuffer ( key ) ;
assertIsArrayBuffer ( iv ) ;
return CryptoJS . AES . decrypt (
btoa ( getString ( ciphertext ) ) ,
CryptoJS . enc . Latin1 . parse ( getString ( key ) ) ,
{ iv : CryptoJS . enc . Latin1 . parse ( getString ( iv ) ) }
) ;
} ;
// utility function for connecting front and back ends via promises
// Takes an implementation function and 0 or more arguments
function promise ( implementation ) {
var args = Array . prototype . slice . call ( arguments ) ;
args . shift ( ) ;
return new Promise ( function ( resolve ) {
var wordArray = implementation . apply ( this , args ) ;
// convert 32bit WordArray to array buffer
var buffer = new ArrayBuffer ( wordArray . sigBytes ) ;
var view = new DataView ( buffer ) ;
for ( var i = 0 ; i * 4 < buffer . byteLength ; i ++ ) {
view . setInt32 ( i * 4 , wordArray . words [ i ] ) ;
}
resolve ( buffer ) ;
} ) ;
} ;
return {
encrypt : function ( algorithm , key , data ) {
if ( algorithm . name === "AES-CBC" )
return promise ( encryptAESCBC , data , key , algorithm . iv . buffer || algorithm . iv ) ;
} ,
decrypt : function ( algorithm , key , data ) {
if ( algorithm . name === "AES-CBC" )
return promise ( decryptAESCBC , data , key , algorithm . iv . buffer || algorithm . iv ) ;
} ,
sign : function ( algorithm , key , data ) {
if ( algorithm . name === "HMAC" && algorithm . hash === "SHA-256" )
return promise ( HmacSHA256 , key , data ) ;
} ,
importKey : function ( format , key , algorithm , extractable , usages ) {
return new Promise ( function ( resolve , reject ) { resolve ( key ) ; } ) ;
}
} ;
} ) ( ) ;
} // if !window.crypto.subtle
} ) ( ) ;
} ) ( ) ;
/ *
Copyright 2013 Daniel Wirtz < dcode @ dcode . io >
Copyright 2009 The Closure Library Authors . 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 .
* /
/ * *
* @ license Long . js ( c ) 2013 Daniel Wirtz < dcode @ dcode . io >
* Released under the Apache License , Version 2.0
* see : https : //github.com/dcodeIO/Long.js for details
* /
( function ( global ) {
"use strict" ;
/ * *
* Constructs a 64 bit two ' s - complement integer , given its low and high 32 bit values as * signed * integers .
* See the from * functions below for more convenient ways of constructing Longs .
* @ exports Long
* @ class A Long class for representing a 64 bit two ' s - complement integer value .
* @ param { number } low The low ( signed ) 32 bits of the long
* @ param { number } high The high ( signed ) 32 bits of the long
* @ param { boolean = } unsigned Whether unsigned or not , defaults to ` false ` for signed
* @ constructor
* /
var Long = function ( low , high , unsigned ) {
/ * *
* The low 32 bits as a signed value .
* @ type { number }
* @ expose
* /
this . low = low | 0 ;
/ * *
* The high 32 bits as a signed value .
* @ type { number }
* @ expose
* /
this . high = high | 0 ;
/ * *
* Whether unsigned or not .
* @ type { boolean }
* @ expose
* /
this . unsigned = ! ! unsigned ;
} ;
// The internal representation of a long is the two given signed, 32-bit values.
// We use 32-bit pieces because these are the size of integers on which
// Javascript performs bit-operations. For operations like addition and
// multiplication, we split each number into 16 bit pieces, which can easily be
// multiplied within Javascript's floating-point representation without overflow
// or change in sign.
//
// In the algorithms below, we frequently reduce the negative case to the
// positive case by negating the input(s) and then post-processing the result.
// Note that we must ALWAYS check specially whether those values are MIN_VALUE
// (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
// a positive number, it overflows back into a negative). Not handling this
// case would often result in infinite recursion.
//
// Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
// methods on which they depend.
/ * *
* Tests if the specified object is a Long .
* @ param { * } obj Object
* @ returns { boolean }
* @ expose
* /
Long . isLong = function ( obj ) {
return ( obj && obj instanceof Long ) === true ;
} ;
/ * *
* A cache of the Long representations of small integer values .
* @ type { ! Object }
* @ inner
* /
var INT _CACHE = { } ;
/ * *
* A cache of the Long representations of small unsigned integer values .
* @ type { ! Object }
* @ inner
* /
var UINT _CACHE = { } ;
/ * *
* Returns a Long representing the given 32 bit integer value .
* @ param { number } value The 32 bit integer in question
* @ param { boolean = } unsigned Whether unsigned or not , defaults to ` false ` for signed
* @ returns { ! Long } The corresponding Long value
* @ expose
* /
Long . fromInt = function ( value , unsigned ) {
var obj , cachedObj ;
if ( ! unsigned ) {
value = value | 0 ;
if ( - 128 <= value && value < 128 ) {
cachedObj = INT _CACHE [ value ] ;
if ( cachedObj )
return cachedObj ;
}
obj = new Long ( value , value < 0 ? - 1 : 0 , false ) ;
if ( - 128 <= value && value < 128 )
INT _CACHE [ value ] = obj ;
return obj ;
} else {
value = value >>> 0 ;
if ( 0 <= value && value < 256 ) {
cachedObj = UINT _CACHE [ value ] ;
if ( cachedObj )
return cachedObj ;
}
obj = new Long ( value , ( value | 0 ) < 0 ? - 1 : 0 , true ) ;
if ( 0 <= value && value < 256 )
UINT _CACHE [ value ] = obj ;
return obj ;
}
} ;
/ * *
* Returns a Long representing the given value , provided that it is a finite number . Otherwise , zero is returned .
* @ param { number } value The number in question
* @ param { boolean = } unsigned Whether unsigned or not , defaults to ` false ` for signed
* @ returns { ! Long } The corresponding Long value
* @ expose
* /
Long . fromNumber = function ( value , unsigned ) {
unsigned = ! ! unsigned ;
if ( isNaN ( value ) || ! isFinite ( value ) )
return Long . ZERO ;
if ( ! unsigned && value <= - TWO _PWR _63 _DBL )
return Long . MIN _VALUE ;
if ( ! unsigned && value + 1 >= TWO _PWR _63 _DBL )
return Long . MAX _VALUE ;
if ( unsigned && value >= TWO _PWR _64 _DBL )
return Long . MAX _UNSIGNED _VALUE ;
if ( value < 0 )
return Long . fromNumber ( - value , unsigned ) . negate ( ) ;
return new Long ( ( value % TWO _PWR _32 _DBL ) | 0 , ( value / TWO _PWR _32 _DBL ) | 0 , unsigned ) ;
} ;
/ * *
* Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits . Each is
* assumed to use 32 bits .
* @ param { number } lowBits The low 32 bits
* @ param { number } highBits The high 32 bits
* @ param { boolean = } unsigned Whether unsigned or not , defaults to ` false ` for signed
* @ returns { ! Long } The corresponding Long value
* @ expose
* /
Long . fromBits = function ( lowBits , highBits , unsigned ) {
return new Long ( lowBits , highBits , unsigned ) ;
} ;
/ * *
* Returns a Long representation of the given string , written using the specified radix .
* @ param { string } str The textual representation of the Long
* @ param { ( boolean | number ) = } unsigned Whether unsigned or not , defaults to ` false ` for signed
* @ param { number = } radix The radix in which the text is written ( 2 - 36 ) , defaults to 10
* @ returns { ! Long } The corresponding Long value
* @ expose
* /
Long . fromString = function ( str , unsigned , radix ) {
if ( str . length === 0 )
throw Error ( 'number format error: empty string' ) ;
if ( str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity" )
return Long . ZERO ;
if ( typeof unsigned === 'number' ) // For goog.math.long compatibility
radix = unsigned ,
unsigned = false ;
radix = radix || 10 ;
if ( radix < 2 || 36 < radix )
throw Error ( 'radix out of range: ' + radix ) ;
var p ;
if ( ( p = str . indexOf ( '-' ) ) > 0 )
throw Error ( 'number format error: interior "-" character: ' + str ) ;
else if ( p === 0 )
return Long . fromString ( str . substring ( 1 ) , unsigned , radix ) . negate ( ) ;
// Do several (8) digits each time through the loop, so as to
// minimize the calls to the very expensive emulated div.
var radixToPower = Long . fromNumber ( Math . pow ( radix , 8 ) ) ;
var result = Long . ZERO ;
for ( var i = 0 ; i < str . length ; i += 8 ) {
var size = Math . min ( 8 , str . length - i ) ;
var value = parseInt ( str . substring ( i , i + size ) , radix ) ;
if ( size < 8 ) {
var power = Long . fromNumber ( Math . pow ( radix , size ) ) ;
result = result . multiply ( power ) . add ( Long . fromNumber ( value ) ) ;
} else {
result = result . multiply ( radixToPower ) ;
result = result . add ( Long . fromNumber ( value ) ) ;
}
}
result . unsigned = unsigned ;
return result ;
} ;
/ * *
* Converts the specified value to a Long .
* @ param { ! Long | number | string | ! { low : number , high : number , unsigned : boolean } } val Value
* @ returns { ! Long }
* @ expose
* /
Long . fromValue = function ( val ) {
if ( typeof val === 'number' )
return Long . fromNumber ( val ) ;
if ( typeof val === 'string' )
return Long . fromString ( val ) ;
if ( Long . isLong ( val ) )
return val ;
// Throws for not an object (undefined, null):
return new Long ( val . low , val . high , val . unsigned ) ;
} ;
// NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
// no runtime penalty for these.
/ * *
* @ type { number }
* @ const
* @ inner
* /
var TWO _PWR _16 _DBL = 1 << 16 ;
/ * *
* @ type { number }
* @ const
* @ inner
* /
var TWO _PWR _24 _DBL = 1 << 24 ;
/ * *
* @ type { number }
* @ const
* @ inner
* /
var TWO _PWR _32 _DBL = TWO _PWR _16 _DBL * TWO _PWR _16 _DBL ;
/ * *
* @ type { number }
* @ const
* @ inner
* /
var TWO _PWR _64 _DBL = TWO _PWR _32 _DBL * TWO _PWR _32 _DBL ;
/ * *
* @ type { number }
* @ const
* @ inner
* /
var TWO _PWR _63 _DBL = TWO _PWR _64 _DBL / 2 ;
/ * *
* @ type { ! Long }
* @ const
* @ inner
* /
var TWO _PWR _24 = Long . fromInt ( TWO _PWR _24 _DBL ) ;
/ * *
* Signed zero .
* @ type { ! Long }
* @ expose
* /
Long . ZERO = Long . fromInt ( 0 ) ;
/ * *
* Unsigned zero .
* @ type { ! Long }
* @ expose
* /
Long . UZERO = Long . fromInt ( 0 , true ) ;
/ * *
* Signed one .
* @ type { ! Long }
* @ expose
* /
Long . ONE = Long . fromInt ( 1 ) ;
/ * *
* Unsigned one .
* @ type { ! Long }
* @ expose
* /
Long . UONE = Long . fromInt ( 1 , true ) ;
/ * *
* Signed negative one .
* @ type { ! Long }
* @ expose
* /
Long . NEG _ONE = Long . fromInt ( - 1 ) ;
/ * *
* Maximum signed value .
* @ type { ! Long }
* @ expose
* /
Long . MAX _VALUE = Long . fromBits ( 0xFFFFFFFF | 0 , 0x7FFFFFFF | 0 , false ) ;
/ * *
* Maximum unsigned value .
* @ type { ! Long }
* @ expose
* /
Long . MAX _UNSIGNED _VALUE = Long . fromBits ( 0xFFFFFFFF | 0 , 0xFFFFFFFF | 0 , true ) ;
/ * *
* Minimum signed value .
* @ type { ! Long }
* @ expose
* /
Long . MIN _VALUE = Long . fromBits ( 0 , 0x80000000 | 0 , false ) ;
/ * *
* Converts the Long to a 32 bit integer , assuming it is a 32 bit integer .
* @ returns { number }
* @ expose
* /
Long . prototype . toInt = function ( ) {
return this . unsigned ? this . low >>> 0 : this . low ;
} ;
/ * *
* Converts the Long to a the nearest floating - point representation of this value ( double , 53 bit mantissa ) .
* @ returns { number }
* @ expose
* /
Long . prototype . toNumber = function ( ) {
if ( this . unsigned ) {
return ( ( this . high >>> 0 ) * TWO _PWR _32 _DBL ) + ( this . low >>> 0 ) ;
}
return this . high * TWO _PWR _32 _DBL + ( this . low >>> 0 ) ;
} ;
/ * *
* Converts the Long to a string written in the specified radix .
* @ param { number = } radix Radix ( 2 - 36 ) , defaults to 10
* @ returns { string }
* @ override
* @ throws { RangeError } If ` radix ` is out of range
* @ expose
* /
Long . prototype . toString = function ( radix ) {
radix = radix || 10 ;
if ( radix < 2 || 36 < radix )
throw RangeError ( 'radix out of range: ' + radix ) ;
if ( this . isZero ( ) )
return '0' ;
var rem ;
if ( this . isNegative ( ) ) { // Unsigned Longs are never negative
if ( this . equals ( Long . MIN _VALUE ) ) {
// We need to change the Long value before it can be negated, so we remove
// the bottom-most digit in this base and then recurse to do the rest.
var radixLong = Long . fromNumber ( radix ) ;
var div = this . div ( radixLong ) ;
rem = div . multiply ( radixLong ) . subtract ( this ) ;
return div . toString ( radix ) + rem . toInt ( ) . toString ( radix ) ;
} else
return '-' + this . negate ( ) . toString ( radix ) ;
}
// Do several (6) digits each time through the loop, so as to
// minimize the calls to the very expensive emulated div.
var radixToPower = Long . fromNumber ( Math . pow ( radix , 6 ) , this . unsigned ) ;
rem = this ;
var result = '' ;
while ( true ) {
var remDiv = rem . div ( radixToPower ) ,
intval = rem . subtract ( remDiv . multiply ( radixToPower ) ) . toInt ( ) >>> 0 ,
digits = intval . toString ( radix ) ;
rem = remDiv ;
if ( rem . isZero ( ) )
return digits + result ;
else {
while ( digits . length < 6 )
digits = '0' + digits ;
result = '' + digits + result ;
}
}
} ;
/ * *
* Gets the high 32 bits as a signed integer .
* @ returns { number } Signed high bits
* @ expose
* /
Long . prototype . getHighBits = function ( ) {
return this . high ;
} ;
/ * *
* Gets the high 32 bits as an unsigned integer .
* @ returns { number } Unsigned high bits
* @ expose
* /
Long . prototype . getHighBitsUnsigned = function ( ) {
return this . high >>> 0 ;
} ;
/ * *
* Gets the low 32 bits as a signed integer .
* @ returns { number } Signed low bits
* @ expose
* /
Long . prototype . getLowBits = function ( ) {
return this . low ;
} ;
/ * *
* Gets the low 32 bits as an unsigned integer .
* @ returns { number } Unsigned low bits
* @ expose
* /
Long . prototype . getLowBitsUnsigned = function ( ) {
return this . low >>> 0 ;
} ;
/ * *
* Gets the number of bits needed to represent the absolute value of this Long .
* @ returns { number }
* @ expose
* /
Long . prototype . getNumBitsAbs = function ( ) {
if ( this . isNegative ( ) ) // Unsigned Longs are never negative
return this . equals ( Long . MIN _VALUE ) ? 64 : this . negate ( ) . getNumBitsAbs ( ) ;
var val = this . high != 0 ? this . high : this . low ;
for ( var bit = 31 ; bit > 0 ; bit -- )
if ( ( val & ( 1 << bit ) ) != 0 )
break ;
return this . high != 0 ? bit + 33 : bit + 1 ;
} ;
/ * *
* Tests if this Long ' s value equals zero .
* @ returns { boolean }
* @ expose
* /
Long . prototype . isZero = function ( ) {
return this . high === 0 && this . low === 0 ;
} ;
/ * *
* Tests if this Long ' s value is negative .
* @ returns { boolean }
* @ expose
* /
Long . prototype . isNegative = function ( ) {
return ! this . unsigned && this . high < 0 ;
} ;
/ * *
* Tests if this Long ' s value is positive .
* @ returns { boolean }
* @ expose
* /
Long . prototype . isPositive = function ( ) {
return this . unsigned || this . high >= 0 ;
} ;
/ * *
* Tests if this Long ' s value is odd .
* @ returns { boolean }
* @ expose
* /
Long . prototype . isOdd = function ( ) {
return ( this . low & 1 ) === 1 ;
} ;
/ * *
* Tests if this Long ' s value is even .
* @ returns { boolean }
* @ expose
* /
Long . prototype . isEven = function ( ) {
return ( this . low & 1 ) === 0 ;
} ;
/ * *
* Tests if this Long 's value equals the specified' s .
* @ param { ! Long | number | string } other Other value
* @ returns { boolean }
* @ expose
* /
Long . prototype . equals = function ( other ) {
if ( ! Long . isLong ( other ) )
other = Long . fromValue ( other ) ;
if ( this . unsigned !== other . unsigned && ( this . high >>> 31 ) === 1 && ( other . high >>> 31 ) === 1 )
return false ;
return this . high === other . high && this . low === other . low ;
} ;
/ * *
* Tests if this Long 's value differs from the specified' s .
* @ param { ! Long | number | string } other Other value
* @ returns { boolean }
* @ expose
* /
Long . prototype . notEquals = function ( other ) {
if ( ! Long . isLong ( other ) )
other = Long . fromValue ( other ) ;
return ! this . equals ( other ) ;
} ;
/ * *
* Tests if this Long 's value is less than the specified' s .
* @ param { ! Long | number | string } other Other value
* @ returns { boolean }
* @ expose
* /
Long . prototype . lessThan = function ( other ) {
if ( ! Long . isLong ( other ) )
other = Long . fromValue ( other ) ;
return this . compare ( other ) < 0 ;
} ;
/ * *
* Tests if this Long 's value is less than or equal the specified' s .
* @ param { ! Long | number | string } other Other value
* @ returns { boolean }
* @ expose
* /
Long . prototype . lessThanOrEqual = function ( other ) {
if ( ! Long . isLong ( other ) )
other = Long . fromValue ( other ) ;
return this . compare ( other ) <= 0 ;
} ;
/ * *
* Tests if this Long 's value is greater than the specified' s .
* @ param { ! Long | number | string } other Other value
* @ returns { boolean }
* @ expose
* /
Long . prototype . greaterThan = function ( other ) {
if ( ! Long . isLong ( other ) )
other = Long . fromValue ( other ) ;
return this . compare ( other ) > 0 ;
} ;
/ * *
* Tests if this Long 's value is greater than or equal the specified' s .
* @ param { ! Long | number | string } other Other value
* @ returns { boolean }
* @ expose
* /
Long . prototype . greaterThanOrEqual = function ( other ) {
return this . compare ( other ) >= 0 ;
} ;
/ * *
* Compares this Long 's value with the specified' s .
* @ param { ! Long | number | string } other Other value
* @ returns { number } 0 if they are the same , 1 if the this is greater and - 1
* if the given one is greater
* @ expose
* /
Long . prototype . compare = function ( other ) {
if ( this . equals ( other ) )
return 0 ;
var thisNeg = this . isNegative ( ) ,
otherNeg = other . isNegative ( ) ;
if ( thisNeg && ! otherNeg )
return - 1 ;
if ( ! thisNeg && otherNeg )
return 1 ;
// At this point the sign bits are the same
if ( ! this . unsigned )
return this . subtract ( other ) . isNegative ( ) ? - 1 : 1 ;
// Both are positive if at least one is unsigned
return ( other . high >>> 0 ) > ( this . high >>> 0 ) || ( other . high === this . high && ( other . low >>> 0 ) > ( this . low >>> 0 ) ) ? - 1 : 1 ;
} ;
/ * *
* Negates this Long ' s value .
* @ returns { ! Long } Negated Long
* @ expose
* /
Long . prototype . negate = function ( ) {
if ( ! this . unsigned && this . equals ( Long . MIN _VALUE ) )
return Long . MIN _VALUE ;
return this . not ( ) . add ( Long . ONE ) ;
} ;
/ * *
* Returns the sum of this and the specified Long .
* @ param { ! Long | number | string } addend Addend
* @ returns { ! Long } Sum
* @ expose
* /
Long . prototype . add = function ( addend ) {
if ( ! Long . isLong ( addend ) )
addend = Long . fromValue ( addend ) ;
// Divide each number into 4 chunks of 16 bits, and then sum the chunks.
var a48 = this . high >>> 16 ;
var a32 = this . high & 0xFFFF ;
var a16 = this . low >>> 16 ;
var a00 = this . low & 0xFFFF ;
var b48 = addend . high >>> 16 ;
var b32 = addend . high & 0xFFFF ;
var b16 = addend . low >>> 16 ;
var b00 = addend . low & 0xFFFF ;
var c48 = 0 , c32 = 0 , c16 = 0 , c00 = 0 ;
c00 += a00 + b00 ;
c16 += c00 >>> 16 ;
c00 &= 0xFFFF ;
c16 += a16 + b16 ;
c32 += c16 >>> 16 ;
c16 &= 0xFFFF ;
c32 += a32 + b32 ;
c48 += c32 >>> 16 ;
c32 &= 0xFFFF ;
c48 += a48 + b48 ;
c48 &= 0xFFFF ;
return Long . fromBits ( ( c16 << 16 ) | c00 , ( c48 << 16 ) | c32 , this . unsigned ) ;
} ;
/ * *
* Returns the difference of this and the specified Long .
* @ param { ! Long | number | string } subtrahend Subtrahend
* @ returns { ! Long } Difference
* @ expose
* /
Long . prototype . subtract = function ( subtrahend ) {
if ( ! Long . isLong ( subtrahend ) )
subtrahend = Long . fromValue ( subtrahend ) ;
return this . add ( subtrahend . negate ( ) ) ;
} ;
/ * *
* Returns the product of this and the specified Long .
* @ param { ! Long | number | string } multiplier Multiplier
* @ returns { ! Long } Product
* @ expose
* /
Long . prototype . multiply = function ( multiplier ) {
if ( this . isZero ( ) )
return Long . ZERO ;
if ( ! Long . isLong ( multiplier ) )
multiplier = Long . fromValue ( multiplier ) ;
if ( multiplier . isZero ( ) )
return Long . ZERO ;
if ( this . equals ( Long . MIN _VALUE ) )
return multiplier . isOdd ( ) ? Long . MIN _VALUE : Long . ZERO ;
if ( multiplier . equals ( Long . MIN _VALUE ) )
return this . isOdd ( ) ? Long . MIN _VALUE : Long . ZERO ;
if ( this . isNegative ( ) ) {
if ( multiplier . isNegative ( ) )
return this . negate ( ) . multiply ( multiplier . negate ( ) ) ;
else
return this . negate ( ) . multiply ( multiplier ) . negate ( ) ;
} else if ( multiplier . isNegative ( ) )
return this . multiply ( multiplier . negate ( ) ) . negate ( ) ;
// If both longs are small, use float multiplication
if ( this . lessThan ( TWO _PWR _24 ) && multiplier . lessThan ( TWO _PWR _24 ) )
return Long . fromNumber ( this . toNumber ( ) * multiplier . toNumber ( ) , this . unsigned ) ;
// Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
// We can skip products that would overflow.
var a48 = this . high >>> 16 ;
var a32 = this . high & 0xFFFF ;
var a16 = this . low >>> 16 ;
var a00 = this . low & 0xFFFF ;
var b48 = multiplier . high >>> 16 ;
var b32 = multiplier . high & 0xFFFF ;
var b16 = multiplier . low >>> 16 ;
var b00 = multiplier . low & 0xFFFF ;
var c48 = 0 , c32 = 0 , c16 = 0 , c00 = 0 ;
c00 += a00 * b00 ;
c16 += c00 >>> 16 ;
c00 &= 0xFFFF ;
c16 += a16 * b00 ;
c32 += c16 >>> 16 ;
c16 &= 0xFFFF ;
c16 += a00 * b16 ;
c32 += c16 >>> 16 ;
c16 &= 0xFFFF ;
c32 += a32 * b00 ;
c48 += c32 >>> 16 ;
c32 &= 0xFFFF ;
c32 += a16 * b16 ;
c48 += c32 >>> 16 ;
c32 &= 0xFFFF ;
c32 += a00 * b32 ;
c48 += c32 >>> 16 ;
c32 &= 0xFFFF ;
c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48 ;
c48 &= 0xFFFF ;
return Long . fromBits ( ( c16 << 16 ) | c00 , ( c48 << 16 ) | c32 , this . unsigned ) ;
} ;
/ * *
* Returns this Long divided by the specified .
* @ param { ! Long | number | string } divisor Divisor
* @ returns { ! Long } Quotient
* @ expose
* /
Long . prototype . div = function ( divisor ) {
if ( ! Long . isLong ( divisor ) )
divisor = Long . fromValue ( divisor ) ;
if ( divisor . isZero ( ) )
throw ( new Error ( 'division by zero' ) ) ;
if ( this . isZero ( ) )
return this . unsigned ? Long . UZERO : Long . ZERO ;
var approx , rem , res ;
if ( this . equals ( Long . MIN _VALUE ) ) {
if ( divisor . equals ( Long . ONE ) || divisor . equals ( Long . NEG _ONE ) )
return Long . MIN _VALUE ; // recall that -MIN_VALUE == MIN_VALUE
else if ( divisor . equals ( Long . MIN _VALUE ) )
return Long . ONE ;
else {
// At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
var halfThis = this . shiftRight ( 1 ) ;
approx = halfThis . div ( divisor ) . shiftLeft ( 1 ) ;
if ( approx . equals ( Long . ZERO ) ) {
return divisor . isNegative ( ) ? Long . ONE : Long . NEG _ONE ;
} else {
rem = this . subtract ( divisor . multiply ( approx ) ) ;
res = approx . add ( rem . div ( divisor ) ) ;
return res ;
}
}
} else if ( divisor . equals ( Long . MIN _VALUE ) )
return this . unsigned ? Long . UZERO : Long . ZERO ;
if ( this . isNegative ( ) ) {
if ( divisor . isNegative ( ) )
return this . negate ( ) . div ( divisor . negate ( ) ) ;
return this . negate ( ) . div ( divisor ) . negate ( ) ;
} else if ( divisor . isNegative ( ) )
return this . div ( divisor . negate ( ) ) . negate ( ) ;
// Repeat the following until the remainder is less than other: find a
// floating-point that approximates remainder / other *from below*, add this
// into the result, and subtract it from the remainder. It is critical that
// the approximate value is less than or equal to the real value so that the
// remainder never becomes negative.
res = Long . ZERO ;
rem = this ;
while ( rem . greaterThanOrEqual ( divisor ) ) {
// Approximate the result of division. This may be a little greater or
// smaller than the actual value.
approx = Math . max ( 1 , Math . floor ( rem . toNumber ( ) / divisor . toNumber ( ) ) ) ;
// We will tweak the approximate result by changing it in the 48-th digit or
// the smallest non-fractional digit, whichever is larger.
var log2 = Math . ceil ( Math . log ( approx ) / Math . LN2 ) ,
delta = ( log2 <= 48 ) ? 1 : Math . pow ( 2 , log2 - 48 ) ,
// Decrease the approximation until it is smaller than the remainder. Note
// that if it is too large, the product overflows and is negative.
approxRes = Long . fromNumber ( approx ) ,
approxRem = approxRes . multiply ( divisor ) ;
while ( approxRem . isNegative ( ) || approxRem . greaterThan ( rem ) ) {
approx -= delta ;
approxRes = Long . fromNumber ( approx , this . unsigned ) ;
approxRem = approxRes . multiply ( divisor ) ;
}
// We know the answer can't be zero... and actually, zero would cause
// infinite recursion since we would make no progress.
if ( approxRes . isZero ( ) )
approxRes = Long . ONE ;
res = res . add ( approxRes ) ;
rem = rem . subtract ( approxRem ) ;
}
return res ;
} ;
/ * *
* Returns this Long modulo the specified .
* @ param { ! Long | number | string } divisor Divisor
* @ returns { ! Long } Remainder
* @ expose
* /
Long . prototype . modulo = function ( divisor ) {
if ( ! Long . isLong ( divisor ) )
divisor = Long . fromValue ( divisor ) ;
return this . subtract ( this . div ( divisor ) . multiply ( divisor ) ) ;
} ;
/ * *
* Returns the bitwise NOT of this Long .
* @ returns { ! Long }
* @ expose
* /
Long . prototype . not = function ( ) {
return Long . fromBits ( ~ this . low , ~ this . high , this . unsigned ) ;
} ;
/ * *
* Returns the bitwise AND of this Long and the specified .
* @ param { ! Long | number | string } other Other Long
* @ returns { ! Long }
* @ expose
* /
Long . prototype . and = function ( other ) {
if ( ! Long . isLong ( other ) )
other = Long . fromValue ( other ) ;
return Long . fromBits ( this . low & other . low , this . high & other . high , this . unsigned ) ;
} ;
/ * *
* Returns the bitwise OR of this Long and the specified .
* @ param { ! Long | number | string } other Other Long
* @ returns { ! Long }
* @ expose
* /
Long . prototype . or = function ( other ) {
if ( ! Long . isLong ( other ) )
other = Long . fromValue ( other ) ;
return Long . fromBits ( this . low | other . low , this . high | other . high , this . unsigned ) ;
} ;
/ * *
* Returns the bitwise XOR of this Long and the given one .
* @ param { ! Long | number | string } other Other Long
* @ returns { ! Long }
* @ expose
* /
Long . prototype . xor = function ( other ) {
if ( ! Long . isLong ( other ) )
other = Long . fromValue ( other ) ;
return Long . fromBits ( this . low ^ other . low , this . high ^ other . high , this . unsigned ) ;
} ;
/ * *
* Returns this Long with bits shifted to the left by the given amount .
* @ param { number | ! Long } numBits Number of bits
* @ returns { ! Long } Shifted Long
* @ expose
* /
Long . prototype . shiftLeft = function ( numBits ) {
if ( Long . isLong ( numBits ) )
numBits = numBits . toInt ( ) ;
if ( ( numBits &= 63 ) === 0 )
return this ;
else if ( numBits < 32 )
return Long . fromBits ( this . low << numBits , ( this . high << numBits ) | ( this . low >>> ( 32 - numBits ) ) , this . unsigned ) ;
else
return Long . fromBits ( 0 , this . low << ( numBits - 32 ) , this . unsigned ) ;
} ;
/ * *
* Returns this Long with bits arithmetically shifted to the right by the given amount .
* @ param { number | ! Long } numBits Number of bits
* @ returns { ! Long } Shifted Long
* @ expose
* /
Long . prototype . shiftRight = function ( numBits ) {
if ( Long . isLong ( numBits ) )
numBits = numBits . toInt ( ) ;
if ( ( numBits &= 63 ) === 0 )
return this ;
else if ( numBits < 32 )
return Long . fromBits ( ( this . low >>> numBits ) | ( this . high << ( 32 - numBits ) ) , this . high >> numBits , this . unsigned ) ;
else
return Long . fromBits ( this . high >> ( numBits - 32 ) , this . high >= 0 ? 0 : - 1 , this . unsigned ) ;
} ;
/ * *
* Returns this Long with bits logically shifted to the right by the given amount .
* @ param { number | ! Long } numBits Number of bits
* @ returns { ! Long } Shifted Long
* @ expose
* /
Long . prototype . shiftRightUnsigned = function ( numBits ) {
if ( Long . isLong ( numBits ) )
numBits = numBits . toInt ( ) ;
numBits &= 63 ;
if ( numBits === 0 )
return this ;
else {
var high = this . high ;
if ( numBits < 32 ) {
var low = this . low ;
return Long . fromBits ( ( low >>> numBits ) | ( high << ( 32 - numBits ) ) , high >>> numBits , this . unsigned ) ;
} else if ( numBits === 32 )
return Long . fromBits ( high , 0 , this . unsigned ) ;
else
return Long . fromBits ( high >>> ( numBits - 32 ) , 0 , this . unsigned ) ;
}
} ;
/ * *
* Converts this Long to signed .
* @ returns { ! Long } Signed long
* @ expose
* /
Long . prototype . toSigned = function ( ) {
if ( ! this . unsigned )
return this ;
return new Long ( this . low , this . high , false ) ;
} ;
/ * *
* Converts this Long to unsigned .
* @ returns { ! Long } Unsigned long
* @ expose
* /
Long . prototype . toUnsigned = function ( ) {
if ( this . unsigned )
return this ;
return new Long ( this . low , this . high , true ) ;
} ;
/* CommonJS */ if ( typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports )
module [ "exports" ] = Long ;
/* AMD */ else if ( typeof define === 'function' && define [ "amd" ] )
define ( function ( ) { return Long ; } ) ;
/* Global */ else
( global [ "dcodeIO" ] = global [ "dcodeIO" ] || { } ) [ "Long" ] = Long ;
} ) ( this ) ;
/ *
Copyright 2013 - 2014 Daniel Wirtz < dcode @ dcode . io >
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 .
* /
/ * *
* @ license ByteBuffer . js ( c ) 2013 - 2014 Daniel Wirtz < dcode @ dcode . io >
* This version of ByteBuffer . js uses an ArrayBuffer ( AB ) as its backing buffer and is compatible with modern browsers .
* Released under the Apache License , Version 2.0
* see : https : //github.com/dcodeIO/ByteBuffer.js for details
* / / /
( function ( global ) {
"use strict" ;
/ * *
* @ param { function ( new : Long , number , number , boolean = ) = } Long
* @ returns { function ( new : ByteBuffer , number = , boolean = , boolean = ) } }
* @ inner
* /
function loadByteBuffer ( Long ) {
/ * *
* Constructs a new ByteBuffer .
* @ class The swiss army knife for binary data in JavaScript .
* @ exports ByteBuffer
* @ constructor
* @ param { number = } capacity Initial capacity . Defaults to { @ link ByteBuffer . DEFAULT _CAPACITY } .
* @ param { boolean = } littleEndian Whether to use little or big endian byte order . Defaults to
* { @ link ByteBuffer . DEFAULT _ENDIAN } .
* @ param { boolean = } noAssert Whether to skip assertions of offsets and values . Defaults to
* { @ link ByteBuffer . DEFAULT _NOASSERT } .
* @ expose
* /
var ByteBuffer = function ( capacity , littleEndian , noAssert ) {
if ( typeof capacity === 'undefined' ) capacity = ByteBuffer . DEFAULT _CAPACITY ;
if ( typeof littleEndian === 'undefined' ) littleEndian = ByteBuffer . DEFAULT _ENDIAN ;
if ( typeof noAssert === 'undefined' ) noAssert = ByteBuffer . DEFAULT _NOASSERT ;
if ( ! noAssert ) {
capacity = capacity | 0 ;
if ( capacity < 0 )
throw RangeError ( "Illegal capacity" ) ;
littleEndian = ! ! littleEndian ;
noAssert = ! ! noAssert ;
}
/ * *
* Backing buffer .
* @ type { ! ArrayBuffer }
* @ expose
* /
this . buffer = capacity === 0 ? EMPTY _BUFFER : new ArrayBuffer ( capacity ) ;
/ * *
* Data view to manipulate the backing buffer . Becomes ` null ` if the backing buffer has a capacity of ` 0 ` .
* @ type { ? DataView }
* @ expose
* /
this . view = capacity === 0 ? null : new DataView ( this . buffer ) ;
/ * *
* Absolute read / write offset .
* @ type { number }
* @ expose
* @ see ByteBuffer # flip
* @ see ByteBuffer # clear
* /
this . offset = 0 ;
/ * *
* Marked offset .
* @ type { number }
* @ expose
* @ see ByteBuffer # mark
* @ see ByteBuffer # reset
* /
this . markedOffset = - 1 ;
/ * *
* Absolute limit of the contained data . Set to the backing buffer ' s capacity upon allocation .
* @ type { number }
* @ expose
* @ see ByteBuffer # flip
* @ see ByteBuffer # clear
* /
this . limit = capacity ;
/ * *
* Whether to use little endian byte order , defaults to ` false ` for big endian .
* @ type { boolean }
* @ expose
* /
this . littleEndian = typeof littleEndian !== 'undefined' ? ! ! littleEndian : false ;
/ * *
* Whether to skip assertions of offsets and values , defaults to ` false ` .
* @ type { boolean }
* @ expose
* /
this . noAssert = ! ! noAssert ;
} ;
/ * *
* ByteBuffer version .
* @ type { string }
* @ const
* @ expose
* /
ByteBuffer . VERSION = "3.5.4" ;
/ * *
* Little endian constant that can be used instead of its boolean value . Evaluates to ` true ` .
* @ type { boolean }
* @ const
* @ expose
* /
ByteBuffer . LITTLE _ENDIAN = true ;
/ * *
* Big endian constant that can be used instead of its boolean value . Evaluates to ` false ` .
* @ type { boolean }
* @ const
* @ expose
* /
ByteBuffer . BIG _ENDIAN = false ;
/ * *
* Default initial capacity of ` 16 ` .
* @ type { number }
* @ expose
* /
ByteBuffer . DEFAULT _CAPACITY = 16 ;
/ * *
* Default endianess of ` false ` for big endian .
* @ type { boolean }
* @ expose
* /
ByteBuffer . DEFAULT _ENDIAN = ByteBuffer . BIG _ENDIAN ;
/ * *
* Default no assertions flag of ` false ` .
* @ type { boolean }
* @ expose
* /
ByteBuffer . DEFAULT _NOASSERT = false ;
/ * *
* A ` Long ` class for representing a 64 - bit two ' s - complement integer value . May be ` null ` if Long . js has not been loaded
* and int64 support is not available .
* @ type { ? Long }
* @ const
* @ see https : //github.com/dcodeIO/Long.js
* @ expose
* /
ByteBuffer . Long = Long || null ;
/ * *
* @ alias ByteBuffer . prototype
* @ inner
* /
var ByteBufferPrototype = ByteBuffer . prototype ;
// helpers
/ * *
* @ type { ! ArrayBuffer }
* @ inner
* /
var EMPTY _BUFFER = new ArrayBuffer ( 0 ) ;
/ * *
* String . fromCharCode reference for compile - time renaming .
* @ type { function ( ... number ) : string }
* @ inner
* /
var stringFromCharCode = String . fromCharCode ;
/ * *
* Creates a source function for a string .
* @ param { string } s String to read from
* @ returns { function ( ) : number | null } Source function returning the next char code respectively ` null ` if there are
* no more characters left .
* @ throws { TypeError } If the argument is invalid
* @ inner
* /
function stringSource ( s ) {
var i = 0 ; return function ( ) {
return i < s . length ? s . charCodeAt ( i ++ ) : null ;
} ;
}
/ * *
* Creates a destination function for a string .
* @ returns { function ( number = ) : undefined | string } Destination function successively called with the next char code .
* Returns the final string when called without arguments .
* @ inner
* /
function stringDestination ( ) {
var cs = [ ] , ps = [ ] ; return function ( ) {
if ( arguments . length === 0 )
return ps . join ( '' ) + stringFromCharCode . apply ( String , cs ) ;
if ( cs . length + arguments . length > 1024 )
ps . push ( stringFromCharCode . apply ( String , cs ) ) ,
cs . length = 0 ;
Array . prototype . push . apply ( cs , arguments ) ;
} ;
}
/ * *
* Allocates a new ByteBuffer backed by a buffer of the specified capacity .
* @ param { number = } capacity Initial capacity . Defaults to { @ link ByteBuffer . DEFAULT _CAPACITY } .
* @ param { boolean = } littleEndian Whether to use little or big endian byte order . Defaults to
* { @ link ByteBuffer . DEFAULT _ENDIAN } .
* @ param { boolean = } noAssert Whether to skip assertions of offsets and values . Defaults to
* { @ link ByteBuffer . DEFAULT _NOASSERT } .
* @ returns { ! ByteBuffer }
* @ expose
* /
ByteBuffer . allocate = function ( capacity , littleEndian , noAssert ) {
return new ByteBuffer ( capacity , littleEndian , noAssert ) ;
} ;
/ * *
* Concatenates multiple ByteBuffers into one .
* @ param { ! Array . < ! ByteBuffer | ! ArrayBuffer | ! Uint8Array | string > } buffers Buffers to concatenate
* @ param { ( string | boolean ) = } encoding String encoding if ` buffers ` contains a string ( "base64" , "hex" , "binary" ,
* defaults to "utf8" )
* @ param { boolean = } littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer . Defaults
* to { @ link ByteBuffer . DEFAULT _ENDIAN } .
* @ param { boolean = } noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer . Defaults to
* { @ link ByteBuffer . DEFAULT _NOASSERT } .
* @ returns { ! ByteBuffer } Concatenated ByteBuffer
* @ expose
* /
ByteBuffer . concat = function ( buffers , encoding , littleEndian , noAssert ) {
if ( typeof encoding === 'boolean' || typeof encoding !== 'string' ) {
noAssert = littleEndian ;
littleEndian = encoding ;
encoding = undefined ;
}
var capacity = 0 ;
for ( var i = 0 , k = buffers . length , length ; i < k ; ++ i ) {
if ( ! ByteBuffer . isByteBuffer ( buffers [ i ] ) )
buffers [ i ] = ByteBuffer . wrap ( buffers [ i ] , encoding ) ;
length = buffers [ i ] . limit - buffers [ i ] . offset ;
if ( length > 0 ) capacity += length ;
}
if ( capacity === 0 )
return new ByteBuffer ( 0 , littleEndian , noAssert ) ;
var bb = new ByteBuffer ( capacity , littleEndian , noAssert ) ,
bi ;
var view = new Uint8Array ( bb . buffer ) ;
i = 0 ; while ( i < k ) {
bi = buffers [ i ++ ] ;
length = bi . limit - bi . offset ;
if ( length <= 0 ) continue ;
view . set ( new Uint8Array ( bi . buffer ) . subarray ( bi . offset , bi . limit ) , bb . offset ) ;
bb . offset += length ;
}
bb . limit = bb . offset ;
bb . offset = 0 ;
return bb ;
} ;
/ * *
* Tests if the specified type is a ByteBuffer .
* @ param { * } bb ByteBuffer to test
* @ returns { boolean } ` true ` if it is a ByteBuffer , otherwise ` false `
* @ expose
* /
ByteBuffer . isByteBuffer = function ( bb ) {
return ( bb && bb instanceof ByteBuffer ) === true ;
} ;
/ * *
* Gets the backing buffer type .
* @ returns { Function } ` Buffer ` for NB builds , ` ArrayBuffer ` for AB builds ( classes )
* @ expose
* /
ByteBuffer . type = function ( ) {
return ArrayBuffer ;
} ;
/ * *
* Wraps a buffer or a string . Sets the allocated ByteBuffer ' s { @ link ByteBuffer # offset } to ` 0 ` and its
* { @ link ByteBuffer # limit } to the length of the wrapped data .
* @ param { ! ByteBuffer | ! ArrayBuffer | ! Uint8Array | string | ! Array . < number > } buffer Anything that can be wrapped
* @ param { ( string | boolean ) = } encoding String encoding if ` buffer ` is a string ( "base64" , "hex" , "binary" , defaults to
* "utf8" )
* @ param { boolean = } littleEndian Whether to use little or big endian byte order . Defaults to
* { @ link ByteBuffer . DEFAULT _ENDIAN } .
* @ param { boolean = } noAssert Whether to skip assertions of offsets and values . Defaults to
* { @ link ByteBuffer . DEFAULT _NOASSERT } .
* @ returns { ! ByteBuffer } A ByteBuffer wrapping ` buffer `
* @ expose
* /
ByteBuffer . wrap = function ( buffer , encoding , littleEndian , noAssert ) {
if ( typeof encoding !== 'string' ) {
noAssert = littleEndian ;
littleEndian = encoding ;
encoding = undefined ;
}
if ( typeof buffer === 'string' ) {
if ( typeof encoding === 'undefined' )
encoding = "utf8" ;
switch ( encoding ) {
case "base64" :
return ByteBuffer . fromBase64 ( buffer , littleEndian ) ;
case "hex" :
return ByteBuffer . fromHex ( buffer , littleEndian ) ;
case "binary" :
return ByteBuffer . fromBinary ( buffer , littleEndian ) ;
case "utf8" :
return ByteBuffer . fromUTF8 ( buffer , littleEndian ) ;
case "debug" :
return ByteBuffer . fromDebug ( buffer , littleEndian ) ;
default :
throw Error ( "Unsupported encoding: " + encoding ) ;
}
}
if ( buffer === null || typeof buffer !== 'object' )
throw TypeError ( "Illegal buffer" ) ;
var bb ;
if ( ByteBuffer . isByteBuffer ( buffer ) ) {
bb = ByteBufferPrototype . clone . call ( buffer ) ;
bb . markedOffset = - 1 ;
return bb ;
}
if ( buffer instanceof Uint8Array ) { // Extract ArrayBuffer from Uint8Array
bb = new ByteBuffer ( 0 , littleEndian , noAssert ) ;
if ( buffer . length > 0 ) { // Avoid references to more than one EMPTY_BUFFER
bb . buffer = buffer . buffer ;
bb . offset = buffer . byteOffset ;
bb . limit = buffer . byteOffset + buffer . length ;
bb . view = buffer . length > 0 ? new DataView ( buffer . buffer ) : null ;
}
} else if ( buffer instanceof ArrayBuffer ) { // Reuse ArrayBuffer
bb = new ByteBuffer ( 0 , littleEndian , noAssert ) ;
if ( buffer . byteLength > 0 ) {
bb . buffer = buffer ;
bb . offset = 0 ;
bb . limit = buffer . byteLength ;
bb . view = buffer . byteLength > 0 ? new DataView ( buffer ) : null ;
}
} else if ( Object . prototype . toString . call ( buffer ) === "[object Array]" ) { // Create from octets
bb = new ByteBuffer ( buffer . length , littleEndian , noAssert ) ;
bb . limit = buffer . length ;
for ( i = 0 ; i < buffer . length ; ++ i )
bb . view . setUint8 ( i , buffer [ i ] ) ;
} else
throw TypeError ( "Illegal buffer" ) ; // Otherwise fail
return bb ;
} ;
// types/ints/int8
/ * *
* Writes an 8 bit signed integer .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and advance { @ link ByteBuffer # offset } by ` 1 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeInt8 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' || value % 1 !== 0 )
throw TypeError ( "Illegal value: " + value + " (not an integer)" ) ;
value |= 0 ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
offset += 1 ;
var capacity0 = this . buffer . byteLength ;
if ( offset > capacity0 )
this . resize ( ( capacity0 *= 2 ) > offset ? capacity0 : offset ) ;
offset -= 1 ;
this . view . setInt8 ( offset , value ) ;
if ( relative ) this . offset += 1 ;
return this ;
} ;
/ * *
* Writes an 8 bit signed integer . This is an alias of { @ link ByteBuffer # writeInt8 } .
* @ function
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and advance { @ link ByteBuffer # offset } by ` 1 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeByte = ByteBufferPrototype . writeInt8 ;
/ * *
* Reads an 8 bit signed integer .
* @ param { number = } offset Offset to read from . Will use and advance { @ link ByteBuffer # offset } by ` 1 ` if omitted .
* @ returns { number } Value read
* @ expose
* /
ByteBufferPrototype . readInt8 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 1 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 1 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . view . getInt8 ( offset ) ;
if ( relative ) this . offset += 1 ;
return value ;
} ;
/ * *
* Reads an 8 bit signed integer . This is an alias of { @ link ByteBuffer # readInt8 } .
* @ function
* @ param { number = } offset Offset to read from . Will use and advance { @ link ByteBuffer # offset } by ` 1 ` if omitted .
* @ returns { number } Value read
* @ expose
* /
ByteBufferPrototype . readByte = ByteBufferPrototype . readInt8 ;
/ * *
* Writes an 8 bit unsigned integer .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and advance { @ link ByteBuffer # offset } by ` 1 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeUint8 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' || value % 1 !== 0 )
throw TypeError ( "Illegal value: " + value + " (not an integer)" ) ;
value >>>= 0 ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
offset += 1 ;
var capacity1 = this . buffer . byteLength ;
if ( offset > capacity1 )
this . resize ( ( capacity1 *= 2 ) > offset ? capacity1 : offset ) ;
offset -= 1 ;
this . view . setUint8 ( offset , value ) ;
if ( relative ) this . offset += 1 ;
return this ;
} ;
/ * *
* Reads an 8 bit unsigned integer .
* @ param { number = } offset Offset to read from . Will use and advance { @ link ByteBuffer # offset } by ` 1 ` if omitted .
* @ returns { number } Value read
* @ expose
* /
ByteBufferPrototype . readUint8 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 1 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 1 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . view . getUint8 ( offset ) ;
if ( relative ) this . offset += 1 ;
return value ;
} ;
// types/ints/int16
/ * *
* Writes a 16 bit signed integer .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and advance { @ link ByteBuffer # offset } by ` 2 ` if omitted .
* @ throws { TypeError } If ` offset ` or ` value ` is not a valid number
* @ throws { RangeError } If ` offset ` is out of bounds
* @ expose
* /
ByteBufferPrototype . writeInt16 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' || value % 1 !== 0 )
throw TypeError ( "Illegal value: " + value + " (not an integer)" ) ;
value |= 0 ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
offset += 2 ;
var capacity2 = this . buffer . byteLength ;
if ( offset > capacity2 )
this . resize ( ( capacity2 *= 2 ) > offset ? capacity2 : offset ) ;
offset -= 2 ;
this . view . setInt16 ( offset , value , this . littleEndian ) ;
if ( relative ) this . offset += 2 ;
return this ;
} ;
/ * *
* Writes a 16 bit signed integer . This is an alias of { @ link ByteBuffer # writeInt16 } .
* @ function
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and advance { @ link ByteBuffer # offset } by ` 2 ` if omitted .
* @ throws { TypeError } If ` offset ` or ` value ` is not a valid number
* @ throws { RangeError } If ` offset ` is out of bounds
* @ expose
* /
ByteBufferPrototype . writeShort = ByteBufferPrototype . writeInt16 ;
/ * *
* Reads a 16 bit signed integer .
* @ param { number = } offset Offset to read from . Will use and advance { @ link ByteBuffer # offset } by ` 2 ` if omitted .
* @ returns { number } Value read
* @ throws { TypeError } If ` offset ` is not a valid number
* @ throws { RangeError } If ` offset ` is out of bounds
* @ expose
* /
ByteBufferPrototype . readInt16 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 2 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 2 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . view . getInt16 ( offset , this . littleEndian ) ;
if ( relative ) this . offset += 2 ;
return value ;
} ;
/ * *
* Reads a 16 bit signed integer . This is an alias of { @ link ByteBuffer # readInt16 } .
* @ function
* @ param { number = } offset Offset to read from . Will use and advance { @ link ByteBuffer # offset } by ` 2 ` if omitted .
* @ returns { number } Value read
* @ throws { TypeError } If ` offset ` is not a valid number
* @ throws { RangeError } If ` offset ` is out of bounds
* @ expose
* /
ByteBufferPrototype . readShort = ByteBufferPrototype . readInt16 ;
/ * *
* Writes a 16 bit unsigned integer .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and advance { @ link ByteBuffer # offset } by ` 2 ` if omitted .
* @ throws { TypeError } If ` offset ` or ` value ` is not a valid number
* @ throws { RangeError } If ` offset ` is out of bounds
* @ expose
* /
ByteBufferPrototype . writeUint16 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' || value % 1 !== 0 )
throw TypeError ( "Illegal value: " + value + " (not an integer)" ) ;
value >>>= 0 ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
offset += 2 ;
var capacity3 = this . buffer . byteLength ;
if ( offset > capacity3 )
this . resize ( ( capacity3 *= 2 ) > offset ? capacity3 : offset ) ;
offset -= 2 ;
this . view . setUint16 ( offset , value , this . littleEndian ) ;
if ( relative ) this . offset += 2 ;
return this ;
} ;
/ * *
* Reads a 16 bit unsigned integer .
* @ param { number = } offset Offset to read from . Will use and advance { @ link ByteBuffer # offset } by ` 2 ` if omitted .
* @ returns { number } Value read
* @ throws { TypeError } If ` offset ` is not a valid number
* @ throws { RangeError } If ` offset ` is out of bounds
* @ expose
* /
ByteBufferPrototype . readUint16 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 2 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 2 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . view . getUint16 ( offset , this . littleEndian ) ;
if ( relative ) this . offset += 2 ;
return value ;
} ;
// types/ints/int32
/ * *
* Writes a 32 bit signed integer .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ expose
* /
ByteBufferPrototype . writeInt32 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' || value % 1 !== 0 )
throw TypeError ( "Illegal value: " + value + " (not an integer)" ) ;
value |= 0 ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
offset += 4 ;
var capacity4 = this . buffer . byteLength ;
if ( offset > capacity4 )
this . resize ( ( capacity4 *= 2 ) > offset ? capacity4 : offset ) ;
offset -= 4 ;
this . view . setInt32 ( offset , value , this . littleEndian ) ;
if ( relative ) this . offset += 4 ;
return this ;
} ;
/ * *
* Writes a 32 bit signed integer . This is an alias of { @ link ByteBuffer # writeInt32 } .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ expose
* /
ByteBufferPrototype . writeInt = ByteBufferPrototype . writeInt32 ;
/ * *
* Reads a 32 bit signed integer .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ returns { number } Value read
* @ expose
* /
ByteBufferPrototype . readInt32 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 4 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 4 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . view . getInt32 ( offset , this . littleEndian ) ;
if ( relative ) this . offset += 4 ;
return value ;
} ;
/ * *
* Reads a 32 bit signed integer . This is an alias of { @ link ByteBuffer # readInt32 } .
* @ param { number = } offset Offset to read from . Will use and advance { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ returns { number } Value read
* @ expose
* /
ByteBufferPrototype . readInt = ByteBufferPrototype . readInt32 ;
/ * *
* Writes a 32 bit unsigned integer .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ expose
* /
ByteBufferPrototype . writeUint32 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' || value % 1 !== 0 )
throw TypeError ( "Illegal value: " + value + " (not an integer)" ) ;
value >>>= 0 ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
offset += 4 ;
var capacity5 = this . buffer . byteLength ;
if ( offset > capacity5 )
this . resize ( ( capacity5 *= 2 ) > offset ? capacity5 : offset ) ;
offset -= 4 ;
this . view . setUint32 ( offset , value , this . littleEndian ) ;
if ( relative ) this . offset += 4 ;
return this ;
} ;
/ * *
* Reads a 32 bit unsigned integer .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ returns { number } Value read
* @ expose
* /
ByteBufferPrototype . readUint32 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 4 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 4 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . view . getUint32 ( offset , this . littleEndian ) ;
if ( relative ) this . offset += 4 ;
return value ;
} ;
// types/ints/int64
if ( Long ) {
/ * *
* Writes a 64 bit signed integer .
* @ param { number | ! Long } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeInt64 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value === 'number' )
value = Long . fromNumber ( value ) ;
else if ( ! ( value && value instanceof Long ) )
throw TypeError ( "Illegal value: " + value + " (not an integer or Long)" ) ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
if ( typeof value === 'number' )
value = Long . fromNumber ( value ) ;
offset += 8 ;
var capacity6 = this . buffer . byteLength ;
if ( offset > capacity6 )
this . resize ( ( capacity6 *= 2 ) > offset ? capacity6 : offset ) ;
offset -= 8 ;
if ( this . littleEndian ) {
this . view . setInt32 ( offset , value . low , true ) ;
this . view . setInt32 ( offset + 4 , value . high , true ) ;
} else {
this . view . setInt32 ( offset , value . high , false ) ;
this . view . setInt32 ( offset + 4 , value . low , false ) ;
}
if ( relative ) this . offset += 8 ;
return this ;
} ;
/ * *
* Writes a 64 bit signed integer . This is an alias of { @ link ByteBuffer # writeInt64 } .
* @ param { number | ! Long } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeLong = ByteBufferPrototype . writeInt64 ;
/ * *
* Reads a 64 bit signed integer .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { ! Long }
* @ expose
* /
ByteBufferPrototype . readInt64 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 8 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 8 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . littleEndian
? new Long ( this . view . getInt32 ( offset , true ) , this . view . getInt32 ( offset + 4 , true ) , false )
: new Long ( this . view . getInt32 ( offset + 4 , false ) , this . view . getInt32 ( offset , false ) , false ) ;
if ( relative ) this . offset += 8 ;
return value ;
} ;
/ * *
* Reads a 64 bit signed integer . This is an alias of { @ link ByteBuffer # readInt64 } .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { ! Long }
* @ expose
* /
ByteBufferPrototype . readLong = ByteBufferPrototype . readInt64 ;
/ * *
* Writes a 64 bit unsigned integer .
* @ param { number | ! Long } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeUint64 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value === 'number' )
value = Long . fromNumber ( value ) ;
else if ( ! ( value && value instanceof Long ) )
throw TypeError ( "Illegal value: " + value + " (not an integer or Long)" ) ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
if ( typeof value === 'number' )
value = Long . fromNumber ( value ) ;
offset += 8 ;
var capacity7 = this . buffer . byteLength ;
if ( offset > capacity7 )
this . resize ( ( capacity7 *= 2 ) > offset ? capacity7 : offset ) ;
offset -= 8 ;
if ( this . littleEndian ) {
this . view . setInt32 ( offset , value . low , true ) ;
this . view . setInt32 ( offset + 4 , value . high , true ) ;
} else {
this . view . setInt32 ( offset , value . high , false ) ;
this . view . setInt32 ( offset + 4 , value . low , false ) ;
}
if ( relative ) this . offset += 8 ;
return this ;
} ;
/ * *
* Reads a 64 bit unsigned integer .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { ! Long }
* @ expose
* /
ByteBufferPrototype . readUint64 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 8 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 8 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . littleEndian
? new Long ( this . view . getInt32 ( offset , true ) , this . view . getInt32 ( offset + 4 , true ) , true )
: new Long ( this . view . getInt32 ( offset + 4 , false ) , this . view . getInt32 ( offset , false ) , true ) ;
if ( relative ) this . offset += 8 ;
return value ;
} ;
} // Long
// types/floats/float32
/ * *
* Writes a 32 bit float .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeFloat32 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' )
throw TypeError ( "Illegal value: " + value + " (not a number)" ) ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
offset += 4 ;
var capacity8 = this . buffer . byteLength ;
if ( offset > capacity8 )
this . resize ( ( capacity8 *= 2 ) > offset ? capacity8 : offset ) ;
offset -= 4 ;
this . view . setFloat32 ( offset , value , this . littleEndian ) ;
if ( relative ) this . offset += 4 ;
return this ;
} ;
/ * *
* Writes a 32 bit float . This is an alias of { @ link ByteBuffer # writeFloat32 } .
* @ function
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeFloat = ByteBufferPrototype . writeFloat32 ;
/ * *
* Reads a 32 bit float .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ returns { number }
* @ expose
* /
ByteBufferPrototype . readFloat32 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 4 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 4 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . view . getFloat32 ( offset , this . littleEndian ) ;
if ( relative ) this . offset += 4 ;
return value ;
} ;
/ * *
* Reads a 32 bit float . This is an alias of { @ link ByteBuffer # readFloat32 } .
* @ function
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by ` 4 ` if omitted .
* @ returns { number }
* @ expose
* /
ByteBufferPrototype . readFloat = ByteBufferPrototype . readFloat32 ;
// types/floats/float64
/ * *
* Writes a 64 bit float .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeFloat64 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' )
throw TypeError ( "Illegal value: " + value + " (not a number)" ) ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
offset += 8 ;
var capacity9 = this . buffer . byteLength ;
if ( offset > capacity9 )
this . resize ( ( capacity9 *= 2 ) > offset ? capacity9 : offset ) ;
offset -= 8 ;
this . view . setFloat64 ( offset , value , this . littleEndian ) ;
if ( relative ) this . offset += 8 ;
return this ;
} ;
/ * *
* Writes a 64 bit float . This is an alias of { @ link ByteBuffer # writeFloat64 } .
* @ function
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . writeDouble = ByteBufferPrototype . writeFloat64 ;
/ * *
* Reads a 64 bit float .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { number }
* @ expose
* /
ByteBufferPrototype . readFloat64 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 8 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 8 + ") <= " + this . buffer . byteLength ) ;
}
var value = this . view . getFloat64 ( offset , this . littleEndian ) ;
if ( relative ) this . offset += 8 ;
return value ;
} ;
/ * *
* Reads a 64 bit float . This is an alias of { @ link ByteBuffer # readFloat64 } .
* @ function
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by ` 8 ` if omitted .
* @ returns { number }
* @ expose
* /
ByteBufferPrototype . readDouble = ByteBufferPrototype . readFloat64 ;
// types/varints/varint32
/ * *
* Maximum number of bytes required to store a 32 bit base 128 variable - length integer .
* @ type { number }
* @ const
* @ expose
* /
ByteBuffer . MAX _VARINT32 _BYTES = 5 ;
/ * *
* Calculates the actual number of bytes required to store a 32 bit base 128 variable - length integer .
* @ param { number } value Value to encode
* @ returns { number } Number of bytes required . Capped to { @ link ByteBuffer . MAX _VARINT32 _BYTES }
* @ expose
* /
ByteBuffer . calculateVarint32 = function ( value ) {
// ref: src/google/protobuf/io/coded_stream.cc
value = value >>> 0 ;
if ( value < 1 << 7 ) return 1 ;
else if ( value < 1 << 14 ) return 2 ;
else if ( value < 1 << 21 ) return 3 ;
else if ( value < 1 << 28 ) return 4 ;
else return 5 ;
} ;
/ * *
* Zigzag encodes a signed 32 bit integer so that it can be effectively used with varint encoding .
* @ param { number } n Signed 32 bit integer
* @ returns { number } Unsigned zigzag encoded 32 bit integer
* @ expose
* /
ByteBuffer . zigZagEncode32 = function ( n ) {
return ( ( ( n |= 0 ) << 1 ) ^ ( n >> 31 ) ) >>> 0 ; // ref: src/google/protobuf/wire_format_lite.h
} ;
/ * *
* Decodes a zigzag encoded signed 32 bit integer .
* @ param { number } n Unsigned zigzag encoded 32 bit integer
* @ returns { number } Signed 32 bit integer
* @ expose
* /
ByteBuffer . zigZagDecode32 = function ( n ) {
return ( ( n >>> 1 ) ^ - ( n & 1 ) ) | 0 ; // // ref: src/google/protobuf/wire_format_lite.h
} ;
/ * *
* Writes a 32 bit base 128 variable - length integer .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* written if omitted .
* @ returns { ! ByteBuffer | number } this if ` offset ` is omitted , else the actual number of bytes written
* @ expose
* /
ByteBufferPrototype . writeVarint32 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' || value % 1 !== 0 )
throw TypeError ( "Illegal value: " + value + " (not an integer)" ) ;
value |= 0 ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
var size = ByteBuffer . calculateVarint32 ( value ) ,
b ;
offset += size ;
var capacity10 = this . buffer . byteLength ;
if ( offset > capacity10 )
this . resize ( ( capacity10 *= 2 ) > offset ? capacity10 : offset ) ;
offset -= size ;
// ref: http://code.google.com/searchframe#WTeibokF6gE/trunk/src/google/protobuf/io/coded_stream.cc
this . view . setUint8 ( offset , b = value | 0x80 ) ;
value >>>= 0 ;
if ( value >= 1 << 7 ) {
b = ( value >> 7 ) | 0x80 ;
this . view . setUint8 ( offset + 1 , b ) ;
if ( value >= 1 << 14 ) {
b = ( value >> 14 ) | 0x80 ;
this . view . setUint8 ( offset + 2 , b ) ;
if ( value >= 1 << 21 ) {
b = ( value >> 21 ) | 0x80 ;
this . view . setUint8 ( offset + 3 , b ) ;
if ( value >= 1 << 28 ) {
this . view . setUint8 ( offset + 4 , ( value >> 28 ) & 0x0F ) ;
size = 5 ;
} else {
this . view . setUint8 ( offset + 3 , b & 0x7F ) ;
size = 4 ;
}
} else {
this . view . setUint8 ( offset + 2 , b & 0x7F ) ;
size = 3 ;
}
} else {
this . view . setUint8 ( offset + 1 , b & 0x7F ) ;
size = 2 ;
}
} else {
this . view . setUint8 ( offset , b & 0x7F ) ;
size = 1 ;
}
if ( relative ) {
this . offset += size ;
return this ;
}
return size ;
} ;
/ * *
* Writes a zig - zag encoded 32 bit base 128 variable - length integer .
* @ param { number } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* written if omitted .
* @ returns { ! ByteBuffer | number } this if ` offset ` is omitted , else the actual number of bytes written
* @ expose
* /
ByteBufferPrototype . writeVarint32ZigZag = function ( value , offset ) {
return this . writeVarint32 ( ByteBuffer . zigZagEncode32 ( value ) , offset ) ;
} ;
/ * *
* Reads a 32 bit base 128 variable - length integer .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* written if omitted .
* @ returns { number | ! { value : number , length : number } } The value read if offset is omitted , else the value read
* and the actual number of bytes read .
* @ throws { Error } If it ' s not a valid varint . Has a property ` truncated = true ` if there is not enough data available
* to fully decode the varint .
* @ expose
* /
ByteBufferPrototype . readVarint32 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 1 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 1 + ") <= " + this . buffer . byteLength ) ;
}
// ref: src/google/protobuf/io/coded_stream.cc
var size = 0 ,
value = 0 >>> 0 ,
temp ,
ioffset ;
do {
ioffset = offset + size ;
if ( ! this . noAssert && ioffset > this . limit ) {
var err = Error ( "Truncated" ) ;
err [ 'truncated' ] = true ;
throw err ;
}
temp = this . view . getUint8 ( ioffset ) ;
if ( size < 5 )
value |= ( ( temp & 0x7F ) << ( 7 * size ) ) >>> 0 ;
++ size ;
} while ( ( temp & 0x80 ) === 0x80 ) ;
value = value | 0 ; // Make sure to discard the higher order bits
if ( relative ) {
this . offset += size ;
return value ;
}
return {
"value" : value ,
"length" : size
} ;
} ;
/ * *
* Reads a zig - zag encoded 32 bit base 128 variable - length integer .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* written if omitted .
* @ returns { number | ! { value : number , length : number } } The value read if offset is omitted , else the value read
* and the actual number of bytes read .
* @ throws { Error } If it ' s not a valid varint
* @ expose
* /
ByteBufferPrototype . readVarint32ZigZag = function ( offset ) {
var val = this . readVarint32 ( offset ) ;
if ( typeof val === 'object' )
val [ "value" ] = ByteBuffer . zigZagDecode32 ( val [ "value" ] ) ;
else
val = ByteBuffer . zigZagDecode32 ( val ) ;
return val ;
} ;
// types/varints/varint64
if ( Long ) {
/ * *
* Maximum number of bytes required to store a 64 bit base 128 variable - length integer .
* @ type { number }
* @ const
* @ expose
* /
ByteBuffer . MAX _VARINT64 _BYTES = 10 ;
/ * *
* Calculates the actual number of bytes required to store a 64 bit base 128 variable - length integer .
* @ param { number | ! Long } value Value to encode
* @ returns { number } Number of bytes required . Capped to { @ link ByteBuffer . MAX _VARINT64 _BYTES }
* @ expose
* /
ByteBuffer . calculateVarint64 = function ( value ) {
if ( typeof value === 'number' )
value = Long . fromNumber ( value ) ;
// ref: src/google/protobuf/io/coded_stream.cc
var part0 = value . toInt ( ) >>> 0 ,
part1 = value . shiftRightUnsigned ( 28 ) . toInt ( ) >>> 0 ,
part2 = value . shiftRightUnsigned ( 56 ) . toInt ( ) >>> 0 ;
if ( part2 == 0 ) {
if ( part1 == 0 ) {
if ( part0 < 1 << 14 )
return part0 < 1 << 7 ? 1 : 2 ;
else
return part0 < 1 << 21 ? 3 : 4 ;
} else {
if ( part1 < 1 << 14 )
return part1 < 1 << 7 ? 5 : 6 ;
else
return part1 < 1 << 21 ? 7 : 8 ;
}
} else
return part2 < 1 << 7 ? 9 : 10 ;
} ;
/ * *
* Zigzag encodes a signed 64 bit integer so that it can be effectively used with varint encoding .
* @ param { number | ! Long } value Signed long
* @ returns { ! Long } Unsigned zigzag encoded long
* @ expose
* /
ByteBuffer . zigZagEncode64 = function ( value ) {
if ( typeof value === 'number' )
value = Long . fromNumber ( value , false ) ;
else if ( value . unsigned !== false ) value = value . toSigned ( ) ;
// ref: src/google/protobuf/wire_format_lite.h
return value . shiftLeft ( 1 ) . xor ( value . shiftRight ( 63 ) ) . toUnsigned ( ) ;
} ;
/ * *
* Decodes a zigzag encoded signed 64 bit integer .
* @ param { ! Long | number } value Unsigned zigzag encoded long or JavaScript number
* @ returns { ! Long } Signed long
* @ expose
* /
ByteBuffer . zigZagDecode64 = function ( value ) {
if ( typeof value === 'number' )
value = Long . fromNumber ( value , false ) ;
else if ( value . unsigned !== false ) value = value . toSigned ( ) ;
// ref: src/google/protobuf/wire_format_lite.h
return value . shiftRightUnsigned ( 1 ) . xor ( value . and ( Long . ONE ) . toSigned ( ) . negate ( ) ) . toSigned ( ) ;
} ;
/ * *
* Writes a 64 bit base 128 variable - length integer .
* @ param { number | Long } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* written if omitted .
* @ returns { ! ByteBuffer | number } ` this ` if offset is omitted , else the actual number of bytes written .
* @ expose
* /
ByteBufferPrototype . writeVarint64 = function ( value , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof value === 'number' )
value = Long . fromNumber ( value ) ;
else if ( ! ( value && value instanceof Long ) )
throw TypeError ( "Illegal value: " + value + " (not an integer or Long)" ) ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
if ( typeof value === 'number' )
value = Long . fromNumber ( value , false ) ;
else if ( value . unsigned !== false ) value = value . toSigned ( ) ;
var size = ByteBuffer . calculateVarint64 ( value ) ,
part0 = value . toInt ( ) >>> 0 ,
part1 = value . shiftRightUnsigned ( 28 ) . toInt ( ) >>> 0 ,
part2 = value . shiftRightUnsigned ( 56 ) . toInt ( ) >>> 0 ;
offset += size ;
var capacity11 = this . buffer . byteLength ;
if ( offset > capacity11 )
this . resize ( ( capacity11 *= 2 ) > offset ? capacity11 : offset ) ;
offset -= size ;
switch ( size ) {
case 10 : this . view . setUint8 ( offset + 9 , ( part2 >>> 7 ) & 0x01 ) ;
case 9 : this . view . setUint8 ( offset + 8 , size !== 9 ? ( part2 ) | 0x80 : ( part2 ) & 0x7F ) ;
case 8 : this . view . setUint8 ( offset + 7 , size !== 8 ? ( part1 >>> 21 ) | 0x80 : ( part1 >>> 21 ) & 0x7F ) ;
case 7 : this . view . setUint8 ( offset + 6 , size !== 7 ? ( part1 >>> 14 ) | 0x80 : ( part1 >>> 14 ) & 0x7F ) ;
case 6 : this . view . setUint8 ( offset + 5 , size !== 6 ? ( part1 >>> 7 ) | 0x80 : ( part1 >>> 7 ) & 0x7F ) ;
case 5 : this . view . setUint8 ( offset + 4 , size !== 5 ? ( part1 ) | 0x80 : ( part1 ) & 0x7F ) ;
case 4 : this . view . setUint8 ( offset + 3 , size !== 4 ? ( part0 >>> 21 ) | 0x80 : ( part0 >>> 21 ) & 0x7F ) ;
case 3 : this . view . setUint8 ( offset + 2 , size !== 3 ? ( part0 >>> 14 ) | 0x80 : ( part0 >>> 14 ) & 0x7F ) ;
case 2 : this . view . setUint8 ( offset + 1 , size !== 2 ? ( part0 >>> 7 ) | 0x80 : ( part0 >>> 7 ) & 0x7F ) ;
case 1 : this . view . setUint8 ( offset , size !== 1 ? ( part0 ) | 0x80 : ( part0 ) & 0x7F ) ;
}
if ( relative ) {
this . offset += size ;
return this ;
} else {
return size ;
}
} ;
/ * *
* Writes a zig - zag encoded 64 bit base 128 variable - length integer .
* @ param { number | Long } value Value to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* written if omitted .
* @ returns { ! ByteBuffer | number } ` this ` if offset is omitted , else the actual number of bytes written .
* @ expose
* /
ByteBufferPrototype . writeVarint64ZigZag = function ( value , offset ) {
return this . writeVarint64 ( ByteBuffer . zigZagEncode64 ( value ) , offset ) ;
} ;
/ * *
* Reads a 64 bit base 128 variable - length integer . Requires Long . js .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* read if omitted .
* @ returns { ! Long | ! { value : Long , length : number } } The value read if offset is omitted , else the value read and
* the actual number of bytes read .
* @ throws { Error } If it ' s not a valid varint
* @ expose
* /
ByteBufferPrototype . readVarint64 = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 1 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 1 + ") <= " + this . buffer . byteLength ) ;
}
// ref: src/google/protobuf/io/coded_stream.cc
var start = offset ,
part0 = 0 ,
part1 = 0 ,
part2 = 0 ,
b = 0 ;
b = this . view . getUint8 ( offset ++ ) ; part0 = ( b & 0x7F ) ; if ( b & 0x80 ) {
b = this . view . getUint8 ( offset ++ ) ; part0 |= ( b & 0x7F ) << 7 ; if ( b & 0x80 ) {
b = this . view . getUint8 ( offset ++ ) ; part0 |= ( b & 0x7F ) << 14 ; if ( b & 0x80 ) {
b = this . view . getUint8 ( offset ++ ) ; part0 |= ( b & 0x7F ) << 21 ; if ( b & 0x80 ) {
b = this . view . getUint8 ( offset ++ ) ; part1 = ( b & 0x7F ) ; if ( b & 0x80 ) {
b = this . view . getUint8 ( offset ++ ) ; part1 |= ( b & 0x7F ) << 7 ; if ( b & 0x80 ) {
b = this . view . getUint8 ( offset ++ ) ; part1 |= ( b & 0x7F ) << 14 ; if ( b & 0x80 ) {
b = this . view . getUint8 ( offset ++ ) ; part1 |= ( b & 0x7F ) << 21 ; if ( b & 0x80 ) {
b = this . view . getUint8 ( offset ++ ) ; part2 = ( b & 0x7F ) ; if ( b & 0x80 ) {
b = this . view . getUint8 ( offset ++ ) ; part2 |= ( b & 0x7F ) << 7 ; if ( b & 0x80 ) {
throw Error ( "Buffer overrun" ) ; } } } } } } } } } }
var value = Long . fromBits ( part0 | ( part1 << 28 ) , ( part1 >>> 4 ) | ( part2 ) << 24 , false ) ;
if ( relative ) {
this . offset = offset ;
return value ;
} else {
return {
'value' : value ,
'length' : offset - start
} ;
}
} ;
/ * *
* Reads a zig - zag encoded 64 bit base 128 variable - length integer . Requires Long . js .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* read if omitted .
* @ returns { ! Long | ! { value : Long , length : number } } The value read if offset is omitted , else the value read and
* the actual number of bytes read .
* @ throws { Error } If it ' s not a valid varint
* @ expose
* /
ByteBufferPrototype . readVarint64ZigZag = function ( offset ) {
var val = this . readVarint64 ( offset ) ;
if ( val && val [ 'value' ] instanceof Long )
val [ "value" ] = ByteBuffer . zigZagDecode64 ( val [ "value" ] ) ;
else
val = ByteBuffer . zigZagDecode64 ( val ) ;
return val ;
} ;
} // Long
// types/strings/cstring
/ * *
* Writes a NULL - terminated UTF8 encoded string . For this to work the specified string must not contain any NULL
* characters itself .
* @ param { string } str String to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* contained in ` str ` + 1 if omitted .
* @ returns { ! ByteBuffer | number } this if offset is omitted , else the actual number of bytes written
* @ expose
* /
ByteBufferPrototype . writeCString = function ( str , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
var i ,
k = str . length ;
if ( ! this . noAssert ) {
if ( typeof str !== 'string' )
throw TypeError ( "Illegal str: Not a string" ) ;
for ( i = 0 ; i < k ; ++ i ) {
if ( str . charCodeAt ( i ) === 0 )
throw RangeError ( "Illegal str: Contains NULL-characters" ) ;
}
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
var start = offset ;
// UTF8 strings do not contain zero bytes in between except for the zero character, so:
k = utfx . calculateUTF16asUTF8 ( stringSource ( str ) ) [ 1 ] ;
offset += k + 1 ;
var capacity12 = this . buffer . byteLength ;
if ( offset > capacity12 )
this . resize ( ( capacity12 *= 2 ) > offset ? capacity12 : offset ) ;
offset -= k + 1 ;
utfx . encodeUTF16toUTF8 ( stringSource ( str ) , function ( b ) {
this . view . setUint8 ( offset ++ , b ) ;
} . bind ( this ) ) ;
this . view . setUint8 ( offset ++ , 0 ) ;
if ( relative ) {
this . offset = offset - start ;
return this ;
}
return k ;
} ;
/ * *
* Reads a NULL - terminated UTF8 encoded string . For this to work the string read must not contain any NULL characters
* itself .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* read if omitted .
* @ returns { string | ! { string : string , length : number } } The string read if offset is omitted , else the string
* read and the actual number of bytes read .
* @ expose
* /
ByteBufferPrototype . readCString = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 1 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 1 + ") <= " + this . buffer . byteLength ) ;
}
var start = offset ,
temp ;
// UTF8 strings do not contain zero bytes in between except for the zero character itself, so:
var sd , b = - 1 ;
utfx . decodeUTF8toUTF16 ( function ( ) {
if ( b === 0 ) return null ;
if ( offset >= this . limit )
throw RangeError ( "Illegal range: Truncated data, " + offset + " < " + this . limit ) ;
return ( b = this . view . getUint8 ( offset ++ ) ) === 0 ? null : b ;
} . bind ( this ) , sd = stringDestination ( ) , true ) ;
if ( relative ) {
this . offset = offset ;
return sd ( ) ;
} else {
return {
"string" : sd ( ) ,
"length" : offset - start
} ;
}
} ;
// types/strings/istring
/ * *
* Writes a length as uint32 prefixed UTF8 encoded string .
* @ param { string } str String to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* written if omitted .
* @ returns { ! ByteBuffer | number } ` this ` if ` offset ` is omitted , else the actual number of bytes written
* @ expose
* @ see ByteBuffer # writeVarint32
* /
ByteBufferPrototype . writeIString = function ( str , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof str !== 'string' )
throw TypeError ( "Illegal str: Not a string" ) ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
var start = offset ,
k ;
k = utfx . calculateUTF16asUTF8 ( stringSource ( str ) , this . noAssert ) [ 1 ] ;
offset += 4 + k ;
var capacity13 = this . buffer . byteLength ;
if ( offset > capacity13 )
this . resize ( ( capacity13 *= 2 ) > offset ? capacity13 : offset ) ;
offset -= 4 + k ;
this . view . setUint32 ( offset , k , this . littleEndian ) ;
offset += 4 ;
utfx . encodeUTF16toUTF8 ( stringSource ( str ) , function ( b ) {
this . view . setUint8 ( offset ++ , b ) ;
} . bind ( this ) ) ;
if ( offset !== start + 4 + k )
throw RangeError ( "Illegal range: Truncated data, " + offset + " == " + ( offset + 4 + k ) ) ;
if ( relative ) {
this . offset = offset ;
return this ;
}
return offset - start ;
} ;
/ * *
* Reads a length as uint32 prefixed UTF8 encoded string .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* read if omitted .
* @ returns { string | ! { string : string , length : number } } The string read if offset is omitted , else the string
* read and the actual number of bytes read .
* @ expose
* @ see ByteBuffer # readVarint32
* /
ByteBufferPrototype . readIString = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 4 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 4 + ") <= " + this . buffer . byteLength ) ;
}
var temp = 0 ,
start = offset ,
str ;
temp = this . view . getUint32 ( offset , this . littleEndian ) ;
offset += 4 ;
var k = offset + temp ,
sd ;
utfx . decodeUTF8toUTF16 ( function ( ) {
return offset < k ? this . view . getUint8 ( offset ++ ) : null ;
} . bind ( this ) , sd = stringDestination ( ) , this . noAssert ) ;
str = sd ( ) ;
if ( relative ) {
this . offset = offset ;
return str ;
} else {
return {
'string' : str ,
'length' : offset - start
} ;
}
} ;
// types/strings/utf8string
/ * *
* Metrics representing number of UTF8 characters . Evaluates to ` c ` .
* @ type { string }
* @ const
* @ expose
* /
ByteBuffer . METRICS _CHARS = 'c' ;
/ * *
* Metrics representing number of bytes . Evaluates to ` b ` .
* @ type { string }
* @ const
* @ expose
* /
ByteBuffer . METRICS _BYTES = 'b' ;
/ * *
* Writes an UTF8 encoded string .
* @ param { string } str String to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } if omitted .
* @ returns { ! ByteBuffer | number } this if offset is omitted , else the actual number of bytes written .
* @ expose
* /
ByteBufferPrototype . writeUTF8String = function ( str , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
var k ;
var start = offset ;
k = utfx . calculateUTF16asUTF8 ( stringSource ( str ) ) [ 1 ] ;
offset += k ;
var capacity14 = this . buffer . byteLength ;
if ( offset > capacity14 )
this . resize ( ( capacity14 *= 2 ) > offset ? capacity14 : offset ) ;
offset -= k ;
utfx . encodeUTF16toUTF8 ( stringSource ( str ) , function ( b ) {
this . view . setUint8 ( offset ++ , b ) ;
} . bind ( this ) ) ;
if ( relative ) {
this . offset = offset ;
return this ;
}
return offset - start ;
} ;
/ * *
* Writes an UTF8 encoded string . This is an alias of { @ link ByteBuffer # writeUTF8String } .
* @ function
* @ param { string } str String to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } if omitted .
* @ returns { ! ByteBuffer | number } this if offset is omitted , else the actual number of bytes written .
* @ expose
* /
ByteBufferPrototype . writeString = ByteBufferPrototype . writeUTF8String ;
/ * *
* Calculates the number of UTF8 characters of a string . JavaScript itself uses UTF - 16 , so that a string ' s
* ` length ` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF .
* @ function
* @ param { string } str String to calculate
* @ returns { number } Number of UTF8 characters
* @ expose
* /
ByteBuffer . calculateUTF8Chars = function ( str ) {
return utfx . calculateUTF16asUTF8 ( stringSource ( str ) ) [ 0 ] ;
} ;
/ * *
* Calculates the number of UTF8 bytes of a string .
* @ function
* @ param { string } str String to calculate
* @ returns { number } Number of UTF8 bytes
* @ expose
* /
ByteBuffer . calculateUTF8Bytes = function ( str ) {
return utfx . calculateUTF16asUTF8 ( stringSource ( str ) ) [ 1 ] ;
} ;
/ * *
* Reads an UTF8 encoded string .
* @ param { number } length Number of characters or bytes to read .
* @ param { string = } metrics Metrics specifying what ` length ` is meant to count . Defaults to
* { @ link ByteBuffer . METRICS _CHARS } .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* read if omitted .
* @ returns { string | ! { string : string , length : number } } The string read if offset is omitted , else the string
* read and the actual number of bytes read .
* @ expose
* /
ByteBufferPrototype . readUTF8String = function ( length , metrics , offset ) {
if ( typeof metrics === 'number' ) {
offset = metrics ;
metrics = undefined ;
}
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( typeof metrics === 'undefined' ) metrics = ByteBuffer . METRICS _CHARS ;
if ( ! this . noAssert ) {
if ( typeof length !== 'number' || length % 1 !== 0 )
throw TypeError ( "Illegal length: " + length + " (not an integer)" ) ;
length |= 0 ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
var i = 0 ,
start = offset ,
sd ;
if ( metrics === ByteBuffer . METRICS _CHARS ) { // The same for node and the browser
sd = stringDestination ( ) ;
utfx . decodeUTF8 ( function ( ) {
return i < length && offset < this . limit ? this . view . getUint8 ( offset ++ ) : null ;
} . bind ( this ) , function ( cp ) {
++ i ; utfx . UTF8toUTF16 ( cp , sd ) ;
} . bind ( this ) ) ;
if ( i !== length )
throw RangeError ( "Illegal range: Truncated data, " + i + " == " + length ) ;
if ( relative ) {
this . offset = offset ;
return sd ( ) ;
} else {
return {
"string" : sd ( ) ,
"length" : offset - start
} ;
}
} else if ( metrics === ByteBuffer . METRICS _BYTES ) {
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + length > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + length + ") <= " + this . buffer . byteLength ) ;
}
var k = offset + length ;
utfx . decodeUTF8toUTF16 ( function ( ) {
return offset < k ? this . view . getUint8 ( offset ++ ) : null ;
} . bind ( this ) , sd = stringDestination ( ) , this . noAssert ) ;
if ( offset !== k )
throw RangeError ( "Illegal range: Truncated data, " + offset + " == " + k ) ;
if ( relative ) {
this . offset = offset ;
return sd ( ) ;
} else {
return {
'string' : sd ( ) ,
'length' : offset - start
} ;
}
} else
throw TypeError ( "Unsupported metrics: " + metrics ) ;
} ;
/ * *
* Reads an UTF8 encoded string . This is an alias of { @ link ByteBuffer # readUTF8String } .
* @ function
* @ param { number } length Number of characters or bytes to read
* @ param { number = } metrics Metrics specifying what ` n ` is meant to count . Defaults to
* { @ link ByteBuffer . METRICS _CHARS } .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* read if omitted .
* @ returns { string | ! { string : string , length : number } } The string read if offset is omitted , else the string
* read and the actual number of bytes read .
* @ expose
* /
ByteBufferPrototype . readString = ByteBufferPrototype . readUTF8String ;
// types/strings/vstring
/ * *
* Writes a length as varint32 prefixed UTF8 encoded string .
* @ param { string } str String to write
* @ param { number = } offset Offset to write to . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* written if omitted .
* @ returns { ! ByteBuffer | number } ` this ` if ` offset ` is omitted , else the actual number of bytes written
* @ expose
* @ see ByteBuffer # writeVarint32
* /
ByteBufferPrototype . writeVString = function ( str , offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof str !== 'string' )
throw TypeError ( "Illegal str: Not a string" ) ;
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
var start = offset ,
k , l ;
k = utfx . calculateUTF16asUTF8 ( stringSource ( str ) , this . noAssert ) [ 1 ] ;
l = ByteBuffer . calculateVarint32 ( k ) ;
offset += l + k ;
var capacity15 = this . buffer . byteLength ;
if ( offset > capacity15 )
this . resize ( ( capacity15 *= 2 ) > offset ? capacity15 : offset ) ;
offset -= l + k ;
offset += this . writeVarint32 ( k , offset ) ;
utfx . encodeUTF16toUTF8 ( stringSource ( str ) , function ( b ) {
this . view . setUint8 ( offset ++ , b ) ;
} . bind ( this ) ) ;
if ( offset !== start + k + l )
throw RangeError ( "Illegal range: Truncated data, " + offset + " == " + ( offset + k + l ) ) ;
if ( relative ) {
this . offset = offset ;
return this ;
}
return offset - start ;
} ;
/ * *
* Reads a length as varint32 prefixed UTF8 encoded string .
* @ param { number = } offset Offset to read from . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* read if omitted .
* @ returns { string | ! { string : string , length : number } } The string read if offset is omitted , else the string
* read and the actual number of bytes read .
* @ expose
* @ see ByteBuffer # readVarint32
* /
ByteBufferPrototype . readVString = function ( offset ) {
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 1 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 1 + ") <= " + this . buffer . byteLength ) ;
}
var temp = this . readVarint32 ( offset ) ,
start = offset ,
str ;
offset += temp [ 'length' ] ;
temp = temp [ 'value' ] ;
var k = offset + temp ,
sd = stringDestination ( ) ;
utfx . decodeUTF8toUTF16 ( function ( ) {
return offset < k ? this . view . getUint8 ( offset ++ ) : null ;
} . bind ( this ) , sd , this . noAssert ) ;
str = sd ( ) ;
if ( relative ) {
this . offset = offset ;
return str ;
} else {
return {
'string' : str ,
'length' : offset - start
} ;
}
} ;
/ * *
* Appends some data to this ByteBuffer . This will overwrite any contents behind the specified offset up to the appended
* data ' s length .
* @ param { ! ByteBuffer | ! ArrayBuffer | ! Uint8Array | string } source Data to append . If ` source ` is a ByteBuffer , its offsets
* will be modified according to the performed read operation .
* @ param { ( string | number ) = } encoding Encoding if ` data ` is a string ( "base64" , "hex" , "binary" , defaults to "utf8" )
* @ param { number = } offset Offset to append at . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* read if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* @ example A relative ` <01 02>03.append(<04 05>) ` will result in ` <01 02 04 05>, 04 05| `
* @ example An absolute ` <01 02>03.append(04 05>, 1) ` will result in ` <01 04>05, 04 05| `
* /
ByteBufferPrototype . append = function ( source , encoding , offset ) {
if ( typeof encoding === 'number' || typeof encoding !== 'string' ) {
offset = encoding ;
encoding = undefined ;
}
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
if ( ! ( source instanceof ByteBuffer ) )
source = ByteBuffer . wrap ( source , encoding ) ;
var length = source . limit - source . offset ;
if ( length <= 0 ) return this ; // Nothing to append
offset += length ;
var capacity16 = this . buffer . byteLength ;
if ( offset > capacity16 )
this . resize ( ( capacity16 *= 2 ) > offset ? capacity16 : offset ) ;
offset -= length ;
new Uint8Array ( this . buffer , offset ) . set ( new Uint8Array ( source . buffer ) . subarray ( source . offset , source . limit ) ) ;
source . offset += length ;
if ( relative ) this . offset += length ;
return this ;
} ;
/ * *
* Appends this ByteBuffer ' s contents to another ByteBuffer . This will overwrite any contents behind the specified
* offset up to the length of this ByteBuffer ' s data .
* @ param { ! ByteBuffer } target Target ByteBuffer
* @ param { number = } offset Offset to append to . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* read if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* @ see ByteBuffer # append
* /
ByteBufferPrototype . appendTo = function ( target , offset ) {
target . append ( this , offset ) ;
return this ;
} ;
/ * *
* Enables or disables assertions of argument types and offsets . Assertions are enabled by default but you can opt to
* disable them if your code already makes sure that everything is valid .
* @ param { boolean } assert ` true ` to enable assertions , otherwise ` false `
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . assert = function ( assert ) {
this . noAssert = ! assert ;
return this ;
} ;
/ * *
* Gets the capacity of this ByteBuffer ' s backing buffer .
* @ returns { number } Capacity of the backing buffer
* @ expose
* /
ByteBufferPrototype . capacity = function ( ) {
return this . buffer . byteLength ;
} ;
/ * *
* Clears this ByteBuffer ' s offsets by setting { @ link ByteBuffer # offset } to ` 0 ` and { @ link ByteBuffer # limit } to the
* backing buffer ' s capacity . Discards { @ link ByteBuffer # markedOffset } .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . clear = function ( ) {
this . offset = 0 ;
this . limit = this . buffer . byteLength ;
this . markedOffset = - 1 ;
return this ;
} ;
/ * *
* Creates a cloned instance of this ByteBuffer , preset with this ByteBuffer ' s values for { @ link ByteBuffer # offset } ,
* { @ link ByteBuffer # markedOffset } and { @ link ByteBuffer # limit } .
* @ param { boolean = } copy Whether to copy the backing buffer or to return another view on the same , defaults to ` false `
* @ returns { ! ByteBuffer } Cloned instance
* @ expose
* /
ByteBufferPrototype . clone = function ( copy ) {
var bb = new ByteBuffer ( 0 , this . littleEndian , this . noAssert ) ;
if ( copy ) {
var buffer = new ArrayBuffer ( this . buffer . byteLength ) ;
new Uint8Array ( buffer ) . set ( this . buffer ) ;
bb . buffer = buffer ;
bb . view = new DataView ( buffer ) ;
} else {
bb . buffer = this . buffer ;
bb . view = this . view ;
}
bb . offset = this . offset ;
bb . markedOffset = this . markedOffset ;
bb . limit = this . limit ;
return bb ;
} ;
/ * *
* Compacts this ByteBuffer to be backed by a { @ link ByteBuffer # buffer } of its contents ' length . Contents are the bytes
* between { @ link ByteBuffer # offset } and { @ link ByteBuffer # limit } . Will set ` offset = 0 ` and ` limit = capacity ` and
* adapt { @ link ByteBuffer # markedOffset } to the same relative position if set .
* @ param { number = } begin Offset to start at , defaults to { @ link ByteBuffer # offset }
* @ param { number = } end Offset to end at , defaults to { @ link ByteBuffer # limit }
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . compact = function ( begin , end ) {
if ( typeof begin === 'undefined' ) begin = this . offset ;
if ( typeof end === 'undefined' ) end = this . limit ;
if ( ! this . noAssert ) {
if ( typeof begin !== 'number' || begin % 1 !== 0 )
throw TypeError ( "Illegal begin: Not an integer" ) ;
begin >>>= 0 ;
if ( typeof end !== 'number' || end % 1 !== 0 )
throw TypeError ( "Illegal end: Not an integer" ) ;
end >>>= 0 ;
if ( begin < 0 || begin > end || end > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + begin + " <= " + end + " <= " + this . buffer . byteLength ) ;
}
if ( begin === 0 && end === this . buffer . byteLength )
return this ; // Already compacted
var len = end - begin ;
if ( len === 0 ) {
this . buffer = EMPTY _BUFFER ;
this . view = null ;
if ( this . markedOffset >= 0 ) this . markedOffset -= begin ;
this . offset = 0 ;
this . limit = 0 ;
return this ;
}
var buffer = new ArrayBuffer ( len ) ;
new Uint8Array ( buffer ) . set ( new Uint8Array ( this . buffer ) . subarray ( begin , end ) ) ;
this . buffer = buffer ;
this . view = new DataView ( buffer ) ;
if ( this . markedOffset >= 0 ) this . markedOffset -= begin ;
this . offset = 0 ;
this . limit = len ;
return this ;
} ;
/ * *
* Creates a copy of this ByteBuffer ' s contents . Contents are the bytes between { @ link ByteBuffer # offset } and
* { @ link ByteBuffer # limit } .
* @ param { number = } begin Begin offset , defaults to { @ link ByteBuffer # offset } .
* @ param { number = } end End offset , defaults to { @ link ByteBuffer # limit } .
* @ returns { ! ByteBuffer } Copy
* @ expose
* /
ByteBufferPrototype . copy = function ( begin , end ) {
if ( typeof begin === 'undefined' ) begin = this . offset ;
if ( typeof end === 'undefined' ) end = this . limit ;
if ( ! this . noAssert ) {
if ( typeof begin !== 'number' || begin % 1 !== 0 )
throw TypeError ( "Illegal begin: Not an integer" ) ;
begin >>>= 0 ;
if ( typeof end !== 'number' || end % 1 !== 0 )
throw TypeError ( "Illegal end: Not an integer" ) ;
end >>>= 0 ;
if ( begin < 0 || begin > end || end > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + begin + " <= " + end + " <= " + this . buffer . byteLength ) ;
}
if ( begin === end )
return new ByteBuffer ( 0 , this . littleEndian , this . noAssert ) ;
var capacity = end - begin ,
bb = new ByteBuffer ( capacity , this . littleEndian , this . noAssert ) ;
bb . offset = 0 ;
bb . limit = capacity ;
if ( bb . markedOffset >= 0 ) bb . markedOffset -= begin ;
this . copyTo ( bb , 0 , begin , end ) ;
return bb ;
} ;
/ * *
* Copies this ByteBuffer ' s contents to another ByteBuffer . Contents are the bytes between { @ link ByteBuffer # offset } and
* { @ link ByteBuffer # limit } .
* @ param { ! ByteBuffer } target Target ByteBuffer
* @ param { number = } targetOffset Offset to copy to . Will use and increase the target ' s { @ link ByteBuffer # offset }
* by the number of bytes copied if omitted .
* @ param { number = } sourceOffset Offset to start copying from . Will use and increase { @ link ByteBuffer # offset } by the
* number of bytes copied if omitted .
* @ param { number = } sourceLimit Offset to end copying from , defaults to { @ link ByteBuffer # limit }
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . copyTo = function ( target , targetOffset , sourceOffset , sourceLimit ) {
var relative ,
targetRelative ;
if ( ! this . noAssert ) {
if ( ! ByteBuffer . isByteBuffer ( target ) )
throw TypeError ( "Illegal target: Not a ByteBuffer" ) ;
}
targetOffset = ( targetRelative = typeof targetOffset === 'undefined' ) ? target . offset : targetOffset | 0 ;
sourceOffset = ( relative = typeof sourceOffset === 'undefined' ) ? this . offset : sourceOffset | 0 ;
sourceLimit = typeof sourceLimit === 'undefined' ? this . limit : sourceLimit | 0 ;
if ( targetOffset < 0 || targetOffset > target . buffer . byteLength )
throw RangeError ( "Illegal target range: 0 <= " + targetOffset + " <= " + target . buffer . byteLength ) ;
if ( sourceOffset < 0 || sourceLimit > this . buffer . byteLength )
throw RangeError ( "Illegal source range: 0 <= " + sourceOffset + " <= " + this . buffer . byteLength ) ;
var len = sourceLimit - sourceOffset ;
if ( len === 0 )
return target ; // Nothing to copy
target . ensureCapacity ( targetOffset + len ) ;
new Uint8Array ( target . buffer ) . set ( new Uint8Array ( this . buffer ) . subarray ( sourceOffset , sourceLimit ) , targetOffset ) ;
if ( relative ) this . offset += len ;
if ( targetRelative ) target . offset += len ;
return this ;
} ;
/ * *
* Makes sure that this ByteBuffer is backed by a { @ link ByteBuffer # buffer } of at least the specified capacity . If the
* current capacity is exceeded , it will be doubled . If double the current capacity is less than the required capacity ,
* the required capacity will be used instead .
* @ param { number } capacity Required capacity
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . ensureCapacity = function ( capacity ) {
var current = this . buffer . byteLength ;
if ( current < capacity )
return this . resize ( ( current *= 2 ) > capacity ? current : capacity ) ;
return this ;
} ;
/ * *
* Overwrites this ByteBuffer ' s contents with the specified value . Contents are the bytes between
* { @ link ByteBuffer # offset } and { @ link ByteBuffer # limit } .
* @ param { number | string } value Byte value to fill with . If given as a string , the first character is used .
* @ param { number = } begin Begin offset . Will use and increase { @ link ByteBuffer # offset } by the number of bytes
* written if omitted . defaults to { @ link ByteBuffer # offset } .
* @ param { number = } end End offset , defaults to { @ link ByteBuffer # limit } .
* @ returns { ! ByteBuffer } this
* @ expose
* @ example ` someByteBuffer.clear().fill(0) ` fills the entire backing buffer with zeroes
* /
ByteBufferPrototype . fill = function ( value , begin , end ) {
var relative = typeof begin === 'undefined' ;
if ( relative ) begin = this . offset ;
if ( typeof value === 'string' && value . length > 0 )
value = value . charCodeAt ( 0 ) ;
if ( typeof begin === 'undefined' ) begin = this . offset ;
if ( typeof end === 'undefined' ) end = this . limit ;
if ( ! this . noAssert ) {
if ( typeof value !== 'number' || value % 1 !== 0 )
throw TypeError ( "Illegal value: " + value + " (not an integer)" ) ;
value |= 0 ;
if ( typeof begin !== 'number' || begin % 1 !== 0 )
throw TypeError ( "Illegal begin: Not an integer" ) ;
begin >>>= 0 ;
if ( typeof end !== 'number' || end % 1 !== 0 )
throw TypeError ( "Illegal end: Not an integer" ) ;
end >>>= 0 ;
if ( begin < 0 || begin > end || end > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + begin + " <= " + end + " <= " + this . buffer . byteLength ) ;
}
if ( begin >= end )
return this ; // Nothing to fill
while ( begin < end ) this . view . setUint8 ( begin ++ , value ) ;
if ( relative ) this . offset = begin ;
return this ;
} ;
/ * *
* Makes this ByteBuffer ready for a new sequence of write or relative read operations . Sets ` limit = offset ` and
* ` offset = 0 ` . Make sure always to flip a ByteBuffer when all relative read or write operations are complete .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . flip = function ( ) {
this . limit = this . offset ;
this . offset = 0 ;
return this ;
} ;
/ * *
* Marks an offset on this ByteBuffer to be used later .
* @ param { number = } offset Offset to mark . Defaults to { @ link ByteBuffer # offset } .
* @ returns { ! ByteBuffer } this
* @ throws { TypeError } If ` offset ` is not a valid number
* @ throws { RangeError } If ` offset ` is out of bounds
* @ see ByteBuffer # reset
* @ expose
* /
ByteBufferPrototype . mark = function ( offset ) {
offset = typeof offset === 'undefined' ? this . offset : offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
this . markedOffset = offset ;
return this ;
} ;
/ * *
* Sets the byte order .
* @ param { boolean } littleEndian ` true ` for little endian byte order , ` false ` for big endian
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . order = function ( littleEndian ) {
if ( ! this . noAssert ) {
if ( typeof littleEndian !== 'boolean' )
throw TypeError ( "Illegal littleEndian: Not a boolean" ) ;
}
this . littleEndian = ! ! littleEndian ;
return this ;
} ;
/ * *
* Switches ( to ) little endian byte order .
* @ param { boolean = } littleEndian Defaults to ` true ` , otherwise uses big endian
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . LE = function ( littleEndian ) {
this . littleEndian = typeof littleEndian !== 'undefined' ? ! ! littleEndian : true ;
return this ;
} ;
/ * *
* Switches ( to ) big endian byte order .
* @ param { boolean = } bigEndian Defaults to ` true ` , otherwise uses little endian
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . BE = function ( bigEndian ) {
this . littleEndian = typeof bigEndian !== 'undefined' ? ! bigEndian : false ;
return this ;
} ;
/ * *
* Prepends some data to this ByteBuffer . This will overwrite any contents before the specified offset up to the
* prepended data ' s length . If there is not enough space available before the specified ` offset ` , the backing buffer
* will be resized and its contents moved accordingly .
* @ param { ! ByteBuffer | string | ! ArrayBuffer } source Data to prepend . If ` source ` is a ByteBuffer , its offset will be
* modified according to the performed read operation .
* @ param { ( string | number ) = } encoding Encoding if ` data ` is a string ( "base64" , "hex" , "binary" , defaults to "utf8" )
* @ param { number = } offset Offset to prepend at . Will use and decrease { @ link ByteBuffer # offset } by the number of bytes
* prepended if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* @ example A relative ` 00<01 02 03>.prepend(<04 05>) ` results in ` <04 05 01 02 03>, 04 05| `
* @ example An absolute ` 00<01 02 03>.prepend(<04 05>, 2) ` results in ` 04<05 02 03>, 04 05| `
* /
ByteBufferPrototype . prepend = function ( source , encoding , offset ) {
if ( typeof encoding === 'number' || typeof encoding !== 'string' ) {
offset = encoding ;
encoding = undefined ;
}
var relative = typeof offset === 'undefined' ;
if ( relative ) offset = this . offset ;
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: " + offset + " (not an integer)" ) ;
offset >>>= 0 ;
if ( offset < 0 || offset + 0 > this . buffer . byteLength )
throw RangeError ( "Illegal offset: 0 <= " + offset + " (+" + 0 + ") <= " + this . buffer . byteLength ) ;
}
if ( ! ( source instanceof ByteBuffer ) )
source = ByteBuffer . wrap ( source , encoding ) ;
var len = source . limit - source . offset ;
if ( len <= 0 ) return this ; // Nothing to prepend
var diff = len - offset ;
var arrayView ;
if ( diff > 0 ) { // Not enough space before offset, so resize + move
var buffer = new ArrayBuffer ( this . buffer . byteLength + diff ) ;
arrayView = new Uint8Array ( buffer ) ;
arrayView . set ( new Uint8Array ( this . buffer ) . subarray ( offset , this . buffer . byteLength ) , len ) ;
this . buffer = buffer ;
this . view = new DataView ( buffer ) ;
this . offset += diff ;
if ( this . markedOffset >= 0 ) this . markedOffset += diff ;
this . limit += diff ;
offset += diff ;
} else {
arrayView = new Uint8Array ( this . buffer ) ;
}
arrayView . set ( new Uint8Array ( source . buffer ) . subarray ( source . offset , source . limit ) , offset - len ) ;
source . offset = source . limit ;
if ( relative )
this . offset -= len ;
return this ;
} ;
/ * *
* Prepends this ByteBuffer to another ByteBuffer . This will overwrite any contents before the specified offset up to the
* prepended data ' s length . If there is not enough space available before the specified ` offset ` , the backing buffer
* will be resized and its contents moved accordingly .
* @ param { ! ByteBuffer } target Target ByteBuffer
* @ param { number = } offset Offset to prepend at . Will use and decrease { @ link ByteBuffer # offset } by the number of bytes
* prepended if omitted .
* @ returns { ! ByteBuffer } this
* @ expose
* @ see ByteBuffer # prepend
* /
ByteBufferPrototype . prependTo = function ( target , offset ) {
target . prepend ( this , offset ) ;
return this ;
} ;
/ * *
* Prints debug information about this ByteBuffer ' s contents .
* @ param { function ( string ) = } out Output function to call , defaults to console . log
* @ expose
* /
ByteBufferPrototype . printDebug = function ( out ) {
if ( typeof out !== 'function' ) out = console . log . bind ( console ) ;
out (
this . toString ( ) + "\n" +
"-------------------------------------------------------------------\n" +
this . toDebug ( /* columns */ true )
) ;
} ;
/ * *
* Gets the number of remaining readable bytes . Contents are the bytes between { @ link ByteBuffer # offset } and
* { @ link ByteBuffer # limit } , so this returns ` limit - offset ` .
* @ returns { number } Remaining readable bytes . May be negative if ` offset > limit ` .
* @ expose
* /
ByteBufferPrototype . remaining = function ( ) {
return this . limit - this . offset ;
} ;
/ * *
* Resets this ByteBuffer ' s { @ link ByteBuffer # offset } . If an offset has been marked through { @ link ByteBuffer # mark }
* before , ` offset ` will be set to { @ link ByteBuffer # markedOffset } , which will then be discarded . If no offset has been
* marked , sets ` offset = 0 ` .
* @ returns { ! ByteBuffer } this
* @ see ByteBuffer # mark
* @ expose
* /
ByteBufferPrototype . reset = function ( ) {
if ( this . markedOffset >= 0 ) {
this . offset = this . markedOffset ;
this . markedOffset = - 1 ;
} else {
this . offset = 0 ;
}
return this ;
} ;
/ * *
* Resizes this ByteBuffer to be backed by a buffer of at least the given capacity . Will do nothing if already that
* large or larger .
* @ param { number } capacity Capacity required
* @ returns { ! ByteBuffer } this
* @ throws { TypeError } If ` capacity ` is not a number
* @ throws { RangeError } If ` capacity < 0 `
* @ expose
* /
ByteBufferPrototype . resize = function ( capacity ) {
if ( ! this . noAssert ) {
if ( typeof capacity !== 'number' || capacity % 1 !== 0 )
throw TypeError ( "Illegal capacity: " + capacity + " (not an integer)" ) ;
capacity |= 0 ;
if ( capacity < 0 )
throw RangeError ( "Illegal capacity: 0 <= " + capacity ) ;
}
if ( this . buffer . byteLength < capacity ) {
var buffer = new ArrayBuffer ( capacity ) ;
new Uint8Array ( buffer ) . set ( new Uint8Array ( this . buffer ) ) ;
this . buffer = buffer ;
this . view = new DataView ( buffer ) ;
}
return this ;
} ;
/ * *
* Reverses this ByteBuffer ' s contents .
* @ param { number = } begin Offset to start at , defaults to { @ link ByteBuffer # offset }
* @ param { number = } end Offset to end at , defaults to { @ link ByteBuffer # limit }
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . reverse = function ( begin , end ) {
if ( typeof begin === 'undefined' ) begin = this . offset ;
if ( typeof end === 'undefined' ) end = this . limit ;
if ( ! this . noAssert ) {
if ( typeof begin !== 'number' || begin % 1 !== 0 )
throw TypeError ( "Illegal begin: Not an integer" ) ;
begin >>>= 0 ;
if ( typeof end !== 'number' || end % 1 !== 0 )
throw TypeError ( "Illegal end: Not an integer" ) ;
end >>>= 0 ;
if ( begin < 0 || begin > end || end > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + begin + " <= " + end + " <= " + this . buffer . byteLength ) ;
}
if ( begin === end )
return this ; // Nothing to reverse
Array . prototype . reverse . call ( new Uint8Array ( this . buffer ) . subarray ( begin , end ) ) ;
this . view = new DataView ( this . buffer ) ; // FIXME: Why exactly is this necessary?
return this ;
} ;
/ * *
* Skips the next ` length ` bytes . This will just advance
* @ param { number } length Number of bytes to skip . May also be negative to move the offset back .
* @ returns { ! ByteBuffer } this
* @ expose
* /
ByteBufferPrototype . skip = function ( length ) {
if ( ! this . noAssert ) {
if ( typeof length !== 'number' || length % 1 !== 0 )
throw TypeError ( "Illegal length: " + length + " (not an integer)" ) ;
length |= 0 ;
}
var offset = this . offset + length ;
if ( ! this . noAssert ) {
if ( offset < 0 || offset > this . buffer . byteLength )
throw RangeError ( "Illegal length: 0 <= " + this . offset + " + " + length + " <= " + this . buffer . byteLength ) ;
}
this . offset = offset ;
return this ;
} ;
/ * *
* Slices this ByteBuffer by creating a cloned instance with ` offset = begin ` and ` limit = end ` .
* @ param { number = } begin Begin offset , defaults to { @ link ByteBuffer # offset } .
* @ param { number = } end End offset , defaults to { @ link ByteBuffer # limit } .
* @ returns { ! ByteBuffer } Clone of this ByteBuffer with slicing applied , backed by the same { @ link ByteBuffer # buffer }
* @ expose
* /
ByteBufferPrototype . slice = function ( begin , end ) {
if ( typeof begin === 'undefined' ) begin = this . offset ;
if ( typeof end === 'undefined' ) end = this . limit ;
if ( ! this . noAssert ) {
if ( typeof begin !== 'number' || begin % 1 !== 0 )
throw TypeError ( "Illegal begin: Not an integer" ) ;
begin >>>= 0 ;
if ( typeof end !== 'number' || end % 1 !== 0 )
throw TypeError ( "Illegal end: Not an integer" ) ;
end >>>= 0 ;
if ( begin < 0 || begin > end || end > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + begin + " <= " + end + " <= " + this . buffer . byteLength ) ;
}
var bb = this . clone ( ) ;
bb . offset = begin ;
bb . limit = end ;
return bb ;
} ;
/ * *
* Returns a copy of the backing buffer that contains this ByteBuffer ' s contents . Contents are the bytes between
* { @ link ByteBuffer # offset } and { @ link ByteBuffer # limit } . Will transparently { @ link ByteBuffer # flip } this
* ByteBuffer if ` offset > limit ` but the actual offsets remain untouched .
* @ param { boolean = } forceCopy If ` true ` returns a copy , otherwise returns a view referencing the same memory if
* possible . Defaults to ` false `
* @ returns { ! ArrayBuffer } Contents as an ArrayBuffer
* @ expose
* /
ByteBufferPrototype . toBuffer = function ( forceCopy ) {
var offset = this . offset ,
limit = this . limit ;
if ( offset > limit ) {
var t = offset ;
offset = limit ;
limit = t ;
}
if ( ! this . noAssert ) {
if ( typeof offset !== 'number' || offset % 1 !== 0 )
throw TypeError ( "Illegal offset: Not an integer" ) ;
offset >>>= 0 ;
if ( typeof limit !== 'number' || limit % 1 !== 0 )
throw TypeError ( "Illegal limit: Not an integer" ) ;
limit >>>= 0 ;
if ( offset < 0 || offset > limit || limit > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + offset + " <= " + limit + " <= " + this . buffer . byteLength ) ;
}
// NOTE: It's not possible to have another ArrayBuffer reference the same memory as the backing buffer. This is
// possible with Uint8Array#subarray only, but we have to return an ArrayBuffer by contract. So:
if ( ! forceCopy && offset === 0 && limit === this . buffer . byteLength ) {
return this . buffer ;
}
if ( offset === limit ) {
return EMPTY _BUFFER ;
}
var buffer = new ArrayBuffer ( limit - offset ) ;
new Uint8Array ( buffer ) . set ( new Uint8Array ( this . buffer ) . subarray ( offset , limit ) , 0 ) ;
return buffer ;
} ;
/ * *
* Returns a raw buffer compacted to contain this ByteBuffer ' s contents . Contents are the bytes between
* { @ link ByteBuffer # offset } and { @ link ByteBuffer # limit } . Will transparently { @ link ByteBuffer # flip } this
* ByteBuffer if ` offset > limit ` but the actual offsets remain untouched . This is an alias of
* { @ link ByteBuffer # toBuffer } .
* @ function
* @ param { boolean = } forceCopy If ` true ` returns a copy , otherwise returns a view referencing the same memory .
* Defaults to ` false `
* @ returns { ! ArrayBuffer } Contents as an ArrayBuffer
* @ expose
* /
ByteBufferPrototype . toArrayBuffer = ByteBufferPrototype . toBuffer ;
/ * *
* Converts the ByteBuffer ' s contents to a string .
* @ param { string = } encoding Output encoding . Returns an informative string representation if omitted but also allows
* direct conversion to "utf8" , "hex" , "base64" and "binary" encoding . "debug" returns a hex representation with
* highlighted offsets .
* @ param { number = } begin Offset to begin at , defaults to { @ link ByteBuffer # offset }
* @ param { number = } end Offset to end at , defaults to { @ link ByteBuffer # limit }
* @ returns { string } String representation
* @ throws { Error } If ` encoding ` is invalid
* @ expose
* /
ByteBufferPrototype . toString = function ( encoding , begin , end ) {
if ( typeof encoding === 'undefined' )
return "ByteBufferAB(offset=" + this . offset + ",markedOffset=" + this . markedOffset + ",limit=" + this . limit + ",capacity=" + this . capacity ( ) + ")" ;
if ( typeof encoding === 'number' )
encoding = "utf8" ,
begin = encoding ,
end = begin ;
switch ( encoding ) {
case "utf8" :
return this . toUTF8 ( begin , end ) ;
case "base64" :
return this . toBase64 ( begin , end ) ;
case "hex" :
return this . toHex ( begin , end ) ;
case "binary" :
return this . toBinary ( begin , end ) ;
case "debug" :
return this . toDebug ( ) ;
case "columns" :
return this . toColumns ( ) ;
default :
throw Error ( "Unsupported encoding: " + encoding ) ;
}
} ;
// lxiv-embeddable
/ * *
* lxiv - embeddable ( c ) 2014 Daniel Wirtz < dcode @ dcode . io >
* Released under the Apache License , Version 2.0
* see : https : //github.com/dcodeIO/lxiv for details
* /
var lxiv = function ( ) {
"use strict" ;
/ * *
* lxiv namespace .
* @ type { ! Object . < string , * > }
* @ exports lxiv
* /
var lxiv = { } ;
/ * *
* Character codes for output .
* @ type { ! Array . < number > }
* @ inner
* /
var aout = [
65 , 66 , 67 , 68 , 69 , 70 , 71 , 72 , 73 , 74 , 75 , 76 , 77 , 78 , 79 , 80 ,
81 , 82 , 83 , 84 , 85 , 86 , 87 , 88 , 89 , 90 , 97 , 98 , 99 , 100 , 101 , 102 ,
103 , 104 , 105 , 106 , 107 , 108 , 109 , 110 , 111 , 112 , 113 , 114 , 115 , 116 , 117 , 118 ,
119 , 120 , 121 , 122 , 48 , 49 , 50 , 51 , 52 , 53 , 54 , 55 , 56 , 57 , 43 , 47
] ;
/ * *
* Character codes for input .
* @ type { ! Array . < number > }
* @ inner
* /
var ain = [ ] ;
for ( var i = 0 , k = aout . length ; i < k ; ++ i )
ain [ aout [ i ] ] = i ;
/ * *
* Encodes bytes to base64 char codes .
* @ param { ! function ( ) : number | null } src Bytes source as a function returning the next byte respectively ` null ` if
* there are no more bytes left .
* @ param { ! function ( number ) } dst Characters destination as a function successively called with each encoded char
* code .
* /
lxiv . encode = function ( src , dst ) {
var b , t ;
while ( ( b = src ( ) ) !== null ) {
dst ( aout [ ( b >> 2 ) & 0x3f ] ) ;
t = ( b & 0x3 ) << 4 ;
if ( ( b = src ( ) ) !== null ) {
t |= ( b >> 4 ) & 0xf ;
dst ( aout [ ( t | ( ( b >> 4 ) & 0xf ) ) & 0x3f ] ) ;
t = ( b & 0xf ) << 2 ;
if ( ( b = src ( ) ) !== null )
dst ( aout [ ( t | ( ( b >> 6 ) & 0x3 ) ) & 0x3f ] ) ,
dst ( aout [ b & 0x3f ] ) ;
else
dst ( aout [ t & 0x3f ] ) ,
dst ( 61 ) ;
} else
dst ( aout [ t & 0x3f ] ) ,
dst ( 61 ) ,
dst ( 61 ) ;
}
} ;
/ * *
* Decodes base64 char codes to bytes .
* @ param { ! function ( ) : number | null } src Characters source as a function returning the next char code respectively
* ` null ` if there are no more characters left .
* @ param { ! function ( number ) } dst Bytes destination as a function successively called with the next byte .
* @ throws { Error } If a character code is invalid
* /
lxiv . decode = function ( src , dst ) {
var c , t1 , t2 ;
function fail ( c ) {
throw Error ( "Illegal character code: " + c ) ;
}
while ( ( c = src ( ) ) !== null ) {
t1 = ain [ c ] ;
if ( typeof t1 === 'undefined' ) fail ( c ) ;
if ( ( c = src ( ) ) !== null ) {
t2 = ain [ c ] ;
if ( typeof t2 === 'undefined' ) fail ( c ) ;
dst ( ( t1 << 2 ) >>> 0 | ( t2 & 0x30 ) >> 4 ) ;
if ( ( c = src ( ) ) !== null ) {
t1 = ain [ c ] ;
if ( typeof t1 === 'undefined' )
if ( c === 61 ) break ; else fail ( c ) ;
dst ( ( ( t2 & 0xf ) << 4 ) >>> 0 | ( t1 & 0x3c ) >> 2 ) ;
if ( ( c = src ( ) ) !== null ) {
t2 = ain [ c ] ;
if ( typeof t2 === 'undefined' )
if ( c === 61 ) break ; else fail ( c ) ;
dst ( ( ( t1 & 0x3 ) << 6 ) >>> 0 | t2 ) ;
}
}
}
}
} ;
/ * *
* Tests if a string is valid base64 .
* @ param { string } str String to test
* @ returns { boolean } ` true ` if valid , otherwise ` false `
* /
lxiv . test = function ( str ) {
return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/ . test ( str ) ;
} ;
return lxiv ;
} ( ) ;
// encodings/base64
/ * *
* Encodes this ByteBuffer ' s contents to a base64 encoded string .
* @ param { number = } begin Offset to begin at , defaults to { @ link ByteBuffer # offset } .
* @ param { number = } end Offset to end at , defaults to { @ link ByteBuffer # limit } .
* @ returns { string } Base64 encoded string
* @ expose
* /
ByteBufferPrototype . toBase64 = function ( begin , end ) {
if ( typeof begin === 'undefined' )
begin = this . offset ;
if ( typeof end === 'undefined' )
end = this . limit ;
if ( ! this . noAssert ) {
if ( typeof begin !== 'number' || begin % 1 !== 0 )
throw TypeError ( "Illegal begin: Not an integer" ) ;
begin >>>= 0 ;
if ( typeof end !== 'number' || end % 1 !== 0 )
throw TypeError ( "Illegal end: Not an integer" ) ;
end >>>= 0 ;
if ( begin < 0 || begin > end || end > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + begin + " <= " + end + " <= " + this . buffer . byteLength ) ;
}
var sd ; lxiv . encode ( function ( ) {
return begin < end ? this . view . getUint8 ( begin ++ ) : null ;
} . bind ( this ) , sd = stringDestination ( ) ) ;
return sd ( ) ;
} ;
/ * *
* Decodes a base64 encoded string to a ByteBuffer .
* @ param { string } str String to decode
* @ param { boolean = } littleEndian Whether to use little or big endian byte order . Defaults to
* { @ link ByteBuffer . DEFAULT _ENDIAN } .
* @ param { boolean = } noAssert Whether to skip assertions of offsets and values . Defaults to
* { @ link ByteBuffer . DEFAULT _NOASSERT } .
* @ returns { ! ByteBuffer } ByteBuffer
* @ expose
* /
ByteBuffer . fromBase64 = function ( str , littleEndian , noAssert ) {
if ( ! noAssert ) {
if ( typeof str !== 'string' )
throw TypeError ( "Illegal str: Not a string" ) ;
if ( str . length % 4 !== 0 )
throw TypeError ( "Illegal str: Length not a multiple of 4" ) ;
}
var bb = new ByteBuffer ( str . length / 4 * 3 , littleEndian , noAssert ) ,
i = 0 ;
lxiv . decode ( stringSource ( str ) , function ( b ) {
bb . view . setUint8 ( i ++ , b ) ;
} ) ;
bb . limit = i ;
return bb ;
} ;
/ * *
* Encodes a binary string to base64 like ` window.btoa ` does .
* @ param { string } str Binary string
* @ returns { string } Base64 encoded string
* @ see https : //developer.mozilla.org/en-US/docs/Web/API/Window.btoa
* @ expose
* /
ByteBuffer . btoa = function ( str ) {
return ByteBuffer . fromBinary ( str ) . toBase64 ( ) ;
} ;
/ * *
* Decodes a base64 encoded string to binary like ` window.atob ` does .
* @ param { string } b64 Base64 encoded string
* @ returns { string } Binary string
* @ see https : //developer.mozilla.org/en-US/docs/Web/API/Window.atob
* @ expose
* /
ByteBuffer . atob = function ( b64 ) {
return ByteBuffer . fromBase64 ( b64 ) . toBinary ( ) ;
} ;
// encodings/binary
/ * *
* Encodes this ByteBuffer to a binary encoded string , that is using only characters 0x00 - 0xFF as bytes .
* @ param { number = } begin Offset to begin at . Defaults to { @ link ByteBuffer # offset } .
* @ param { number = } end Offset to end at . Defaults to { @ link ByteBuffer # limit } .
* @ returns { string } Binary encoded string
* @ throws { RangeError } If ` offset > limit `
* @ expose
* /
ByteBufferPrototype . toBinary = function ( begin , end ) {
begin = typeof begin === 'undefined' ? this . offset : begin ;
end = typeof end === 'undefined' ? this . limit : end ;
if ( ! this . noAssert ) {
if ( typeof begin !== 'number' || begin % 1 !== 0 )
throw TypeError ( "Illegal begin: Not an integer" ) ;
begin >>>= 0 ;
if ( typeof end !== 'number' || end % 1 !== 0 )
throw TypeError ( "Illegal end: Not an integer" ) ;
end >>>= 0 ;
if ( begin < 0 || begin > end || end > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + begin + " <= " + end + " <= " + this . buffer . byteLength ) ;
}
if ( begin === end )
return "" ;
var cc = [ ] , pt = [ ] ;
while ( begin < end ) {
cc . push ( this . view . getUint8 ( begin ++ ) ) ;
if ( cc . length >= 1024 )
pt . push ( String . fromCharCode . apply ( String , cc ) ) ,
cc = [ ] ;
}
return pt . join ( '' ) + String . fromCharCode . apply ( String , cc ) ;
} ;
/ * *
* Decodes a binary encoded string , that is using only characters 0x00 - 0xFF as bytes , to a ByteBuffer .
* @ param { string } str String to decode
* @ param { boolean = } littleEndian Whether to use little or big endian byte order . Defaults to
* { @ link ByteBuffer . DEFAULT _ENDIAN } .
* @ param { boolean = } noAssert Whether to skip assertions of offsets and values . Defaults to
* { @ link ByteBuffer . DEFAULT _NOASSERT } .
* @ returns { ! ByteBuffer } ByteBuffer
* @ expose
* /
ByteBuffer . fromBinary = function ( str , littleEndian , noAssert ) {
if ( ! noAssert ) {
if ( typeof str !== 'string' )
throw TypeError ( "Illegal str: Not a string" ) ;
}
var i = 0 , k = str . length , charCode ,
bb = new ByteBuffer ( k , littleEndian , noAssert ) ;
while ( i < k ) {
charCode = str . charCodeAt ( i ) ;
if ( ! noAssert && charCode > 255 )
throw RangeError ( "Illegal charCode at " + i + ": 0 <= " + charCode + " <= 255" ) ;
bb . view . setUint8 ( i ++ , charCode ) ;
}
bb . limit = k ;
return bb ;
} ;
// encodings/debug
/ * *
* Encodes this ByteBuffer to a hex encoded string with marked offsets . Offset symbols are :
* * ` < ` : offset ,
* * ` ' ` : markedOffset ,
* * ` > ` : limit ,
* * ` | ` : offset and limit ,
* * ` [ ` : offset and markedOffset ,
* * ` ] ` : markedOffset and limit ,
* * ` ! ` : offset , markedOffset and limit
* @ param { boolean = } columns If ` true ` returns two columns hex + ascii , defaults to ` false `
* @ returns { string | ! Array . < string > } Debug string or array of lines if ` asArray = true `
* @ expose
* @ example ` >00'01 02<03 ` contains four bytes with ` limit=0, markedOffset=1, offset=3 `
* @ example ` 00[01 02 03> ` contains four bytes with ` offset=markedOffset=1, limit=4 `
* @ example ` 00|01 02 03 ` contains four bytes with ` offset=limit=1, markedOffset=-1 `
* @ example ` | ` contains zero bytes with ` offset=limit=0, markedOffset=-1 `
* /
ByteBufferPrototype . toDebug = function ( columns ) {
var i = - 1 ,
k = this . buffer . byteLength ,
b ,
hex = "" ,
asc = "" ,
out = "" ;
while ( i < k ) {
if ( i !== - 1 ) {
b = this . view . getUint8 ( i ) ;
if ( b < 0x10 ) hex += "0" + b . toString ( 16 ) . toUpperCase ( ) ;
else hex += b . toString ( 16 ) . toUpperCase ( ) ;
if ( columns ) {
asc += b > 32 && b < 127 ? String . fromCharCode ( b ) : '.' ;
}
}
++ i ;
if ( columns ) {
if ( i > 0 && i % 16 === 0 && i !== k ) {
while ( hex . length < 3 * 16 + 3 ) hex += " " ;
out += hex + asc + "\n" ;
hex = asc = "" ;
}
}
if ( i === this . offset && i === this . limit )
hex += i === this . markedOffset ? "!" : "|" ;
else if ( i === this . offset )
hex += i === this . markedOffset ? "[" : "<" ;
else if ( i === this . limit )
hex += i === this . markedOffset ? "]" : ">" ;
else
hex += i === this . markedOffset ? "'" : ( columns || ( i !== 0 && i !== k ) ? " " : "" ) ;
}
if ( columns && hex !== " " ) {
while ( hex . length < 3 * 16 + 3 ) hex += " " ;
out += hex + asc + "\n" ;
}
return columns ? out : hex ;
} ;
/ * *
* Decodes a hex encoded string with marked offsets to a ByteBuffer .
* @ param { string } str Debug string to decode ( not be generated with ` columns = true ` )
* @ param { boolean = } littleEndian Whether to use little or big endian byte order . Defaults to
* { @ link ByteBuffer . DEFAULT _ENDIAN } .
* @ param { boolean = } noAssert Whether to skip assertions of offsets and values . Defaults to
* { @ link ByteBuffer . DEFAULT _NOASSERT } .
* @ returns { ! ByteBuffer } ByteBuffer
* @ expose
* @ see ByteBuffer # toDebug
* /
ByteBuffer . fromDebug = function ( str , littleEndian , noAssert ) {
var k = str . length ,
bb = new ByteBuffer ( ( ( k + 1 ) / 3 ) | 0 , littleEndian , noAssert ) ;
var i = 0 , j = 0 , ch , b ,
rs = false , // Require symbol next
ho = false , hm = false , hl = false , // Already has offset, markedOffset, limit?
fail = false ;
while ( i < k ) {
switch ( ch = str . charAt ( i ++ ) ) {
case '!' :
if ( ! noAssert ) {
if ( ho || hm || hl ) {
fail = true ; break ;
}
ho = hm = hl = true ;
}
bb . offset = bb . markedOffset = bb . limit = j ;
rs = false ;
break ;
case '|' :
if ( ! noAssert ) {
if ( ho || hl ) {
fail = true ; break ;
}
ho = hl = true ;
}
bb . offset = bb . limit = j ;
rs = false ;
break ;
case '[' :
if ( ! noAssert ) {
if ( ho || hm ) {
fail = true ; break ;
}
ho = hm = true ;
}
bb . offset = bb . markedOffset = j ;
rs = false ;
break ;
case '<' :
if ( ! noAssert ) {
if ( ho ) {
fail = true ; break ;
}
ho = true ;
}
bb . offset = j ;
rs = false ;
break ;
case ']' :
if ( ! noAssert ) {
if ( hl || hm ) {
fail = true ; break ;
}
hl = hm = true ;
}
bb . limit = bb . markedOffset = j ;
rs = false ;
break ;
case '>' :
if ( ! noAssert ) {
if ( hl ) {
fail = true ; break ;
}
hl = true ;
}
bb . limit = j ;
rs = false ;
break ;
case "'" :
if ( ! noAssert ) {
if ( hm ) {
fail = true ; break ;
}
hm = true ;
}
bb . markedOffset = j ;
rs = false ;
break ;
case ' ' :
rs = false ;
break ;
default :
if ( ! noAssert ) {
if ( rs ) {
fail = true ; break ;
}
}
b = parseInt ( ch + str . charAt ( i ++ ) , 16 ) ;
if ( ! noAssert ) {
if ( isNaN ( b ) || b < 0 || b > 255 )
throw TypeError ( "Illegal str: Not a debug encoded string" ) ;
}
bb . view . setUint8 ( j ++ , b ) ;
rs = true ;
}
if ( fail )
throw TypeError ( "Illegal str: Invalid symbol at " + i ) ;
}
if ( ! noAssert ) {
if ( ! ho || ! hl )
throw TypeError ( "Illegal str: Missing offset or limit" ) ;
if ( j < bb . buffer . byteLength )
throw TypeError ( "Illegal str: Not a debug encoded string (is it hex?) " + j + " < " + k ) ;
}
return bb ;
} ;
// encodings/hex
/ * *
* Encodes this ByteBuffer ' s contents to a hex encoded string .
* @ param { number = } begin Offset to begin at . Defaults to { @ link ByteBuffer # offset } .
* @ param { number = } end Offset to end at . Defaults to { @ link ByteBuffer # limit } .
* @ returns { string } Hex encoded string
* @ expose
* /
ByteBufferPrototype . toHex = function ( begin , end ) {
begin = typeof begin === 'undefined' ? this . offset : begin ;
end = typeof end === 'undefined' ? this . limit : end ;
if ( ! this . noAssert ) {
if ( typeof begin !== 'number' || begin % 1 !== 0 )
throw TypeError ( "Illegal begin: Not an integer" ) ;
begin >>>= 0 ;
if ( typeof end !== 'number' || end % 1 !== 0 )
throw TypeError ( "Illegal end: Not an integer" ) ;
end >>>= 0 ;
if ( begin < 0 || begin > end || end > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + begin + " <= " + end + " <= " + this . buffer . byteLength ) ;
}
var out = new Array ( end - begin ) ,
b ;
while ( begin < end ) {
b = this . view . getUint8 ( begin ++ ) ;
if ( b < 0x10 )
out . push ( "0" , b . toString ( 16 ) ) ;
else out . push ( b . toString ( 16 ) ) ;
}
return out . join ( '' ) ;
} ;
/ * *
* Decodes a hex encoded string to a ByteBuffer .
* @ param { string } str String to decode
* @ param { boolean = } littleEndian Whether to use little or big endian byte order . Defaults to
* { @ link ByteBuffer . DEFAULT _ENDIAN } .
* @ param { boolean = } noAssert Whether to skip assertions of offsets and values . Defaults to
* { @ link ByteBuffer . DEFAULT _NOASSERT } .
* @ returns { ! ByteBuffer } ByteBuffer
* @ expose
* /
ByteBuffer . fromHex = function ( str , littleEndian , noAssert ) {
if ( ! noAssert ) {
if ( typeof str !== 'string' )
throw TypeError ( "Illegal str: Not a string" ) ;
if ( str . length % 2 !== 0 )
throw TypeError ( "Illegal str: Length not a multiple of 2" ) ;
}
var k = str . length ,
bb = new ByteBuffer ( ( k / 2 ) | 0 , littleEndian ) ,
b ;
for ( var i = 0 , j = 0 ; i < k ; i += 2 ) {
b = parseInt ( str . substring ( i , i + 2 ) , 16 ) ;
if ( ! noAssert )
if ( ! isFinite ( b ) || b < 0 || b > 255 )
throw TypeError ( "Illegal str: Contains non-hex characters" ) ;
bb . view . setUint8 ( j ++ , b ) ;
}
bb . limit = j ;
return bb ;
} ;
// utfx-embeddable
/ * *
* utfx - embeddable ( c ) 2014 Daniel Wirtz < dcode @ dcode . io >
* Released under the Apache License , Version 2.0
* see : https : //github.com/dcodeIO/utfx for details
* /
var utfx = function ( ) {
"use strict" ;
/ * *
* utfx namespace .
* @ inner
* @ type { ! Object . < string , * > }
* /
var utfx = { } ;
/ * *
* Maximum valid code point .
* @ type { number }
* @ const
* /
utfx . MAX _CODEPOINT = 0x10FFFF ;
/ * *
* Encodes UTF8 code points to UTF8 bytes .
* @ param { ( ! function ( ) : number | null ) | number } src Code points source , either as a function returning the next code point
* respectively ` null ` if there are no more code points left or a single numeric code point .
* @ param { ! function ( number ) } dst Bytes destination as a function successively called with the next byte
* /
utfx . encodeUTF8 = function ( src , dst ) {
var cp = null ;
if ( typeof src === 'number' )
cp = src ,
src = function ( ) { return null ; } ;
while ( cp !== null || ( cp = src ( ) ) !== null ) {
if ( cp < 0x80 )
dst ( cp & 0x7F ) ;
else if ( cp < 0x800 )
dst ( ( ( cp >> 6 ) & 0x1F ) | 0xC0 ) ,
dst ( ( cp & 0x3F ) | 0x80 ) ;
else if ( cp < 0x10000 )
dst ( ( ( cp >> 12 ) & 0x0F ) | 0xE0 ) ,
dst ( ( ( cp >> 6 ) & 0x3F ) | 0x80 ) ,
dst ( ( cp & 0x3F ) | 0x80 ) ;
else
dst ( ( ( cp >> 18 ) & 0x07 ) | 0xF0 ) ,
dst ( ( ( cp >> 12 ) & 0x3F ) | 0x80 ) ,
dst ( ( ( cp >> 6 ) & 0x3F ) | 0x80 ) ,
dst ( ( cp & 0x3F ) | 0x80 ) ;
cp = null ;
}
} ;
/ * *
* Decodes UTF8 bytes to UTF8 code points .
* @ param { ! function ( ) : number | null } src Bytes source as a function returning the next byte respectively ` null ` if there
* are no more bytes left .
* @ param { ! function ( number ) } dst Code points destination as a function successively called with each decoded code point .
* @ throws { RangeError } If a starting byte is invalid in UTF8
* @ throws { Error } If the last sequence is truncated . Has an array property ` bytes ` holding the
* remaining bytes .
* /
utfx . decodeUTF8 = function ( src , dst ) {
var a , b , c , d , fail = function ( b ) {
b = b . slice ( 0 , b . indexOf ( null ) ) ;
var err = Error ( b . toString ( ) ) ;
err . name = "TruncatedError" ;
err [ 'bytes' ] = b ;
throw err ;
} ;
while ( ( a = src ( ) ) !== null ) {
if ( ( a & 0x80 ) === 0 )
dst ( a ) ;
else if ( ( a & 0xE0 ) === 0xC0 )
( ( b = src ( ) ) === null ) && fail ( [ a , b ] ) ,
dst ( ( ( a & 0x1F ) << 6 ) | ( b & 0x3F ) ) ;
else if ( ( a & 0xF0 ) === 0xE0 )
( ( b = src ( ) ) === null || ( c = src ( ) ) === null ) && fail ( [ a , b , c ] ) ,
dst ( ( ( a & 0x0F ) << 12 ) | ( ( b & 0x3F ) << 6 ) | ( c & 0x3F ) ) ;
else if ( ( a & 0xF8 ) === 0xF0 )
( ( b = src ( ) ) === null || ( c = src ( ) ) === null || ( d = src ( ) ) === null ) && fail ( [ a , b , c , d ] ) ,
dst ( ( ( a & 0x07 ) << 18 ) | ( ( b & 0x3F ) << 12 ) | ( ( c & 0x3F ) << 6 ) | ( d & 0x3F ) ) ;
else throw RangeError ( "Illegal starting byte: " + a ) ;
}
} ;
/ * *
* Converts UTF16 characters to UTF8 code points .
* @ param { ! function ( ) : number | null } src Characters source as a function returning the next char code respectively
* ` null ` if there are no more characters left .
* @ param { ! function ( number ) } dst Code points destination as a function successively called with each converted code
* point .
* /
utfx . UTF16toUTF8 = function ( src , dst ) {
var c1 , c2 = null ;
while ( true ) {
if ( ( c1 = c2 !== null ? c2 : src ( ) ) === null )
break ;
if ( c1 >= 0xD800 && c1 <= 0xDFFF ) {
if ( ( c2 = src ( ) ) !== null ) {
if ( c2 >= 0xDC00 && c2 <= 0xDFFF ) {
dst ( ( c1 - 0xD800 ) * 0x400 + c2 - 0xDC00 + 0x10000 ) ;
c2 = null ; continue ;
}
}
}
dst ( c1 ) ;
}
if ( c2 !== null ) dst ( c2 ) ;
} ;
/ * *
* Converts UTF8 code points to UTF16 characters .
* @ param { ( ! function ( ) : number | null ) | number } src Code points source , either as a function returning the next code point
* respectively ` null ` if there are no more code points left or a single numeric code point .
* @ param { ! function ( number ) } dst Characters destination as a function successively called with each converted char code .
* @ throws { RangeError } If a code point is out of range
* /
utfx . UTF8toUTF16 = function ( src , dst ) {
var cp = null ;
if ( typeof src === 'number' )
cp = src , src = function ( ) { return null ; } ;
while ( cp !== null || ( cp = src ( ) ) !== null ) {
if ( cp <= 0xFFFF )
dst ( cp ) ;
else
cp -= 0x10000 ,
dst ( ( cp >> 10 ) + 0xD800 ) ,
dst ( ( cp % 0x400 ) + 0xDC00 ) ;
cp = null ;
}
} ;
/ * *
* Converts and encodes UTF16 characters to UTF8 bytes .
* @ param { ! function ( ) : number | null } src Characters source as a function returning the next char code respectively ` null `
* if there are no more characters left .
* @ param { ! function ( number ) } dst Bytes destination as a function successively called with the next byte .
* /
utfx . encodeUTF16toUTF8 = function ( src , dst ) {
utfx . UTF16toUTF8 ( src , function ( cp ) {
utfx . encodeUTF8 ( cp , dst ) ;
} ) ;
} ;
/ * *
* Decodes and converts UTF8 bytes to UTF16 characters .
* @ param { ! function ( ) : number | null } src Bytes source as a function returning the next byte respectively ` null ` if there
* are no more bytes left .
* @ param { ! function ( number ) } dst Characters destination as a function successively called with each converted char code .
* @ throws { RangeError } If a starting byte is invalid in UTF8
* @ throws { Error } If the last sequence is truncated . Has an array property ` bytes ` holding the remaining bytes .
* /
utfx . decodeUTF8toUTF16 = function ( src , dst ) {
utfx . decodeUTF8 ( src , function ( cp ) {
utfx . UTF8toUTF16 ( cp , dst ) ;
} ) ;
} ;
/ * *
* Calculates the byte length of an UTF8 code point .
* @ param { number } cp UTF8 code point
* @ returns { number } Byte length
* /
utfx . calculateCodePoint = function ( cp ) {
return ( cp < 0x80 ) ? 1 : ( cp < 0x800 ) ? 2 : ( cp < 0x10000 ) ? 3 : 4 ;
} ;
/ * *
* Calculates the number of UTF8 bytes required to store UTF8 code points .
* @ param { ( ! function ( ) : number | null ) } src Code points source as a function returning the next code point respectively
* ` null ` if there are no more code points left .
* @ returns { number } The number of UTF8 bytes required
* /
utfx . calculateUTF8 = function ( src ) {
var cp , l = 0 ;
while ( ( cp = src ( ) ) !== null )
l += utfx . calculateCodePoint ( cp ) ;
return l ;
} ;
/ * *
* Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes .
* @ param { ( ! function ( ) : number | null ) } src Characters source as a function returning the next char code respectively
* ` null ` if there are no more characters left .
* @ returns { ! Array . < number > } The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1.
* /
utfx . calculateUTF16asUTF8 = function ( src ) {
var n = 0 , l = 0 ;
utfx . UTF16toUTF8 ( src , function ( cp ) {
++ n ; l += utfx . calculateCodePoint ( cp ) ;
} ) ;
return [ n , l ] ;
} ;
return utfx ;
} ( ) ;
// encodings/utf8
/ * *
* Encodes this ByteBuffer ' s contents between { @ link ByteBuffer # offset } and { @ link ByteBuffer # limit } to an UTF8 encoded
* string .
* @ returns { string } Hex encoded string
* @ throws { RangeError } If ` offset > limit `
* @ expose
* /
ByteBufferPrototype . toUTF8 = function ( begin , end ) {
if ( typeof begin === 'undefined' ) begin = this . offset ;
if ( typeof end === 'undefined' ) end = this . limit ;
if ( ! this . noAssert ) {
if ( typeof begin !== 'number' || begin % 1 !== 0 )
throw TypeError ( "Illegal begin: Not an integer" ) ;
begin >>>= 0 ;
if ( typeof end !== 'number' || end % 1 !== 0 )
throw TypeError ( "Illegal end: Not an integer" ) ;
end >>>= 0 ;
if ( begin < 0 || begin > end || end > this . buffer . byteLength )
throw RangeError ( "Illegal range: 0 <= " + begin + " <= " + end + " <= " + this . buffer . byteLength ) ;
}
var sd ; try {
utfx . decodeUTF8toUTF16 ( function ( ) {
return begin < end ? this . view . getUint8 ( begin ++ ) : null ;
} . bind ( this ) , sd = stringDestination ( ) ) ;
} catch ( e ) {
if ( begin !== end )
throw RangeError ( "Illegal range: Truncated data, " + begin + " != " + end ) ;
}
return sd ( ) ;
} ;
/ * *
* Decodes an UTF8 encoded string to a ByteBuffer .
* @ param { string } str String to decode
* @ param { boolean = } littleEndian Whether to use little or big endian byte order . Defaults to
* { @ link ByteBuffer . DEFAULT _ENDIAN } .
* @ param { boolean = } noAssert Whether to skip assertions of offsets and values . Defaults to
* { @ link ByteBuffer . DEFAULT _NOASSERT } .
* @ returns { ! ByteBuffer } ByteBuffer
* @ expose
* /
ByteBuffer . fromUTF8 = function ( str , littleEndian , noAssert ) {
if ( ! noAssert )
if ( typeof str !== 'string' )
throw TypeError ( "Illegal str: Not a string" ) ;
var bb = new ByteBuffer ( utfx . calculateUTF16asUTF8 ( stringSource ( str ) , true ) [ 1 ] , littleEndian , noAssert ) ,
i = 0 ;
utfx . encodeUTF16toUTF8 ( stringSource ( str ) , function ( b ) {
bb . view . setUint8 ( i ++ , b ) ;
} ) ;
bb . limit = i ;
return bb ;
} ;
return ByteBuffer ;
}
/* CommonJS */ if ( typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports )
module [ 'exports' ] = ( function ( ) {
var Long ; try { Long = require ( "long" ) ; } catch ( e ) { }
return loadByteBuffer ( Long ) ;
} ) ( ) ;
/* AMD */ else if ( typeof define === 'function' && define [ "amd" ] )
define ( "ByteBuffer" , [ "Long" ] , function ( Long ) { return loadByteBuffer ( Long ) ; } ) ;
/* Global */ else
( global [ "dcodeIO" ] = global [ "dcodeIO" ] || { } ) [ "ByteBuffer" ] = loadByteBuffer ( global [ "dcodeIO" ] [ "Long" ] ) ;
} ) ( this ) ;
/ *
Copyright 2013 Daniel Wirtz < dcode @ dcode . io >
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 .
* /
/ * *
* @ license ProtoBuf . js ( c ) 2013 Daniel Wirtz < dcode @ dcode . io >
* Released under the Apache License , Version 2.0
* see : https : //github.com/dcodeIO/ProtoBuf.js for details
* /
( function ( global ) {
"use strict" ;
function init ( ByteBuffer ) {
/ * *
* The ProtoBuf namespace .
* @ exports ProtoBuf
* @ namespace
* @ expose
* /
var ProtoBuf = { } ;
/ * *
* ProtoBuf . js version .
* @ type { string }
* @ const
* @ expose
* /
ProtoBuf . VERSION = "3.8.0" ;
/ * *
* Wire types .
* @ type { Object . < string , number > }
* @ const
* @ expose
* /
ProtoBuf . WIRE _TYPES = { } ;
/ * *
* Varint wire type .
* @ type { number }
* @ expose
* /
ProtoBuf . WIRE _TYPES . VARINT = 0 ;
/ * *
* Fixed 64 bits wire type .
* @ type { number }
* @ const
* @ expose
* /
ProtoBuf . WIRE _TYPES . BITS64 = 1 ;
/ * *
* Length delimited wire type .
* @ type { number }
* @ const
* @ expose
* /
ProtoBuf . WIRE _TYPES . LDELIM = 2 ;
/ * *
* Start group wire type .
* @ type { number }
* @ const
* @ expose
* /
ProtoBuf . WIRE _TYPES . STARTGROUP = 3 ;
/ * *
* End group wire type .
* @ type { number }
* @ const
* @ expose
* /
ProtoBuf . WIRE _TYPES . ENDGROUP = 4 ;
/ * *
* Fixed 32 bits wire type .
* @ type { number }
* @ const
* @ expose
* /
ProtoBuf . WIRE _TYPES . BITS32 = 5 ;
/ * *
* Packable wire types .
* @ type { ! Array . < number > }
* @ const
* @ expose
* /
ProtoBuf . PACKABLE _WIRE _TYPES = [
ProtoBuf . WIRE _TYPES . VARINT ,
ProtoBuf . WIRE _TYPES . BITS64 ,
ProtoBuf . WIRE _TYPES . BITS32
] ;
/ * *
* Types .
* @ dict
* @ type { Object . < string , { name : string , wireType : number } > }
* @ const
* @ expose
* /
ProtoBuf . TYPES = {
// According to the protobuf spec.
"int32" : {
name : "int32" ,
wireType : ProtoBuf . WIRE _TYPES . VARINT
} ,
"uint32" : {
name : "uint32" ,
wireType : ProtoBuf . WIRE _TYPES . VARINT
} ,
"sint32" : {
name : "sint32" ,
wireType : ProtoBuf . WIRE _TYPES . VARINT
} ,
"int64" : {
name : "int64" ,
wireType : ProtoBuf . WIRE _TYPES . VARINT
} ,
"uint64" : {
name : "uint64" ,
wireType : ProtoBuf . WIRE _TYPES . VARINT
} ,
"sint64" : {
name : "sint64" ,
wireType : ProtoBuf . WIRE _TYPES . VARINT
} ,
"bool" : {
name : "bool" ,
wireType : ProtoBuf . WIRE _TYPES . VARINT
} ,
"double" : {
name : "double" ,
wireType : ProtoBuf . WIRE _TYPES . BITS64
} ,
"string" : {
name : "string" ,
wireType : ProtoBuf . WIRE _TYPES . LDELIM
} ,
"bytes" : {
name : "bytes" ,
wireType : ProtoBuf . WIRE _TYPES . LDELIM
} ,
"fixed32" : {
name : "fixed32" ,
wireType : ProtoBuf . WIRE _TYPES . BITS32
} ,
"sfixed32" : {
name : "sfixed32" ,
wireType : ProtoBuf . WIRE _TYPES . BITS32
} ,
"fixed64" : {
name : "fixed64" ,
wireType : ProtoBuf . WIRE _TYPES . BITS64
} ,
"sfixed64" : {
name : "sfixed64" ,
wireType : ProtoBuf . WIRE _TYPES . BITS64
} ,
"float" : {
name : "float" ,
wireType : ProtoBuf . WIRE _TYPES . BITS32
} ,
"enum" : {
name : "enum" ,
wireType : ProtoBuf . WIRE _TYPES . VARINT
} ,
"message" : {
name : "message" ,
wireType : ProtoBuf . WIRE _TYPES . LDELIM
} ,
"group" : {
name : "group" ,
wireType : ProtoBuf . WIRE _TYPES . STARTGROUP
}
} ;
/ * *
* Minimum field id .
* @ type { number }
* @ const
* @ expose
* /
ProtoBuf . ID _MIN = 1 ;
/ * *
* Maximum field id .
* @ type { number }
* @ const
* @ expose
* /
ProtoBuf . ID _MAX = 0x1FFFFFFF ;
/ * *
* @ type { ! function ( new : ByteBuffer , ... [ * ] ) }
* @ expose
* /
ProtoBuf . ByteBuffer = ByteBuffer ;
/ * *
* @ type { ? function ( new : Long , ... [ * ] ) }
* @ expose
* /
ProtoBuf . Long = ByteBuffer . Long || null ;
/ * *
* If set to ` true ` , field names will be converted from underscore notation to camel case . Defaults to ` false ` .
* Must be set prior to parsing .
* @ type { boolean }
* @ expose
* /
ProtoBuf . convertFieldsToCamelCase = false ;
/ * *
* By default , messages are populated with ( setX , set _x ) accessors for each field . This can be disabled by
* setting this to ` false ` prior to building messages .
* @ type { boolean }
* @ expose
* /
ProtoBuf . populateAccessors = true ;
/ * *
* @ alias ProtoBuf . Util
* @ expose
* /
ProtoBuf . Util = ( function ( ) {
"use strict" ;
// Object.create polyfill
// ref: https://developer.mozilla.org/de/docs/JavaScript/Reference/Global_Objects/Object/create
if ( ! Object . create )
/** @expose */
Object . create = function ( o ) {
if ( arguments . length > 1 )
throw Error ( 'Object.create polyfill only accepts the first parameter.' ) ;
function F ( ) { }
F . prototype = o ;
return new F ( ) ;
} ;
/ * *
* ProtoBuf utilities .
* @ exports ProtoBuf . Util
* @ namespace
* /
var Util = { } ;
/ * *
* Flag if running in node ( fs is available ) or not .
* @ type { boolean }
* @ const
* @ expose
* /
Util . IS _NODE = false ;
try {
// There is no reliable way to detect node.js as an environment, so our
// best bet is to feature-detect what we actually need.
Util . IS _NODE =
typeof require === 'function' &&
typeof require ( "fs" ) . readFileSync === 'function' &&
typeof require ( "path" ) . resolve === 'function' ;
} catch ( e ) { }
/ * *
* Constructs a XMLHttpRequest object .
* @ return { XMLHttpRequest }
* @ throws { Error } If XMLHttpRequest is not supported
* @ expose
* /
Util . XHR = function ( ) {
// No dependencies please, ref: http://www.quirksmode.org/js/xmlhttp.html
var XMLHttpFactories = [
function ( ) { return new XMLHttpRequest ( ) } ,
function ( ) { return new ActiveXObject ( "Msxml2.XMLHTTP" ) } ,
function ( ) { return new ActiveXObject ( "Msxml3.XMLHTTP" ) } ,
function ( ) { return new ActiveXObject ( "Microsoft.XMLHTTP" ) }
] ;
/** @type {?XMLHttpRequest} */
var xhr = null ;
for ( var i = 0 ; i < XMLHttpFactories . length ; i ++ ) {
try { xhr = XMLHttpFactories [ i ] ( ) ; }
catch ( e ) { continue ; }
break ;
}
if ( ! xhr )
throw Error ( "XMLHttpRequest is not supported" ) ;
return xhr ;
} ;
/ * *
* Fetches a resource .
* @ param { string } path Resource path
* @ param { function ( ? string ) = } callback Callback receiving the resource ' s contents . If omitted the resource will
* be fetched synchronously . If the request failed , contents will be null .
* @ return { ? string | undefined } Resource contents if callback is omitted ( null if the request failed ) , else undefined .
* @ expose
* /
Util . fetch = function ( path , callback ) {
if ( callback && typeof callback != 'function' )
callback = null ;
if ( Util . IS _NODE ) {
if ( callback ) {
require ( "fs" ) . readFile ( path , function ( err , data ) {
if ( err )
callback ( null ) ;
else
callback ( "" + data ) ;
} ) ;
} else
try {
return require ( "fs" ) . readFileSync ( path ) ;
} catch ( e ) {
return null ;
}
} else {
var xhr = Util . XHR ( ) ;
xhr . open ( 'GET' , path , callback ? true : false ) ;
// xhr.setRequestHeader('User-Agent', 'XMLHTTP/1.0');
xhr . setRequestHeader ( 'Accept' , 'text/plain' ) ;
if ( typeof xhr . overrideMimeType === 'function' ) xhr . overrideMimeType ( 'text/plain' ) ;
if ( callback ) {
xhr . onreadystatechange = function ( ) {
if ( xhr . readyState != 4 ) return ;
if ( /* remote */ xhr . status == 200 || /* local */ ( xhr . status == 0 && typeof xhr . responseText === 'string' ) )
callback ( xhr . responseText ) ;
else
callback ( null ) ;
} ;
if ( xhr . readyState == 4 )
return ;
xhr . send ( null ) ;
} else {
xhr . send ( null ) ;
if ( /* remote */ xhr . status == 200 || /* local */ ( xhr . status == 0 && typeof xhr . responseText === 'string' ) )
return xhr . responseText ;
return null ;
}
}
} ;
/ * *
* Tests if an object is an array .
* @ function
* @ param { * } obj Object to test
* @ returns { boolean } true if it is an array , else false
* @ expose
* /
Util . isArray = Array . isArray || function ( obj ) {
return Object . prototype . toString . call ( obj ) === "[object Array]" ;
} ;
return Util ;
} ) ( ) ;
/ * *
* Language expressions .
* @ type { ! Object . < string , string | ! RegExp > }
* @ expose
* /
ProtoBuf . Lang = {
OPEN : "{" ,
CLOSE : "}" ,
OPTOPEN : "[" ,
OPTCLOSE : "]" ,
OPTEND : "," ,
EQUAL : "=" ,
END : ";" ,
STRINGOPEN : '"' ,
STRINGCLOSE : '"' ,
STRINGOPEN _SQ : "'" ,
STRINGCLOSE _SQ : "'" ,
COPTOPEN : '(' ,
COPTCLOSE : ')' ,
DELIM : /[\s\{\}=;\[\],'"\(\)]/g ,
// KEYWORD: /^(?:package|option|import|message|enum|extend|service|syntax|extensions|group)$/,
RULE : /^(?:required|optional|repeated)$/ ,
TYPE : /^(?:double|float|int32|uint32|sint32|int64|uint64|sint64|fixed32|sfixed32|fixed64|sfixed64|bool|string|bytes)$/ ,
NAME : /^[a-zA-Z_][a-zA-Z_0-9]*$/ ,
TYPEDEF : /^[a-zA-Z][a-zA-Z_0-9]*$/ ,
TYPEREF : /^(?:\.?[a-zA-Z_][a-zA-Z_0-9]*)+$/ ,
FQTYPEREF : /^(?:\.[a-zA-Z][a-zA-Z_0-9]*)+$/ ,
NUMBER : /^-?(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+|([0-9]*\.[0-9]+([Ee][+-]?[0-9]+)?))$/ ,
NUMBER _DEC : /^(?:[1-9][0-9]*|0)$/ ,
NUMBER _HEX : /^0x[0-9a-fA-F]+$/ ,
NUMBER _OCT : /^0[0-7]+$/ ,
NUMBER _FLT : /^[0-9]*\.[0-9]+([Ee][+-]?[0-9]+)?$/ ,
ID : /^(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+)$/ ,
NEGID : /^\-?(?:[1-9][0-9]*|0|0x[0-9a-fA-F]+|0[0-7]+)$/ ,
WHITESPACE : /\s/ ,
STRING : /['"]([^'"\\]*(\\.[^"\\]*)*)['"]/g ,
BOOL : /^(?:true|false)$/i
} ;
/ * *
* @ alias ProtoBuf . DotProto
* @ expose
* /
ProtoBuf . DotProto = ( function ( ProtoBuf , Lang ) {
"use strict" ;
/ * *
* Utilities to parse . proto files .
* @ exports ProtoBuf . DotProto
* @ namespace
* /
var DotProto = { } ;
/ * *
* Constructs a new Tokenizer .
* @ exports ProtoBuf . DotProto . Tokenizer
* @ class prototype tokenizer
* @ param { string } proto Proto to tokenize
* @ constructor
* /
var Tokenizer = function ( proto ) {
/ * *
* Source to parse .
* @ type { string }
* @ expose
* /
this . source = "" + proto ; // In case it's a buffer
/ * *
* Current index .
* @ type { number }
* @ expose
* /
this . index = 0 ;
/ * *
* Current line .
* @ type { number }
* @ expose
* /
this . line = 1 ;
/ * *
* Stacked values .
* @ type { Array }
* @ expose
* /
this . stack = [ ] ;
/ * *
* Whether currently reading a string or not .
* @ type { boolean }
* @ expose
* /
this . readingString = false ;
/ * *
* Whatever character ends the string . Either a single or double quote character .
* @ type { string }
* @ expose
* /
this . stringEndsWith = Lang . STRINGCLOSE ;
} ;
/ * *
* @ alias ProtoBuf . DotProto . Tokenizer . prototype
* @ inner
* /
var TokenizerPrototype = Tokenizer . prototype ;
/ * *
* Reads a string beginning at the current index .
* @ return { string } The string
* @ throws { Error } If it ' s not a valid string
* @ private
* /
TokenizerPrototype . _readString = function ( ) {
Lang . STRING . lastIndex = this . index - 1 ; // Include the open quote
var match ;
if ( ( match = Lang . STRING . exec ( this . source ) ) !== null ) {
var s = match [ 1 ] ;
this . index = Lang . STRING . lastIndex ;
this . stack . push ( this . stringEndsWith ) ;
return s ;
}
throw Error ( "Unterminated string at line " + this . line + ", index " + this . index ) ;
} ;
/ * *
* Gets the next token and advances by one .
* @ return { ? string } Token or ` null ` on EOF
* @ throws { Error } If it ' s not a valid proto file
* @ expose
* /
TokenizerPrototype . next = function ( ) {
if ( this . stack . length > 0 )
return this . stack . shift ( ) ;
if ( this . index >= this . source . length )
return null ; // No more tokens
if ( this . readingString ) {
this . readingString = false ;
return this . _readString ( ) ;
}
var repeat , last ;
do {
repeat = false ;
// Strip white spaces
while ( Lang . WHITESPACE . test ( last = this . source . charAt ( this . index ) ) ) {
this . index ++ ;
if ( last === "\n" )
this . line ++ ;
if ( this . index === this . source . length )
return null ;
}
// Strip comments
if ( this . source . charAt ( this . index ) === '/' ) {
if ( this . source . charAt ( ++ this . index ) === '/' ) { // Single line
while ( this . source . charAt ( this . index ) !== "\n" ) {
this . index ++ ;
if ( this . index == this . source . length )
return null ;
}
this . index ++ ;
this . line ++ ;
repeat = true ;
} else if ( this . source . charAt ( this . index ) === '*' ) { /* Block */
last = '' ;
while ( last + ( last = this . source . charAt ( this . index ) ) !== '*/' ) {
this . index ++ ;
if ( last === "\n" )
this . line ++ ;
if ( this . index === this . source . length )
return null ;
}
this . index ++ ;
repeat = true ;
} else
throw Error ( "Unterminated comment at line " + this . line + ": /" + this . source . charAt ( this . index ) ) ;
}
} while ( repeat ) ;
if ( this . index === this . source . length ) return null ;
// Read the next token
var end = this . index ;
Lang . DELIM . lastIndex = 0 ;
var delim = Lang . DELIM . test ( this . source . charAt ( end ) ) ;
if ( ! delim ) {
++ end ;
while ( end < this . source . length && ! Lang . DELIM . test ( this . source . charAt ( end ) ) )
end ++ ;
} else
++ end ;
var token = this . source . substring ( this . index , this . index = end ) ;
if ( token === Lang . STRINGOPEN )
this . readingString = true ,
this . stringEndsWith = Lang . STRINGCLOSE ;
else if ( token === Lang . STRINGOPEN _SQ )
this . readingString = true ,
this . stringEndsWith = Lang . STRINGCLOSE _SQ ;
return token ;
} ;
/ * *
* Peeks for the next token .
* @ return { ? string } Token or ` null ` on EOF
* @ throws { Error } If it ' s not a valid proto file
* @ expose
* /
TokenizerPrototype . peek = function ( ) {
if ( this . stack . length === 0 ) {
var token = this . next ( ) ;
if ( token === null )
return null ;
this . stack . push ( token ) ;
}
return this . stack [ 0 ] ;
} ;
/ * *
* Returns a string representation of this object .
* @ return { string } String representation as of "Tokenizer(index/length)"
* @ expose
* /
TokenizerPrototype . toString = function ( ) {
return "Tokenizer(" + this . index + "/" + this . source . length + " at line " + this . line + ")" ;
} ;
/ * *
* @ alias ProtoBuf . DotProto . Tokenizer
* @ expose
* /
DotProto . Tokenizer = Tokenizer ;
/ * *
* Constructs a new Parser .
* @ exports ProtoBuf . DotProto . Parser
* @ class prototype parser
* @ param { string } proto Protocol source
* @ constructor
* /
var Parser = function ( proto ) {
/ * *
* Tokenizer .
* @ type { ProtoBuf . DotProto . Tokenizer }
* @ expose
* /
this . tn = new Tokenizer ( proto ) ;
} ;
/ * *
* @ alias ProtoBuf . DotProto . Parser . prototype
* @ inner
* /
var ParserPrototype = Parser . prototype ;
/ * *
* Runs the parser .
* @ return { { package : string | null , messages : Array . < object > , enums : Array . < object > , imports : Array . < string > , options : object < string , * > } }
* @ throws { Error } If the source cannot be parsed
* @ expose
* /
ParserPrototype . parse = function ( ) {
var topLevel = {
"name" : "[ROOT]" , // temporary
"package" : null ,
"messages" : [ ] ,
"enums" : [ ] ,
"imports" : [ ] ,
"options" : { } ,
"services" : [ ]
} ;
var token , head = true ;
while ( token = this . tn . next ( ) ) {
switch ( token ) {
case 'package' :
if ( ! head || topLevel [ "package" ] !== null )
throw Error ( "Unexpected package at line " + this . tn . line ) ;
topLevel [ "package" ] = this . _parsePackage ( token ) ;
break ;
case 'import' :
if ( ! head )
throw Error ( "Unexpected import at line " + this . tn . line ) ;
topLevel . imports . push ( this . _parseImport ( token ) ) ;
break ;
case 'message' :
this . _parseMessage ( topLevel , null , token ) ;
head = false ;
break ;
case 'enum' :
this . _parseEnum ( topLevel , token ) ;
head = false ;
break ;
case 'option' :
if ( ! head )
throw Error ( "Unexpected option at line " + this . tn . line ) ;
this . _parseOption ( topLevel , token ) ;
break ;
case 'service' :
this . _parseService ( topLevel , token ) ;
break ;
case 'extend' :
this . _parseExtend ( topLevel , token ) ;
break ;
case 'syntax' :
this . _parseIgnoredStatement ( topLevel , token ) ;
break ;
default :
throw Error ( "Unexpected token at line " + this . tn . line + ": " + token ) ;
}
}
delete topLevel [ "name" ] ;
return topLevel ;
} ;
/ * *
* Parses a number value .
* @ param { string } val Number value to parse
* @ return { number } Number
* @ throws { Error } If the number value is invalid
* @ private
* /
ParserPrototype . _parseNumber = function ( val ) {
var sign = 1 ;
if ( val . charAt ( 0 ) == '-' )
sign = - 1 ,
val = val . substring ( 1 ) ;
if ( Lang . NUMBER _DEC . test ( val ) )
return sign * parseInt ( val , 10 ) ;
else if ( Lang . NUMBER _HEX . test ( val ) )
return sign * parseInt ( val . substring ( 2 ) , 16 ) ;
else if ( Lang . NUMBER _OCT . test ( val ) )
return sign * parseInt ( val . substring ( 1 ) , 8 ) ;
else if ( Lang . NUMBER _FLT . test ( val ) )
return sign * parseFloat ( val ) ;
throw Error ( "Illegal number at line " + this . tn . line + ": " + ( sign < 0 ? '-' : '' ) + val ) ;
} ;
/ * *
* Parses a ( possibly multiline ) string .
* @ returns { string }
* @ private
* /
ParserPrototype . _parseString = function ( ) {
var value = "" , token ;
do {
token = this . tn . next ( ) ; // Known to be = this.tn.stringEndsWith
value += this . tn . next ( ) ;
token = this . tn . next ( ) ;
if ( token !== this . tn . stringEndsWith )
throw Error ( "Illegal end of string at line " + this . tn . line + ": " + token ) ;
token = this . tn . peek ( ) ;
} while ( token === Lang . STRINGOPEN || token === Lang . STRINGOPEN _SQ ) ;
return value ;
} ;
/ * *
* Parses an ID value .
* @ param { string } val ID value to parse
* @ param { boolean = } neg Whether the ID may be negative , defaults to ` false `
* @ returns { number } ID
* @ throws { Error } If the ID value is invalid
* @ private
* /
ParserPrototype . _parseId = function ( val , neg ) {
var id = - 1 ;
var sign = 1 ;
if ( val . charAt ( 0 ) == '-' )
sign = - 1 ,
val = val . substring ( 1 ) ;
if ( Lang . NUMBER _DEC . test ( val ) )
id = parseInt ( val ) ;
else if ( Lang . NUMBER _HEX . test ( val ) )
id = parseInt ( val . substring ( 2 ) , 16 ) ;
else if ( Lang . NUMBER _OCT . test ( val ) )
id = parseInt ( val . substring ( 1 ) , 8 ) ;
else
throw Error ( "Illegal id at line " + this . tn . line + ": " + ( sign < 0 ? '-' : '' ) + val ) ;
id = ( sign * id ) | 0 ; // Force to 32bit
if ( ! neg && id < 0 )
throw Error ( "Illegal id at line " + this . tn . line + ": " + ( sign < 0 ? '-' : '' ) + val ) ;
return id ;
} ;
/ * *
* Parses the package definition .
* @ param { string } token Initial token
* @ return { string } Package name
* @ throws { Error } If the package definition cannot be parsed
* @ private
* /
ParserPrototype . _parsePackage = function ( token ) {
token = this . tn . next ( ) ;
if ( ! Lang . TYPEREF . test ( token ) )
throw Error ( "Illegal package name at line " + this . tn . line + ": " + token ) ;
var pkg = token ;
token = this . tn . next ( ) ;
if ( token != Lang . END )
throw Error ( "Illegal end of package at line " + this . tn . line + ": " + token ) ;
return pkg ;
} ;
/ * *
* Parses an import definition .
* @ param { string } token Initial token
* @ return { string } Import file name
* @ throws { Error } If the import definition cannot be parsed
* @ private
* /
ParserPrototype . _parseImport = function ( token ) {
token = this . tn . peek ( ) ;
if ( token === "public" )
this . tn . next ( ) ,
token = this . tn . peek ( ) ;
if ( token !== Lang . STRINGOPEN && token !== Lang . STRINGOPEN _SQ )
throw Error ( "Illegal start of import at line " + this . tn . line + ": " + token ) ;
var imported = this . _parseString ( ) ;
token = this . tn . next ( ) ;
if ( token !== Lang . END )
throw Error ( "Illegal end of import at line " + this . tn . line + ": " + token ) ;
return imported ;
} ;
/ * *
* Parses a namespace option .
* @ param { Object } parent Parent definition
* @ param { string } token Initial token
* @ throws { Error } If the option cannot be parsed
* @ private
* /
ParserPrototype . _parseOption = function ( parent , token ) {
token = this . tn . next ( ) ;
var custom = false ;
if ( token == Lang . COPTOPEN )
custom = true ,
token = this . tn . next ( ) ;
if ( ! Lang . TYPEREF . test ( token ) )
// we can allow options of the form google.protobuf.* since they will just get ignored anyways
if ( ! /google\.protobuf\./ . test ( token ) )
throw Error ( "Illegal option name in message " + parent . name + " at line " + this . tn . line + ": " + token ) ;
var name = token ;
token = this . tn . next ( ) ;
if ( custom ) { // (my_method_option).foo, (my_method_option), some_method_option, (foo.my_option).bar
if ( token !== Lang . COPTCLOSE )
throw Error ( "Illegal end in message " + parent . name + ", option " + name + " at line " + this . tn . line + ": " + token ) ;
name = '(' + name + ')' ;
token = this . tn . next ( ) ;
if ( Lang . FQTYPEREF . test ( token ) )
name += token ,
token = this . tn . next ( ) ;
}
if ( token !== Lang . EQUAL )
throw Error ( "Illegal operator in message " + parent . name + ", option " + name + " at line " + this . tn . line + ": " + token ) ;
var value ;
token = this . tn . peek ( ) ;
if ( token === Lang . STRINGOPEN || token === Lang . STRINGOPEN _SQ )
value = this . _parseString ( ) ;
else {
this . tn . next ( ) ;
if ( Lang . NUMBER . test ( token ) )
value = this . _parseNumber ( token , true ) ;
else if ( Lang . BOOL . test ( token ) )
value = token === 'true' ;
else if ( Lang . TYPEREF . test ( token ) )
value = token ;
else
throw Error ( "Illegal option value in message " + parent . name + ", option " + name + " at line " + this . tn . line + ": " + token ) ;
}
token = this . tn . next ( ) ;
if ( token !== Lang . END )
throw Error ( "Illegal end of option in message " + parent . name + ", option " + name + " at line " + this . tn . line + ": " + token ) ;
parent [ "options" ] [ name ] = value ;
} ;
/ * *
* Parses an ignored statement of the form [ 'keyword' , ... , ';' ] .
* @ param { Object } parent Parent definition
* @ param { string } keyword Initial token
* @ throws { Error } If the directive cannot be parsed
* @ private
* /
ParserPrototype . _parseIgnoredStatement = function ( parent , keyword ) {
var token ;
do {
token = this . tn . next ( ) ;
if ( token === null )
throw Error ( "Unexpected EOF in " + parent . name + ", " + keyword + " at line " + this . tn . line ) ;
if ( token === Lang . END )
break ;
} while ( true ) ;
} ;
/ * *
* Parses a service definition .
* @ param { Object } parent Parent definition
* @ param { string } token Initial token
* @ throws { Error } If the service cannot be parsed
* @ private
* /
ParserPrototype . _parseService = function ( parent , token ) {
token = this . tn . next ( ) ;
if ( ! Lang . NAME . test ( token ) )
throw Error ( "Illegal service name at line " + this . tn . line + ": " + token ) ;
var name = token ;
var svc = {
"name" : name ,
"rpc" : { } ,
"options" : { }
} ;
token = this . tn . next ( ) ;
if ( token !== Lang . OPEN )
throw Error ( "Illegal start of service " + name + " at line " + this . tn . line + ": " + token ) ;
do {
token = this . tn . next ( ) ;
if ( token === "option" )
this . _parseOption ( svc , token ) ;
else if ( token === 'rpc' )
this . _parseServiceRPC ( svc , token ) ;
else if ( token !== Lang . CLOSE )
throw Error ( "Illegal type of service " + name + " at line " + this . tn . line + ": " + token ) ;
} while ( token !== Lang . CLOSE ) ;
parent [ "services" ] . push ( svc ) ;
} ;
/ * *
* Parses a RPC service definition of the form [ 'rpc' , name , ( request ) , 'returns' , ( response ) ] .
* @ param { Object } svc Parent definition
* @ param { string } token Initial token
* @ private
* /
ParserPrototype . _parseServiceRPC = function ( svc , token ) {
var type = token ;
token = this . tn . next ( ) ;
if ( ! Lang . NAME . test ( token ) )
throw Error ( "Illegal method name in service " + svc [ "name" ] + " at line " + this . tn . line + ": " + token ) ;
var name = token ;
var method = {
"request" : null ,
"response" : null ,
"options" : { }
} ;
token = this . tn . next ( ) ;
if ( token !== Lang . COPTOPEN )
throw Error ( "Illegal start of request type in service " + svc [ "name" ] + "#" + name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
if ( ! Lang . TYPEREF . test ( token ) )
throw Error ( "Illegal request type in service " + svc [ "name" ] + "#" + name + " at line " + this . tn . line + ": " + token ) ;
method [ "request" ] = token ;
token = this . tn . next ( ) ;
if ( token != Lang . COPTCLOSE )
throw Error ( "Illegal end of request type in service " + svc [ "name" ] + "#" + name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
if ( token . toLowerCase ( ) !== "returns" )
throw Error ( "Illegal delimiter in service " + svc [ "name" ] + "#" + name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
if ( token != Lang . COPTOPEN )
throw Error ( "Illegal start of response type in service " + svc [ "name" ] + "#" + name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
method [ "response" ] = token ;
token = this . tn . next ( ) ;
if ( token !== Lang . COPTCLOSE )
throw Error ( "Illegal end of response type in service " + svc [ "name" ] + "#" + name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
if ( token === Lang . OPEN ) {
do {
token = this . tn . next ( ) ;
if ( token === 'option' )
this . _parseOption ( method , token ) ; // <- will fail for the custom-options example
else if ( token !== Lang . CLOSE )
throw Error ( "Illegal start of option inservice " + svc [ "name" ] + "#" + name + " at line " + this . tn . line + ": " + token ) ;
} while ( token !== Lang . CLOSE ) ;
if ( this . tn . peek ( ) === Lang . END )
this . tn . next ( ) ;
} else if ( token !== Lang . END )
throw Error ( "Illegal delimiter in service " + svc [ "name" ] + "#" + name + " at line " + this . tn . line + ": " + token ) ;
if ( typeof svc [ type ] === 'undefined' )
svc [ type ] = { } ;
svc [ type ] [ name ] = method ;
} ;
/ * *
* Parses a message definition .
* @ param { Object } parent Parent definition
* @ param { Object } fld Field definition if this is a group , otherwise ` null `
* @ param { string } token First token
* @ return { Object }
* @ throws { Error } If the message cannot be parsed
* @ private
* /
ParserPrototype . _parseMessage = function ( parent , fld , token ) {
/** @dict */
var msg = { } ; // Note: At some point we might want to exclude the parser, so we need a dict.
var isGroup = token === "group" ;
token = this . tn . next ( ) ;
if ( ! Lang . NAME . test ( token ) )
throw Error ( "Illegal " + ( isGroup ? "group" : "message" ) + " name" + ( parent ? " in message " + parent [ "name" ] : "" ) + " at line " + this . tn . line + ": " + token ) ;
msg [ "name" ] = token ;
if ( isGroup ) {
token = this . tn . next ( ) ;
if ( token !== Lang . EQUAL )
throw Error ( "Illegal id assignment after group " + msg . name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
try {
fld [ "id" ] = this . _parseId ( token ) ;
} catch ( e ) {
throw Error ( "Illegal field id value for group " + msg . name + "#" + fld . name + " at line " + this . tn . line + ": " + token ) ;
}
msg [ "isGroup" ] = true ;
}
msg [ "fields" ] = [ ] ; // Note: Using arrays to support also browser that cannot preserve order of object keys.
msg [ "enums" ] = [ ] ;
msg [ "messages" ] = [ ] ;
msg [ "options" ] = { } ;
msg [ "oneofs" ] = { } ;
token = this . tn . next ( ) ;
if ( token === Lang . OPTOPEN && fld )
this . _parseFieldOptions ( msg , fld , token ) ,
token = this . tn . next ( ) ;
if ( token !== Lang . OPEN )
throw Error ( "Illegal start of " + ( isGroup ? "group" : "message" ) + " " + msg . name + " at line " + this . tn . line + ": " + token ) ;
// msg["extensions"] = undefined
do {
token = this . tn . next ( ) ;
if ( token === Lang . CLOSE ) {
token = this . tn . peek ( ) ;
if ( token === Lang . END )
this . tn . next ( ) ;
break ;
} else if ( Lang . RULE . test ( token ) )
this . _parseMessageField ( msg , token ) ;
else if ( token === "oneof" )
this . _parseMessageOneOf ( msg , token ) ;
else if ( token === "enum" )
this . _parseEnum ( msg , token ) ;
else if ( token === "message" )
this . _parseMessage ( msg , null , token ) ;
else if ( token === "option" )
this . _parseOption ( msg , token ) ;
else if ( token === "extensions" )
msg [ "extensions" ] = this . _parseExtensions ( msg , token ) ;
else if ( token === "extend" )
this . _parseExtend ( msg , token ) ;
else
throw Error ( "Illegal token in message " + msg . name + " at line " + this . tn . line + ": " + token ) ;
} while ( true ) ;
parent [ "messages" ] . push ( msg ) ;
return msg ;
} ;
/ * *
* Parses a message field .
* @ param { Object } msg Message definition
* @ param { string } token Initial token
* @ returns { ! Object } Field descriptor
* @ throws { Error } If the message field cannot be parsed
* @ private
* /
ParserPrototype . _parseMessageField = function ( msg , token ) {
/** @dict */
var fld = { } , grp = null ;
fld [ "rule" ] = token ;
/** @dict */
fld [ "options" ] = { } ;
token = this . tn . next ( ) ;
if ( token === "group" ) {
// "A [legacy] group simply combines a nested message type and a field into a single declaration. In your
// code, you can treat this message just as if it had a Result type field called result (the latter name is
// converted to lower-case so that it does not conflict with the former)."
grp = this . _parseMessage ( msg , fld , token ) ;
if ( ! /^[A-Z]/ . test ( grp [ "name" ] ) )
throw Error ( 'Group names must start with a capital letter' ) ;
fld [ "type" ] = grp [ "name" ] ;
fld [ "name" ] = grp [ "name" ] . toLowerCase ( ) ;
token = this . tn . peek ( ) ;
if ( token === Lang . END )
this . tn . next ( ) ;
} else {
if ( ! Lang . TYPE . test ( token ) && ! Lang . TYPEREF . test ( token ) )
throw Error ( "Illegal field type in message " + msg . name + " at line " + this . tn . line + ": " + token ) ;
fld [ "type" ] = token ;
token = this . tn . next ( ) ;
if ( ! Lang . NAME . test ( token ) )
throw Error ( "Illegal field name in message " + msg . name + " at line " + this . tn . line + ": " + token ) ;
fld [ "name" ] = token ;
token = this . tn . next ( ) ;
if ( token !== Lang . EQUAL )
throw Error ( "Illegal token in field " + msg . name + "#" + fld . name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
try {
fld [ "id" ] = this . _parseId ( token ) ;
} catch ( e ) {
throw Error ( "Illegal field id in message " + msg . name + "#" + fld . name + " at line " + this . tn . line + ": " + token ) ;
}
token = this . tn . next ( ) ;
if ( token === Lang . OPTOPEN )
this . _parseFieldOptions ( msg , fld , token ) ,
token = this . tn . next ( ) ;
if ( token !== Lang . END )
throw Error ( "Illegal delimiter in message " + msg . name + "#" + fld . name + " at line " + this . tn . line + ": " + token ) ;
}
msg [ "fields" ] . push ( fld ) ;
return fld ;
} ;
/ * *
* Parses a message oneof .
* @ param { Object } msg Message definition
* @ param { string } token Initial token
* @ throws { Error } If the message oneof cannot be parsed
* @ private
* /
ParserPrototype . _parseMessageOneOf = function ( msg , token ) {
token = this . tn . next ( ) ;
if ( ! Lang . NAME . test ( token ) )
throw Error ( "Illegal oneof name in message " + msg . name + " at line " + this . tn . line + ": " + token ) ;
var name = token ,
fld ;
var fields = [ ] ;
token = this . tn . next ( ) ;
if ( token !== Lang . OPEN )
throw Error ( "Illegal start of oneof " + name + " at line " + this . tn . line + ": " + token ) ;
while ( this . tn . peek ( ) !== Lang . CLOSE ) {
fld = this . _parseMessageField ( msg , "optional" ) ;
fld [ "oneof" ] = name ;
fields . push ( fld [ "id" ] ) ;
}
this . tn . next ( ) ;
msg [ "oneofs" ] [ name ] = fields ;
} ;
/ * *
* Parses a set of field option definitions .
* @ param { Object } msg Message definition
* @ param { Object } fld Field definition
* @ param { string } token Initial token
* @ throws { Error } If the message field options cannot be parsed
* @ private
* /
ParserPrototype . _parseFieldOptions = function ( msg , fld , token ) {
var first = true ;
do {
token = this . tn . next ( ) ;
if ( token === Lang . OPTCLOSE )
break ;
else if ( token === Lang . OPTEND ) {
if ( first )
throw Error ( "Illegal start of options in message " + msg . name + "#" + fld . name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
}
this . _parseFieldOption ( msg , fld , token ) ;
first = false ;
} while ( true ) ;
} ;
/ * *
* Parses a single field option .
* @ param { Object } msg Message definition
* @ param { Object } fld Field definition
* @ param { string } token Initial token
* @ throws { Error } If the mesage field option cannot be parsed
* @ private
* /
ParserPrototype . _parseFieldOption = function ( msg , fld , token ) {
var custom = false ;
if ( token === Lang . COPTOPEN )
token = this . tn . next ( ) ,
custom = true ;
if ( ! Lang . TYPEREF . test ( token ) )
throw Error ( "Illegal field option in " + msg . name + "#" + fld . name + " at line " + this . tn . line + ": " + token ) ;
var name = token ;
token = this . tn . next ( ) ;
if ( custom ) {
if ( token !== Lang . COPTCLOSE )
throw Error ( "Illegal delimiter in " + msg . name + "#" + fld . name + " at line " + this . tn . line + ": " + token ) ;
name = '(' + name + ')' ;
token = this . tn . next ( ) ;
if ( Lang . FQTYPEREF . test ( token ) )
name += token ,
token = this . tn . next ( ) ;
}
if ( token !== Lang . EQUAL )
throw Error ( "Illegal token in " + msg . name + "#" + fld . name + " at line " + this . tn . line + ": " + token ) ;
var value ;
token = this . tn . peek ( ) ;
if ( token === Lang . STRINGOPEN || token === Lang . STRINGOPEN _SQ ) {
value = this . _parseString ( ) ;
} else if ( Lang . NUMBER . test ( token , true ) )
value = this . _parseNumber ( this . tn . next ( ) , true ) ;
else if ( Lang . BOOL . test ( token ) )
value = this . tn . next ( ) . toLowerCase ( ) === 'true' ;
else if ( Lang . TYPEREF . test ( token ) )
value = this . tn . next ( ) ; // TODO: Resolve?
else
throw Error ( "Illegal value in message " + msg . name + "#" + fld . name + ", option " + name + " at line " + this . tn . line + ": " + token ) ;
fld [ "options" ] [ name ] = value ;
} ;
/ * *
* Parses an enum .
* @ param { Object } msg Message definition
* @ param { string } token Initial token
* @ throws { Error } If the enum cannot be parsed
* @ private
* /
ParserPrototype . _parseEnum = function ( msg , token ) {
/** @dict */
var enm = { } ;
token = this . tn . next ( ) ;
if ( ! Lang . NAME . test ( token ) )
throw Error ( "Illegal enum name in message " + msg . name + " at line " + this . tn . line + ": " + token ) ;
enm [ "name" ] = token ;
token = this . tn . next ( ) ;
if ( token !== Lang . OPEN )
throw Error ( "Illegal start of enum " + enm . name + " at line " + this . tn . line + ": " + token ) ;
enm [ "values" ] = [ ] ;
enm [ "options" ] = { } ;
do {
token = this . tn . next ( ) ;
if ( token === Lang . CLOSE ) {
token = this . tn . peek ( ) ;
if ( token === Lang . END )
this . tn . next ( ) ;
break ;
}
if ( token == 'option' )
this . _parseOption ( enm , token ) ;
else {
if ( ! Lang . NAME . test ( token ) )
throw Error ( "Illegal name in enum " + enm . name + " at line " + this . tn . line + ": " + token ) ;
this . _parseEnumValue ( enm , token ) ;
}
} while ( true ) ;
msg [ "enums" ] . push ( enm ) ;
} ;
/ * *
* Parses an enum value .
* @ param { Object } enm Enum definition
* @ param { string } token Initial token
* @ throws { Error } If the enum value cannot be parsed
* @ private
* /
ParserPrototype . _parseEnumValue = function ( enm , token ) {
/** @dict */
var val = { } ;
val [ "name" ] = token ;
token = this . tn . next ( ) ;
if ( token !== Lang . EQUAL )
throw Error ( "Illegal token in enum " + enm . name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
try {
val [ "id" ] = this . _parseId ( token , true ) ;
} catch ( e ) {
throw Error ( "Illegal id in enum " + enm . name + " at line " + this . tn . line + ": " + token ) ;
}
enm [ "values" ] . push ( val ) ;
token = this . tn . next ( ) ;
if ( token === Lang . OPTOPEN ) {
var opt = { 'options' : { } } ; // TODO: Actually expose them somehow.
this . _parseFieldOptions ( enm , opt , token ) ;
token = this . tn . next ( ) ;
}
if ( token !== Lang . END )
throw Error ( "Illegal delimiter in enum " + enm . name + " at line " + this . tn . line + ": " + token ) ;
} ;
/ * *
* Parses an extensions statement .
* @ param { Object } msg Message object
* @ param { string } token Initial token
* @ throws { Error } If the extensions statement cannot be parsed
* @ private
* /
ParserPrototype . _parseExtensions = function ( msg , token ) {
/** @type {Array.<number>} */
var range = [ ] ;
token = this . tn . next ( ) ;
if ( token === "min" ) // FIXME: Does the official implementation support this?
range . push ( ProtoBuf . ID _MIN ) ;
else if ( token === "max" )
range . push ( ProtoBuf . ID _MAX ) ;
else
range . push ( this . _parseNumber ( token ) ) ;
token = this . tn . next ( ) ;
if ( token !== 'to' )
throw Error ( "Illegal extensions delimiter in message " + msg . name + " at line " + this . tn . line + ": " + token ) ;
token = this . tn . next ( ) ;
if ( token === "min" )
range . push ( ProtoBuf . ID _MIN ) ;
else if ( token === "max" )
range . push ( ProtoBuf . ID _MAX ) ;
else
range . push ( this . _parseNumber ( token ) ) ;
token = this . tn . next ( ) ;
if ( token !== Lang . END )
throw Error ( "Illegal extensions delimiter in message " + msg . name + " at line " + this . tn . line + ": " + token ) ;
return range ;
} ;
/ * *
* Parses an extend block .
* @ param { Object } parent Parent object
* @ param { string } token Initial token
* @ throws { Error } If the extend block cannot be parsed
* @ private
* /
ParserPrototype . _parseExtend = function ( parent , token ) {
token = this . tn . next ( ) ;
if ( ! Lang . TYPEREF . test ( token ) )
throw Error ( "Illegal message name at line " + this . tn . line + ": " + token ) ;
/** @dict */
var ext = { } ;
ext [ "ref" ] = token ;
ext [ "fields" ] = [ ] ;
token = this . tn . next ( ) ;
if ( token !== Lang . OPEN )
throw Error ( "Illegal start of extend " + ext . name + " at line " + this . tn . line + ": " + token ) ;
do {
token = this . tn . next ( ) ;
if ( token === Lang . CLOSE ) {
token = this . tn . peek ( ) ;
if ( token == Lang . END )
this . tn . next ( ) ;
break ;
} else if ( Lang . RULE . test ( token ) )
this . _parseMessageField ( ext , token ) ;
else
throw Error ( "Illegal token in extend " + ext . name + " at line " + this . tn . line + ": " + token ) ;
} while ( true ) ;
parent [ "messages" ] . push ( ext ) ;
return ext ;
} ;
/ * *
* Returns a string representation of this object .
* @ returns { string } String representation as of "Parser"
* /
ParserPrototype . toString = function ( ) {
return "Parser" ;
} ;
/ * *
* @ alias ProtoBuf . DotProto . Parser
* @ expose
* /
DotProto . Parser = Parser ;
return DotProto ;
} ) ( ProtoBuf , ProtoBuf . Lang ) ;
/ * *
* @ alias ProtoBuf . Reflect
* @ expose
* /
ProtoBuf . Reflect = ( function ( ProtoBuf ) {
"use strict" ;
/ * *
* Reflection types .
* @ exports ProtoBuf . Reflect
* @ namespace
* /
var Reflect = { } ;
/ * *
* Constructs a Reflect base class .
* @ exports ProtoBuf . Reflect . T
* @ constructor
* @ abstract
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ? ProtoBuf . Reflect . T } parent Parent object
* @ param { string } name Object name
* /
var T = function ( builder , parent , name ) {
/ * *
* Builder reference .
* @ type { ! ProtoBuf . Builder }
* @ expose
* /
this . builder = builder ;
/ * *
* Parent object .
* @ type { ? ProtoBuf . Reflect . T }
* @ expose
* /
this . parent = parent ;
/ * *
* Object name in namespace .
* @ type { string }
* @ expose
* /
this . name = name ;
/ * *
* Fully qualified class name
* @ type { string }
* @ expose
* /
this . className ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . T . prototype
* @ inner
* /
var TPrototype = T . prototype ;
/ * *
* Returns the fully qualified name of this object .
* @ returns { string } Fully qualified name as of ".PATH.TO.THIS"
* @ expose
* /
TPrototype . fqn = function ( ) {
var name = this . name ,
ptr = this ;
do {
ptr = ptr . parent ;
if ( ptr == null )
break ;
name = ptr . name + "." + name ;
} while ( true ) ;
return name ;
} ;
/ * *
* Returns a string representation of this Reflect object ( its fully qualified name ) .
* @ param { boolean = } includeClass Set to true to include the class name . Defaults to false .
* @ return String representation
* @ expose
* /
TPrototype . toString = function ( includeClass ) {
return ( includeClass ? this . className + " " : "" ) + this . fqn ( ) ;
} ;
/ * *
* Builds this type .
* @ throws { Error } If this type cannot be built directly
* @ expose
* /
TPrototype . build = function ( ) {
throw Error ( this . toString ( true ) + " cannot be built directly" ) ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . T
* @ expose
* /
Reflect . T = T ;
/ * *
* Constructs a new Namespace .
* @ exports ProtoBuf . Reflect . Namespace
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ? ProtoBuf . Reflect . Namespace } parent Namespace parent
* @ param { string } name Namespace name
* @ param { Object . < string , * >= } options Namespace options
* @ constructor
* @ extends ProtoBuf . Reflect . T
* /
var Namespace = function ( builder , parent , name , options ) {
T . call ( this , builder , parent , name ) ;
/ * *
* @ override
* /
this . className = "Namespace" ;
/ * *
* Children inside the namespace .
* @ type { ! Array . < ProtoBuf . Reflect . T > }
* /
this . children = [ ] ;
/ * *
* Options .
* @ type { ! Object . < string , * > }
* /
this . options = options || { } ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Namespace . prototype
* @ inner
* /
var NamespacePrototype = Namespace . prototype = Object . create ( T . prototype ) ;
/ * *
* Returns an array of the namespace ' s children .
* @ param { ProtoBuf . Reflect . T = } type Filter type ( returns instances of this type only ) . Defaults to null ( all children ) .
* @ return { Array . < ProtoBuf . Reflect . T > }
* @ expose
* /
NamespacePrototype . getChildren = function ( type ) {
type = type || null ;
if ( type == null )
return this . children . slice ( ) ;
var children = [ ] ;
for ( var i = 0 , k = this . children . length ; i < k ; ++ i )
if ( this . children [ i ] instanceof type )
children . push ( this . children [ i ] ) ;
return children ;
} ;
/ * *
* Adds a child to the namespace .
* @ param { ProtoBuf . Reflect . T } child Child
* @ throws { Error } If the child cannot be added ( duplicate )
* @ expose
* /
NamespacePrototype . addChild = function ( child ) {
var other ;
if ( other = this . getChild ( child . name ) ) {
// Try to revert camelcase transformation on collision
if ( other instanceof Message . Field && other . name !== other . originalName && this . getChild ( other . originalName ) === null )
other . name = other . originalName ; // Revert previous first (effectively keeps both originals)
else if ( child instanceof Message . Field && child . name !== child . originalName && this . getChild ( child . originalName ) === null )
child . name = child . originalName ;
else
throw Error ( "Duplicate name in namespace " + this . toString ( true ) + ": " + child . name ) ;
}
this . children . push ( child ) ;
} ;
/ * *
* Gets a child by its name or id .
* @ param { string | number } nameOrId Child name or id
* @ return { ? ProtoBuf . Reflect . T } The child or null if not found
* @ expose
* /
NamespacePrototype . getChild = function ( nameOrId ) {
var key = typeof nameOrId === 'number' ? 'id' : 'name' ;
for ( var i = 0 , k = this . children . length ; i < k ; ++ i )
if ( this . children [ i ] [ key ] === nameOrId )
return this . children [ i ] ;
return null ;
} ;
/ * *
* Resolves a reflect object inside of this namespace .
* @ param { string } qn Qualified name to resolve
* @ param { boolean = } excludeFields Excludes fields , defaults to ` false `
* @ return { ? ProtoBuf . Reflect . Namespace } The resolved type or null if not found
* @ expose
* /
NamespacePrototype . resolve = function ( qn , excludeFields ) {
var part = qn . split ( "." ) ,
ptr = this ,
i = 0 ;
if ( part [ i ] === "" ) { // Fully qualified name, e.g. ".My.Message'
while ( ptr . parent !== null )
ptr = ptr . parent ;
i ++ ;
}
var child ;
do {
do {
child = ptr . getChild ( part [ i ] ) ;
if ( ! child || ! ( child instanceof Reflect . T ) || ( excludeFields && child instanceof Reflect . Message . Field ) ) {
ptr = null ;
break ;
}
ptr = child ; i ++ ;
} while ( i < part . length ) ;
if ( ptr != null )
break ; // Found
// Else search the parent
if ( this . parent !== null ) {
return this . parent . resolve ( qn , excludeFields ) ;
}
} while ( ptr != null ) ;
return ptr ;
} ;
/ * *
* Builds the namespace and returns the runtime counterpart .
* @ return { Object . < string , Function | Object > } Runtime namespace
* @ expose
* /
NamespacePrototype . build = function ( ) {
/** @dict */
var ns = { } ;
var children = this . children ;
for ( var i = 0 , k = children . length , child ; i < k ; ++ i ) {
child = children [ i ] ;
if ( child instanceof Namespace )
ns [ child . name ] = child . build ( ) ;
}
if ( Object . defineProperty )
Object . defineProperty ( ns , "$options" , { "value" : this . buildOpt ( ) } ) ;
return ns ;
} ;
/ * *
* Builds the namespace 's ' $options ' property .
* @ return { Object . < string , * > }
* /
NamespacePrototype . buildOpt = function ( ) {
var opt = { } ,
keys = Object . keys ( this . options ) ;
for ( var i = 0 , k = keys . length ; i < k ; ++ i ) {
var key = keys [ i ] ,
val = this . options [ keys [ i ] ] ;
// TODO: Options are not resolved, yet.
// if (val instanceof Namespace) {
// opt[key] = val.build();
// } else {
opt [ key ] = val ;
// }
}
return opt ;
} ;
/ * *
* Gets the value assigned to the option with the specified name .
* @ param { string = } name Returns the option value if specified , otherwise all options are returned .
* @ return { * | Object . < string , * > } null } Option value or NULL if there is no such option
* /
NamespacePrototype . getOption = function ( name ) {
if ( typeof name === 'undefined' )
return this . options ;
return typeof this . options [ name ] !== 'undefined' ? this . options [ name ] : null ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Namespace
* @ expose
* /
Reflect . Namespace = Namespace ;
/ * *
* Constructs a new Message .
* @ exports ProtoBuf . Reflect . Message
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . Namespace } parent Parent message or namespace
* @ param { string } name Message name
* @ param { Object . < string , * >= } options Message options
* @ param { boolean = } isGroup ` true ` if this is a legacy group
* @ constructor
* @ extends ProtoBuf . Reflect . Namespace
* /
var Message = function ( builder , parent , name , options , isGroup ) {
Namespace . call ( this , builder , parent , name , options ) ;
/ * *
* @ override
* /
this . className = "Message" ;
/ * *
* Extensions range .
* @ type { ! Array . < number > }
* @ expose
* /
this . extensions = [ ProtoBuf . ID _MIN , ProtoBuf . ID _MAX ] ;
/ * *
* Runtime message class .
* @ type { ? function ( new : ProtoBuf . Builder . Message ) }
* @ expose
* /
this . clazz = null ;
/ * *
* Whether this is a legacy group or not .
* @ type { boolean }
* @ expose
* /
this . isGroup = ! ! isGroup ;
// The following cached collections are used to efficiently iterate over or look up fields when decoding.
/ * *
* Cached fields .
* @ type { ? Array . < ! ProtoBuf . Reflect . Message . Field > }
* @ private
* /
this . _fields = null ;
/ * *
* Cached fields by id .
* @ type { ? Object . < number , ! ProtoBuf . Reflect . Message . Field > }
* @ private
* /
this . _fieldsById = null ;
/ * *
* Cached fields by name .
* @ type { ? Object . < string , ! ProtoBuf . Reflect . Message . Field > }
* @ private
* /
this . _fieldsByName = null ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Message . prototype
* @ inner
* /
var MessagePrototype = Message . prototype = Object . create ( Namespace . prototype ) ;
/ * *
* Builds the message and returns the runtime counterpart , which is a fully functional class .
* @ see ProtoBuf . Builder . Message
* @ param { boolean = } rebuild Whether to rebuild or not , defaults to false
* @ return { ProtoBuf . Reflect . Message } Message class
* @ throws { Error } If the message cannot be built
* @ expose
* /
MessagePrototype . build = function ( rebuild ) {
if ( this . clazz && ! rebuild )
return this . clazz ;
// Create the runtime Message class in its own scope
var clazz = ( function ( ProtoBuf , T ) {
var fields = T . getChildren ( ProtoBuf . Reflect . Message . Field ) ,
oneofs = T . getChildren ( ProtoBuf . Reflect . Message . OneOf ) ;
/ * *
* Constructs a new runtime Message .
* @ name ProtoBuf . Builder . Message
* @ class Barebone of all runtime messages .
* @ param { ! Object . < string , * > | string } values Preset values
* @ param { ... string } var _args
* @ constructor
* @ throws { Error } If the message cannot be created
* /
var Message = function ( values , var _args ) {
ProtoBuf . Builder . Message . call ( this ) ;
// Create virtual oneof properties
for ( var i = 0 , k = oneofs . length ; i < k ; ++ i )
this [ oneofs [ i ] . name ] = null ;
// Create fields and set default values
for ( i = 0 , k = fields . length ; i < k ; ++ i ) {
var field = fields [ i ] ;
this [ field . name ] = field . repeated ? [ ] : null ;
if ( field . required && field . defaultValue !== null )
this [ field . name ] = field . defaultValue ;
}
if ( arguments . length > 0 ) {
// Set field values from a values object
if ( arguments . length === 1 && typeof values === 'object' &&
/* not another Message */ typeof values . encode !== 'function' &&
/* not a repeated field */ ! ProtoBuf . Util . isArray ( values ) &&
/* not a ByteBuffer */ ! ( values instanceof ByteBuffer ) &&
/* not an ArrayBuffer */ ! ( values instanceof ArrayBuffer ) &&
/* not a Long */ ! ( ProtoBuf . Long && values instanceof ProtoBuf . Long ) ) {
var keys = Object . keys ( values ) ;
for ( i = 0 , k = keys . length ; i < k ; ++ i )
this . $set ( keys [ i ] , values [ keys [ i ] ] ) ; // May throw
} else // Set field values from arguments, in declaration order
for ( i = 0 , k = arguments . length ; i < k ; ++ i )
this . $set ( fields [ i ] . name , arguments [ i ] ) ; // May throw
}
} ;
/ * *
* @ alias ProtoBuf . Builder . Message . prototype
* @ inner
* /
var MessagePrototype = Message . prototype = Object . create ( ProtoBuf . Builder . Message . prototype ) ;
/ * *
* Adds a value to a repeated field .
* @ name ProtoBuf . Builder . Message # add
* @ function
* @ param { string } key Field name
* @ param { * } value Value to add
* @ param { boolean = } noAssert Whether to assert the value or not ( asserts by default )
* @ throws { Error } If the value cannot be added
* @ expose
* /
MessagePrototype . add = function ( key , value , noAssert ) {
var field = T . _fieldsByName [ key ] ;
if ( ! noAssert ) {
if ( ! field )
throw Error ( this + "#" + key + " is undefined" ) ;
if ( ! ( field instanceof ProtoBuf . Reflect . Message . Field ) )
throw Error ( this + "#" + key + " is not a field: " + field . toString ( true ) ) ; // May throw if it's an enum or embedded message
if ( ! field . repeated )
throw Error ( this + "#" + key + " is not a repeated field" ) ;
}
if ( this [ field . name ] === null )
this [ field . name ] = [ ] ;
this [ field . name ] . push ( noAssert ? value : field . verifyValue ( value , true ) ) ;
} ;
/ * *
* Adds a value to a repeated field . This is an alias for { @ link ProtoBuf . Builder . Message # add } .
* @ name ProtoBuf . Builder . Message # $add
* @ function
* @ param { string } key Field name
* @ param { * } value Value to add
* @ param { boolean = } noAssert Whether to assert the value or not ( asserts by default )
* @ throws { Error } If the value cannot be added
* @ expose
* /
MessagePrototype . $add = MessagePrototype . add ;
/ * *
* Sets a field ' s value .
* @ name ProtoBuf . Builder . Message # set
* @ function
* @ param { string } key Key
* @ param { * } value Value to set
* @ param { boolean = } noAssert Whether to not assert for an actual field / proper value type , defaults to ` false `
* @ returns { ! ProtoBuf . Builder . Message } this
* @ throws { Error } If the value cannot be set
* @ expose
* /
MessagePrototype . set = function ( key , value , noAssert ) {
if ( key && typeof key === 'object' ) {
for ( var i in key )
if ( key . hasOwnProperty ( i ) )
this . $set ( i , key [ i ] , noAssert ) ;
return this ;
}
var field = T . _fieldsByName [ key ] ;
if ( ! noAssert ) {
if ( ! field )
throw Error ( this + "#" + key + " is not a field: undefined" ) ;
if ( ! ( field instanceof ProtoBuf . Reflect . Message . Field ) )
throw Error ( this + "#" + key + " is not a field: " + field . toString ( true ) ) ;
this [ field . name ] = ( value = field . verifyValue ( value ) ) ; // May throw
} else {
this [ field . name ] = value ;
}
if ( field . oneof ) {
if ( value !== null ) {
if ( this [ field . oneof . name ] !== null )
this [ this [ field . oneof . name ] ] = null ; // Unset the previous (field name is the oneof field's value)
this [ field . oneof . name ] = field . name ;
} else if ( field . oneof . name === key )
this [ field . oneof . name ] = null ;
}
return this ;
} ;
/ * *
* Sets a field ' s value . This is an alias for [ @ link ProtoBuf . Builder . Message # set } .
* @ name ProtoBuf . Builder . Message # $set
* @ function
* @ param { string } key Key
* @ param { * } value Value to set
* @ param { boolean = } noAssert Whether to not assert the value , defaults to ` false `
* @ throws { Error } If the value cannot be set
* @ expose
* /
MessagePrototype . $set = MessagePrototype . set ;
/ * *
* Gets a field ' s value .
* @ name ProtoBuf . Builder . Message # get
* @ function
* @ param { string } key Key
* @ param { boolean = } noAssert Whether to not assert for an actual field , defaults to ` false `
* @ return { * } Value
* @ throws { Error } If there is no such field
* @ expose
* /
MessagePrototype . get = function ( key , noAssert ) {
if ( noAssert )
return this [ key ] ;
var field = T . _fieldsByName [ key ] ;
if ( ! field || ! ( field instanceof ProtoBuf . Reflect . Message . Field ) )
throw Error ( this + "#" + key + " is not a field: undefined" ) ;
if ( ! ( field instanceof ProtoBuf . Reflect . Message . Field ) )
throw Error ( this + "#" + key + " is not a field: " + field . toString ( true ) ) ;
return this [ field . name ] ;
} ;
/ * *
* Gets a field ' s value . This is an alias for { @ link ProtoBuf . Builder . Message # $get } .
* @ name ProtoBuf . Builder . Message # $get
* @ function
* @ param { string } key Key
* @ return { * } Value
* @ throws { Error } If there is no such field
* @ expose
* /
MessagePrototype . $get = MessagePrototype . get ;
// Getters and setters
for ( var i = 0 ; i < fields . length ; i ++ ) {
var field = fields [ i ] ;
// no setters for extension fields as these are named by their fqn
if ( field instanceof ProtoBuf . Reflect . Message . ExtensionField )
continue ;
if ( T . builder . options [ 'populateAccessors' ] )
( function ( field ) {
// set/get[SomeValue]
var Name = field . originalName . replace ( /(_[a-zA-Z])/g , function ( match ) {
return match . toUpperCase ( ) . replace ( '_' , '' ) ;
} ) ;
Name = Name . substring ( 0 , 1 ) . toUpperCase ( ) + Name . substring ( 1 ) ;
// set/get_[some_value] FIXME: Do we really need these?
var name = field . originalName . replace ( /([A-Z])/g , function ( match ) {
return "_" + match ;
} ) ;
/ * *
* The current field ' s unbound setter function .
* @ function
* @ param { * } value
* @ param { boolean = } noAssert
* @ returns { ! ProtoBuf . Builder . Message }
* @ inner
* /
var setter = function ( value , noAssert ) {
this [ field . name ] = noAssert ? value : field . verifyValue ( value ) ;
return this ;
} ;
/ * *
* The current field ' s unbound getter function .
* @ function
* @ returns { * }
* @ inner
* /
var getter = function ( ) {
return this [ field . name ] ;
} ;
/ * *
* Sets a value . This method is present for each field , but only if there is no name conflict with
* another field .
* @ name ProtoBuf . Builder . Message # set [ SomeField ]
* @ function
* @ param { * } value Value to set
* @ param { boolean = } noAssert Whether to not assert the value , defaults to ` false `
* @ returns { ! ProtoBuf . Builder . Message } this
* @ abstract
* @ throws { Error } If the value cannot be set
* /
if ( T . getChild ( "set" + Name ) === null )
MessagePrototype [ "set" + Name ] = setter ;
/ * *
* Sets a value . This method is present for each field , but only if there is no name conflict with
* another field .
* @ name ProtoBuf . Builder . Message # set _ [ some _field ]
* @ function
* @ param { * } value Value to set
* @ param { boolean = } noAssert Whether to not assert the value , defaults to ` false `
* @ returns { ! ProtoBuf . Builder . Message } this
* @ abstract
* @ throws { Error } If the value cannot be set
* /
if ( T . getChild ( "set_" + name ) === null )
MessagePrototype [ "set_" + name ] = setter ;
/ * *
* Gets a value . This method is present for each field , but only if there is no name conflict with
* another field .
* @ name ProtoBuf . Builder . Message # get [ SomeField ]
* @ function
* @ abstract
* @ return { * } The value
* /
if ( T . getChild ( "get" + Name ) === null )
MessagePrototype [ "get" + Name ] = getter ;
/ * *
* Gets a value . This method is present for each field , but only if there is no name conflict with
* another field .
* @ name ProtoBuf . Builder . Message # get _ [ some _field ]
* @ function
* @ return { * } The value
* @ abstract
* /
if ( T . getChild ( "get_" + name ) === null )
MessagePrototype [ "get_" + name ] = getter ;
} ) ( field ) ;
}
// En-/decoding
/ * *
* Encodes the message .
* @ name ProtoBuf . Builder . Message # $encode
* @ function
* @ param { ( ! ByteBuffer | boolean ) = } buffer ByteBuffer to encode to . Will create a new one and flip it if omitted .
* @ param { boolean = } noVerify Whether to not verify field values , defaults to ` false `
* @ return { ! ByteBuffer } Encoded message as a ByteBuffer
* @ throws { Error } If the message cannot be encoded or if required fields are missing . The later still
* returns the encoded ByteBuffer in the ` encoded ` property on the error .
* @ expose
* @ see ProtoBuf . Builder . Message # encode64
* @ see ProtoBuf . Builder . Message # encodeHex
* @ see ProtoBuf . Builder . Message # encodeAB
* /
MessagePrototype . encode = function ( buffer , noVerify ) {
if ( typeof buffer === 'boolean' )
noVerify = buffer ,
buffer = undefined ;
var isNew = false ;
if ( ! buffer )
buffer = new ByteBuffer ( ) ,
isNew = true ;
var le = buffer . littleEndian ;
try {
T . encode ( this , buffer . LE ( ) , noVerify ) ;
return ( isNew ? buffer . flip ( ) : buffer ) . LE ( le ) ;
} catch ( e ) {
buffer . LE ( le ) ;
throw ( e ) ;
}
} ;
/ * *
* Calculates the byte length of the message .
* @ name ProtoBuf . Builder . Message # calculate
* @ function
* @ returns { number } Byte length
* @ throws { Error } If the message cannot be calculated or if required fields are missing .
* @ expose
* /
MessagePrototype . calculate = function ( ) {
return T . calculate ( this ) ;
} ;
/ * *
* Encodes the varint32 length - delimited message .
* @ name ProtoBuf . Builder . Message # encodeDelimited
* @ function
* @ param { ( ! ByteBuffer | boolean ) = } buffer ByteBuffer to encode to . Will create a new one and flip it if omitted .
* @ return { ! ByteBuffer } Encoded message as a ByteBuffer
* @ throws { Error } If the message cannot be encoded or if required fields are missing . The later still
* returns the encoded ByteBuffer in the ` encoded ` property on the error .
* @ expose
* /
MessagePrototype . encodeDelimited = function ( buffer ) {
var isNew = false ;
if ( ! buffer )
buffer = new ByteBuffer ( ) ,
isNew = true ;
var enc = new ByteBuffer ( ) . LE ( ) ;
T . encode ( this , enc ) . flip ( ) ;
buffer . writeVarint32 ( enc . remaining ( ) ) ;
buffer . append ( enc ) ;
return isNew ? buffer . flip ( ) : buffer ;
} ;
/ * *
* Directly encodes the message to an ArrayBuffer .
* @ name ProtoBuf . Builder . Message # encodeAB
* @ function
* @ return { ArrayBuffer } Encoded message as ArrayBuffer
* @ throws { Error } If the message cannot be encoded or if required fields are missing . The later still
* returns the encoded ArrayBuffer in the ` encoded ` property on the error .
* @ expose
* /
MessagePrototype . encodeAB = function ( ) {
try {
return this . encode ( ) . toArrayBuffer ( ) ;
} catch ( e ) {
if ( e [ "encoded" ] ) e [ "encoded" ] = e [ "encoded" ] . toArrayBuffer ( ) ;
throw ( e ) ;
}
} ;
/ * *
* Returns the message as an ArrayBuffer . This is an alias for { @ link ProtoBuf . Builder . Message # encodeAB } .
* @ name ProtoBuf . Builder . Message # toArrayBuffer
* @ function
* @ return { ArrayBuffer } Encoded message as ArrayBuffer
* @ throws { Error } If the message cannot be encoded or if required fields are missing . The later still
* returns the encoded ArrayBuffer in the ` encoded ` property on the error .
* @ expose
* /
MessagePrototype . toArrayBuffer = MessagePrototype . encodeAB ;
/ * *
* Directly encodes the message to a node Buffer .
* @ name ProtoBuf . Builder . Message # encodeNB
* @ function
* @ return { ! Buffer }
* @ throws { Error } If the message cannot be encoded , not running under node . js or if required fields are
* missing . The later still returns the encoded node Buffer in the ` encoded ` property on the error .
* @ expose
* /
MessagePrototype . encodeNB = function ( ) {
try {
return this . encode ( ) . toBuffer ( ) ;
} catch ( e ) {
if ( e [ "encoded" ] ) e [ "encoded" ] = e [ "encoded" ] . toBuffer ( ) ;
throw ( e ) ;
}
} ;
/ * *
* Returns the message as a node Buffer . This is an alias for { @ link ProtoBuf . Builder . Message # encodeNB } .
* @ name ProtoBuf . Builder . Message # toBuffer
* @ function
* @ return { ! Buffer }
* @ throws { Error } If the message cannot be encoded or if required fields are missing . The later still
* returns the encoded node Buffer in the ` encoded ` property on the error .
* @ expose
* /
MessagePrototype . toBuffer = MessagePrototype . encodeNB ;
/ * *
* Directly encodes the message to a base64 encoded string .
* @ name ProtoBuf . Builder . Message # encode64
* @ function
* @ return { string } Base64 encoded string
* @ throws { Error } If the underlying buffer cannot be encoded or if required fields are missing . The later
* still returns the encoded base64 string in the ` encoded ` property on the error .
* @ expose
* /
MessagePrototype . encode64 = function ( ) {
try {
return this . encode ( ) . toBase64 ( ) ;
} catch ( e ) {
if ( e [ "encoded" ] ) e [ "encoded" ] = e [ "encoded" ] . toBase64 ( ) ;
throw ( e ) ;
}
} ;
/ * *
* Returns the message as a base64 encoded string . This is an alias for { @ link ProtoBuf . Builder . Message # encode64 } .
* @ name ProtoBuf . Builder . Message # toBase64
* @ function
* @ return { string } Base64 encoded string
* @ throws { Error } If the message cannot be encoded or if required fields are missing . The later still
* returns the encoded base64 string in the ` encoded ` property on the error .
* @ expose
* /
MessagePrototype . toBase64 = MessagePrototype . encode64 ;
/ * *
* Directly encodes the message to a hex encoded string .
* @ name ProtoBuf . Builder . Message # encodeHex
* @ function
* @ return { string } Hex encoded string
* @ throws { Error } If the underlying buffer cannot be encoded or if required fields are missing . The later
* still returns the encoded hex string in the ` encoded ` property on the error .
* @ expose
* /
MessagePrototype . encodeHex = function ( ) {
try {
return this . encode ( ) . toHex ( ) ;
} catch ( e ) {
if ( e [ "encoded" ] ) e [ "encoded" ] = e [ "encoded" ] . toHex ( ) ;
throw ( e ) ;
}
} ;
/ * *
* Returns the message as a hex encoded string . This is an alias for { @ link ProtoBuf . Builder . Message # encodeHex } .
* @ name ProtoBuf . Builder . Message # toHex
* @ function
* @ return { string } Hex encoded string
* @ throws { Error } If the message cannot be encoded or if required fields are missing . The later still
* returns the encoded hex string in the ` encoded ` property on the error .
* @ expose
* /
MessagePrototype . toHex = MessagePrototype . encodeHex ;
/ * *
* Clones a message object to a raw object .
* @ param { * } obj Object to clone
* @ param { boolean } includeBinaryAsBase64 Whether to include binary data as base64 strings or not
* @ returns { * } Cloned object
* @ inner
* /
function cloneRaw ( obj , includeBinaryAsBase64 ) {
var clone = { } ;
for ( var i in obj )
if ( obj . hasOwnProperty ( i ) ) {
if ( obj [ i ] === null || typeof obj [ i ] !== 'object' )
clone [ i ] = obj [ i ] ;
else if ( obj [ i ] instanceof ByteBuffer ) {
if ( includeBinaryAsBase64 )
clone [ i ] = obj [ i ] . toBase64 ( ) ;
} else // is a non-null object
clone [ i ] = cloneRaw ( obj [ i ] , includeBinaryAsBase64 ) ;
}
return clone ;
}
/ * *
* Returns the message ' s raw payload .
* @ param { boolean = } includeBinaryAsBase64 Whether to include binary data as base64 strings or not , defaults to ` false `
* @ returns { Object . < string , * > } Raw payload
* @ expose
* /
MessagePrototype . toRaw = function ( includeBinaryAsBase64 ) {
return cloneRaw ( this , ! ! includeBinaryAsBase64 ) ;
} ;
/ * *
* Decodes a message from the specified buffer or string .
* @ name ProtoBuf . Builder . Message . decode
* @ function
* @ param { ! ByteBuffer | ! ArrayBuffer | ! Buffer | string } buffer Buffer to decode from
* @ param { string = } enc Encoding if buffer is a string : hex , utf8 ( not recommended ) , defaults to base64
* @ return { ! ProtoBuf . Builder . Message } Decoded message
* @ throws { Error } If the message cannot be decoded or if required fields are missing . The later still
* returns the decoded message with missing fields in the ` decoded ` property on the error .
* @ expose
* @ see ProtoBuf . Builder . Message . decode64
* @ see ProtoBuf . Builder . Message . decodeHex
* /
Message . decode = function ( buffer , enc ) {
if ( typeof buffer === 'string' )
buffer = ByteBuffer . wrap ( buffer , enc ? enc : "base64" ) ;
buffer = buffer instanceof ByteBuffer ? buffer : ByteBuffer . wrap ( buffer ) ; // May throw
var le = buffer . littleEndian ;
try {
var msg = T . decode ( buffer . LE ( ) ) ;
buffer . LE ( le ) ;
return msg ;
} catch ( e ) {
buffer . LE ( le ) ;
throw ( e ) ;
}
} ;
/ * *
* Decodes a varint32 length - delimited message from the specified buffer or string .
* @ name ProtoBuf . Builder . Message . decodeDelimited
* @ function
* @ param { ! ByteBuffer | ! ArrayBuffer | ! Buffer | string } buffer Buffer to decode from
* @ param { string = } enc Encoding if buffer is a string : hex , utf8 ( not recommended ) , defaults to base64
* @ return { ProtoBuf . Builder . Message } Decoded message or ` null ` if not enough bytes are available yet
* @ throws { Error } If the message cannot be decoded or if required fields are missing . The later still
* returns the decoded message with missing fields in the ` decoded ` property on the error .
* @ expose
* /
Message . decodeDelimited = function ( buffer , enc ) {
if ( typeof buffer === 'string' )
buffer = ByteBuffer . wrap ( buffer , enc ? enc : "base64" ) ;
buffer = buffer instanceof ByteBuffer ? buffer : ByteBuffer . wrap ( buffer ) ; // May throw
if ( buffer . remaining ( ) < 1 )
return null ;
var off = buffer . offset ,
len = buffer . readVarint32 ( ) ;
if ( buffer . remaining ( ) < len ) {
buffer . offset = off ;
return null ;
}
try {
var msg = T . decode ( buffer . slice ( buffer . offset , buffer . offset + len ) . LE ( ) ) ;
buffer . offset += len ;
return msg ;
} catch ( err ) {
buffer . offset += len ;
throw err ;
}
} ;
/ * *
* Decodes the message from the specified base64 encoded string .
* @ name ProtoBuf . Builder . Message . decode64
* @ function
* @ param { string } str String to decode from
* @ return { ! ProtoBuf . Builder . Message } Decoded message
* @ throws { Error } If the message cannot be decoded or if required fields are missing . The later still
* returns the decoded message with missing fields in the ` decoded ` property on the error .
* @ expose
* /
Message . decode64 = function ( str ) {
return Message . decode ( str , "base64" ) ;
} ;
/ * *
* Decodes the message from the specified hex encoded string .
* @ name ProtoBuf . Builder . Message . decodeHex
* @ function
* @ param { string } str String to decode from
* @ return { ! ProtoBuf . Builder . Message } Decoded message
* @ throws { Error } If the message cannot be decoded or if required fields are missing . The later still
* returns the decoded message with missing fields in the ` decoded ` property on the error .
* @ expose
* /
Message . decodeHex = function ( str ) {
return Message . decode ( str , "hex" ) ;
} ;
// Utility
/ * *
* Returns a string representation of this Message .
* @ name ProtoBuf . Builder . Message # toString
* @ function
* @ return { string } String representation as of ".Fully.Qualified.MessageName"
* @ expose
* /
MessagePrototype . toString = function ( ) {
return T . toString ( ) ;
} ;
// Properties
/ * *
* Options .
* @ name ProtoBuf . Builder . Message . $options
* @ type { Object . < string , * > }
* @ expose
* /
var $options ; // cc
/ * *
* Reflection type .
* @ name ProtoBuf . Builder . Message # $type
* @ type { ! ProtoBuf . Reflect . Message }
* @ expose
* /
var $type ; // cc
if ( Object . defineProperty )
Object . defineProperty ( Message , '$options' , { "value" : T . buildOpt ( ) } ) ,
Object . defineProperty ( MessagePrototype , "$type" , {
get : function ( ) { return T ; }
} ) ;
return Message ;
} ) ( ProtoBuf , this ) ;
// Static enums and prototyped sub-messages / cached collections
this . _fields = [ ] ;
this . _fieldsById = { } ;
this . _fieldsByName = { } ;
for ( var i = 0 , k = this . children . length , child ; i < k ; i ++ ) {
child = this . children [ i ] ;
if ( child instanceof Enum )
clazz [ child . name ] = child . build ( ) ;
else if ( child instanceof Message )
clazz [ child . name ] = child . build ( ) ;
else if ( child instanceof Message . Field )
child . build ( ) ,
this . _fields . push ( child ) ,
this . _fieldsById [ child . id ] = child ,
this . _fieldsByName [ child . name ] = child ;
else if ( ! ( child instanceof Message . OneOf ) && ! ( child instanceof Extension ) ) // Not built
throw Error ( "Illegal reflect child of " + this . toString ( true ) + ": " + children [ i ] . toString ( true ) ) ;
}
return this . clazz = clazz ;
} ;
/ * *
* Encodes a runtime message ' s contents to the specified buffer .
* @ param { ! ProtoBuf . Builder . Message } message Runtime message to encode
* @ param { ByteBuffer } buffer ByteBuffer to write to
* @ param { boolean = } noVerify Whether to not verify field values , defaults to ` false `
* @ return { ByteBuffer } The ByteBuffer for chaining
* @ throws { Error } If required fields are missing or the message cannot be encoded for another reason
* @ expose
* /
MessagePrototype . encode = function ( message , buffer , noVerify ) {
var fieldMissing = null ,
field ;
for ( var i = 0 , k = this . _fields . length , val ; i < k ; ++ i ) {
field = this . _fields [ i ] ;
val = message [ field . name ] ;
if ( field . required && val === null ) {
if ( fieldMissing === null )
fieldMissing = field ;
} else
field . encode ( noVerify ? val : field . verifyValue ( val ) , buffer ) ;
}
if ( fieldMissing !== null ) {
var err = Error ( "Missing at least one required field for " + this . toString ( true ) + ": " + fieldMissing ) ;
err [ "encoded" ] = buffer ; // Still expose what we got
throw ( err ) ;
}
return buffer ;
} ;
/ * *
* Calculates a runtime message ' s byte length .
* @ param { ! ProtoBuf . Builder . Message } message Runtime message to encode
* @ returns { number } Byte length
* @ throws { Error } If required fields are missing or the message cannot be calculated for another reason
* @ expose
* /
MessagePrototype . calculate = function ( message ) {
for ( var n = 0 , i = 0 , k = this . _fields . length , field , val ; i < k ; ++ i ) {
field = this . _fields [ i ] ;
val = message [ field . name ] ;
if ( field . required && val === null )
throw Error ( "Missing at least one required field for " + this . toString ( true ) + ": " + field ) ;
else
n += field . calculate ( val ) ;
}
return n ;
} ;
/ * *
* Skips all data until the end of the specified group has been reached .
* @ param { number } expectedId Expected GROUPEND id
* @ param { ! ByteBuffer } buf ByteBuffer
* @ returns { boolean } ` true ` if a value as been skipped , ` false ` if the end has been reached
* @ throws { Error } If it wasn ' t possible to find the end of the group ( buffer overrun or end tag mismatch )
* @ inner
* /
function skipTillGroupEnd ( expectedId , buf ) {
var tag = buf . readVarint32 ( ) , // Throws on OOB
wireType = tag & 0x07 ,
id = tag >> 3 ;
switch ( wireType ) {
case ProtoBuf . WIRE _TYPES . VARINT :
do tag = buf . readUint8 ( ) ;
while ( ( tag & 0x80 ) === 0x80 ) ;
break ;
case ProtoBuf . WIRE _TYPES . BITS64 :
buf . offset += 8 ;
break ;
case ProtoBuf . WIRE _TYPES . LDELIM :
tag = buf . readVarint32 ( ) ; // reads the varint
buf . offset += tag ; // skips n bytes
break ;
case ProtoBuf . WIRE _TYPES . STARTGROUP :
skipTillGroupEnd ( id , buf ) ;
break ;
case ProtoBuf . WIRE _TYPES . ENDGROUP :
if ( id === expectedId )
return false ;
else
throw Error ( "Illegal GROUPEND after unknown group: " + id + " (" + expectedId + " expected)" ) ;
case ProtoBuf . WIRE _TYPES . BITS32 :
buf . offset += 4 ;
break ;
default :
throw Error ( "Illegal wire type in unknown group " + expectedId + ": " + wireType ) ;
}
return true ;
}
/ * *
* Decodes an encoded message and returns the decoded message .
* @ param { ByteBuffer } buffer ByteBuffer to decode from
* @ param { number = } length Message length . Defaults to decode all the available data .
* @ param { number = } expectedGroupEndId Expected GROUPEND id if this is a legacy group
* @ return { ProtoBuf . Builder . Message } Decoded message
* @ throws { Error } If the message cannot be decoded
* @ expose
* /
MessagePrototype . decode = function ( buffer , length , expectedGroupEndId ) {
length = typeof length === 'number' ? length : - 1 ;
var start = buffer . offset ,
msg = new ( this . clazz ) ( ) ,
tag , wireType , id , field ;
while ( buffer . offset < start + length || ( length === - 1 && buffer . remaining ( ) > 0 ) ) {
tag = buffer . readVarint32 ( ) ;
wireType = tag & 0x07 ;
id = tag >> 3 ;
if ( wireType === ProtoBuf . WIRE _TYPES . ENDGROUP ) {
if ( id !== expectedGroupEndId )
throw Error ( "Illegal group end indicator for " + this . toString ( true ) + ": " + id + " (" + ( expectedGroupEndId ? expectedGroupEndId + " expected" : "not a group" ) + ")" ) ;
break ;
}
if ( ! ( field = this . _fieldsById [ id ] ) ) {
// "messages created by your new code can be parsed by your old code: old binaries simply ignore the new field when parsing."
switch ( wireType ) {
case ProtoBuf . WIRE _TYPES . VARINT :
buffer . readVarint32 ( ) ;
break ;
case ProtoBuf . WIRE _TYPES . BITS32 :
buffer . offset += 4 ;
break ;
case ProtoBuf . WIRE _TYPES . BITS64 :
buffer . offset += 8 ;
break ;
case ProtoBuf . WIRE _TYPES . LDELIM :
var len = buffer . readVarint32 ( ) ;
buffer . offset += len ;
break ;
case ProtoBuf . WIRE _TYPES . STARTGROUP :
while ( skipTillGroupEnd ( id , buffer ) ) { }
break ;
default :
throw Error ( "Illegal wire type for unknown field " + id + " in " + this . toString ( true ) + "#decode: " + wireType ) ;
}
continue ;
}
if ( field . repeated && ! field . options [ "packed" ] )
msg [ field . name ] . push ( field . decode ( wireType , buffer ) ) ;
else {
msg [ field . name ] = field . decode ( wireType , buffer ) ;
if ( field . oneof ) {
if ( this [ field . oneof . name ] !== null )
this [ this [ field . oneof . name ] ] = null ;
msg [ field . oneof . name ] = field . name ;
}
}
}
// Check if all required fields are present and set default values for optional fields that are not
for ( var i = 0 , k = this . _fields . length ; i < k ; ++ i ) {
field = this . _fields [ i ] ;
if ( msg [ field . name ] === null )
if ( field . required ) {
var err = Error ( "Missing at least one required field for " + this . toString ( true ) + ": " + field . name ) ;
err [ "decoded" ] = msg ; // Still expose what we got
throw ( err ) ;
} else if ( field . defaultValue !== null )
msg [ field . name ] = field . defaultValue ;
}
return msg ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Message
* @ expose
* /
Reflect . Message = Message ;
/ * *
* Constructs a new Message Field .
* @ exports ProtoBuf . Reflect . Message . Field
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . Message } message Message reference
* @ param { string } rule Rule , one of requried , optional , repeated
* @ param { string } type Data type , e . g . int32
* @ param { string } name Field name
* @ param { number } id Unique field id
* @ param { Object . < string , * >= } options Options
* @ param { ! ProtoBuf . Reflect . Message . OneOf = } oneof Enclosing OneOf
* @ constructor
* @ extends ProtoBuf . Reflect . T
* /
var Field = function ( builder , message , rule , type , name , id , options , oneof ) {
T . call ( this , builder , message , name ) ;
/ * *
* @ override
* /
this . className = "Message.Field" ;
/ * *
* Message field required flag .
* @ type { boolean }
* @ expose
* /
this . required = rule === "required" ;
/ * *
* Message field repeated flag .
* @ type { boolean }
* @ expose
* /
this . repeated = rule === "repeated" ;
/ * *
* Message field type . Type reference string if unresolved , protobuf type if resolved .
* @ type { string | { name : string , wireType : number } }
* @ expose
* /
this . type = type ;
/ * *
* Resolved type reference inside the global namespace .
* @ type { ProtoBuf . Reflect . T | null }
* @ expose
* /
this . resolvedType = null ;
/ * *
* Unique message field id .
* @ type { number }
* @ expose
* /
this . id = id ;
/ * *
* Message field options .
* @ type { ! Object . < string , * > }
* @ dict
* @ expose
* /
this . options = options || { } ;
/ * *
* Default value .
* @ type { * }
* @ expose
* /
this . defaultValue = null ;
/ * *
* Enclosing OneOf .
* @ type { ? ProtoBuf . Reflect . Message . OneOf }
* @ expose
* /
this . oneof = oneof || null ;
/ * *
* Original field name .
* @ type { string }
* @ expose
* /
this . originalName = this . name ; // Used to revert camelcase transformation on naming collisions
// Convert field names to camel case notation if the override is set
if ( this . builder . options [ 'convertFieldsToCamelCase' ] && ! ( this instanceof Message . ExtensionField ) )
this . name = Field . _toCamelCase ( this . name ) ;
} ;
/ * *
* Converts a field name to camel case .
* @ param { string } name Likely underscore notated name
* @ returns { string } Camel case notated name
* @ private
* /
Field . _toCamelCase = function ( name ) {
return name . replace ( /_([a-zA-Z])/g , function ( $0 , $1 ) {
return $1 . toUpperCase ( ) ;
} ) ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Message . Field . prototype
* @ inner
* /
var FieldPrototype = Field . prototype = Object . create ( T . prototype ) ;
/ * *
* Builds the field .
* @ override
* @ expose
* /
FieldPrototype . build = function ( ) {
this . defaultValue = typeof this . options [ 'default' ] !== 'undefined'
? this . verifyValue ( this . options [ 'default' ] ) : null ;
} ;
/ * *
* Makes a Long from a value .
* @ param { { low : number , high : number , unsigned : boolean } | string | number } value Value
* @ param { boolean = } unsigned Whether unsigned or not , defaults to reuse it from Long - like objects or to signed for
* strings and numbers
* @ returns { ! Long }
* @ throws { Error } If the value cannot be converted to a Long
* @ inner
* /
function mkLong ( value , unsigned ) {
if ( value && typeof value . low === 'number' && typeof value . high === 'number' && typeof value . unsigned === 'boolean'
&& value . low === value . low && value . high === value . high )
return new ProtoBuf . Long ( value . low , value . high , typeof unsigned === 'undefined' ? value . unsigned : unsigned ) ;
if ( typeof value === 'string' )
return ProtoBuf . Long . fromString ( value , unsigned || false , 10 ) ;
if ( typeof value === 'number' )
return ProtoBuf . Long . fromNumber ( value , unsigned || false ) ;
throw Error ( "not convertible to Long" ) ;
}
/ * *
* Checks if the given value can be set for this field .
* @ param { * } value Value to check
* @ param { boolean = } skipRepeated Whether to skip the repeated value check or not . Defaults to false .
* @ return { * } Verified , maybe adjusted , value
* @ throws { Error } If the value cannot be set for this field
* @ expose
* /
FieldPrototype . verifyValue = function ( value , skipRepeated ) {
skipRepeated = skipRepeated || false ;
var fail = function ( val , msg ) {
throw Error ( "Illegal value for " + this . toString ( true ) + " of type " + this . type . name + ": " + val + " (" + msg + ")" ) ;
} . bind ( this ) ;
if ( value === null ) { // NULL values for optional fields
if ( this . required )
fail ( typeof value , "required" ) ;
return null ;
}
var i ;
if ( this . repeated && ! skipRepeated ) { // Repeated values as arrays
if ( ! ProtoBuf . Util . isArray ( value ) )
value = [ value ] ;
var res = [ ] ;
for ( i = 0 ; i < value . length ; i ++ )
res . push ( this . verifyValue ( value [ i ] , true ) ) ;
return res ;
}
// All non-repeated fields expect no array
if ( ! this . repeated && ProtoBuf . Util . isArray ( value ) )
fail ( typeof value , "no array expected" ) ;
switch ( this . type ) {
// Signed 32bit
case ProtoBuf . TYPES [ "int32" ] :
case ProtoBuf . TYPES [ "sint32" ] :
case ProtoBuf . TYPES [ "sfixed32" ] :
// Account for !NaN: value === value
if ( typeof value !== 'number' || ( value === value && value % 1 !== 0 ) )
fail ( typeof value , "not an integer" ) ;
return value > 4294967295 ? value | 0 : value ;
// Unsigned 32bit
case ProtoBuf . TYPES [ "uint32" ] :
case ProtoBuf . TYPES [ "fixed32" ] :
if ( typeof value !== 'number' || ( value === value && value % 1 !== 0 ) )
fail ( typeof value , "not an integer" ) ;
return value < 0 ? value >>> 0 : value ;
// Signed 64bit
case ProtoBuf . TYPES [ "int64" ] :
case ProtoBuf . TYPES [ "sint64" ] :
case ProtoBuf . TYPES [ "sfixed64" ] : {
if ( ProtoBuf . Long )
try {
return mkLong ( value , false ) ;
} catch ( e ) {
fail ( typeof value , e . message ) ;
}
else
fail ( typeof value , "requires Long.js" ) ;
}
// Unsigned 64bit
case ProtoBuf . TYPES [ "uint64" ] :
case ProtoBuf . TYPES [ "fixed64" ] : {
if ( ProtoBuf . Long )
try {
return mkLong ( value , true ) ;
} catch ( e ) {
fail ( typeof value , e . message ) ;
}
else
fail ( typeof value , "requires Long.js" ) ;
}
// Bool
case ProtoBuf . TYPES [ "bool" ] :
if ( typeof value !== 'boolean' )
fail ( typeof value , "not a boolean" ) ;
return value ;
// Float
case ProtoBuf . TYPES [ "float" ] :
case ProtoBuf . TYPES [ "double" ] :
if ( typeof value !== 'number' )
fail ( typeof value , "not a number" ) ;
return value ;
// Length-delimited string
case ProtoBuf . TYPES [ "string" ] :
if ( typeof value !== 'string' && ! ( value && value instanceof String ) )
fail ( typeof value , "not a string" ) ;
return "" + value ; // Convert String object to string
// Length-delimited bytes
case ProtoBuf . TYPES [ "bytes" ] :
if ( ByteBuffer . isByteBuffer ( value ) )
return value ;
return ByteBuffer . wrap ( value , "base64" ) ;
// Constant enum value
case ProtoBuf . TYPES [ "enum" ] : {
var values = this . resolvedType . getChildren ( Enum . Value ) ;
for ( i = 0 ; i < values . length ; i ++ )
if ( values [ i ] . name == value )
return values [ i ] . id ;
else if ( values [ i ] . id == value )
return values [ i ] . id ;
fail ( value , "not a valid enum value" ) ;
}
// Embedded message
case ProtoBuf . TYPES [ "group" ] :
case ProtoBuf . TYPES [ "message" ] : {
if ( ! value || typeof value !== 'object' )
fail ( typeof value , "object expected" ) ;
if ( value instanceof this . resolvedType . clazz )
return value ;
if ( value instanceof ProtoBuf . Builder . Message ) {
// Mismatched type: Convert to object (see: https://github.com/dcodeIO/ProtoBuf.js/issues/180)
var obj = { } ;
for ( var i in value )
if ( value . hasOwnProperty ( i ) )
obj [ i ] = value [ i ] ;
value = obj ;
}
// Else let's try to construct one from a key-value object
return new ( this . resolvedType . clazz ) ( value ) ; // May throw for a hundred of reasons
}
}
// We should never end here
throw Error ( "[INTERNAL] Illegal value for " + this . toString ( true ) + ": " + value + " (undefined type " + this . type + ")" ) ;
} ;
/ * *
* Encodes the specified field value to the specified buffer .
* @ param { * } value Verified field value
* @ param { ByteBuffer } buffer ByteBuffer to encode to
* @ return { ByteBuffer } The ByteBuffer for chaining
* @ throws { Error } If the field cannot be encoded
* @ expose
* /
FieldPrototype . encode = function ( value , buffer ) {
if ( this . type === null || typeof this . type !== 'object' )
throw Error ( "[INTERNAL] Unresolved type in " + this . toString ( true ) + ": " + this . type ) ;
if ( value === null || ( this . repeated && value . length == 0 ) )
return buffer ; // Optional omitted
try {
if ( this . repeated ) {
var i ;
// "Only repeated fields of primitive numeric types (types which use the varint, 32-bit, or 64-bit wire
// types) can be declared 'packed'."
if ( this . options [ "packed" ] && ProtoBuf . PACKABLE _WIRE _TYPES . indexOf ( this . type . wireType ) >= 0 ) {
// "All of the elements of the field are packed into a single key-value pair with wire type 2
// (length-delimited). Each element is encoded the same way it would be normally, except without a
// tag preceding it."
buffer . writeVarint32 ( ( this . id << 3 ) | ProtoBuf . WIRE _TYPES . LDELIM ) ;
buffer . ensureCapacity ( buffer . offset += 1 ) ; // We do not know the length yet, so let's assume a varint of length 1
var start = buffer . offset ; // Remember where the contents begin
for ( i = 0 ; i < value . length ; i ++ )
this . encodeValue ( value [ i ] , buffer ) ;
var len = buffer . offset - start ,
varintLen = ByteBuffer . calculateVarint32 ( len ) ;
if ( varintLen > 1 ) { // We need to move the contents
var contents = buffer . slice ( start , buffer . offset ) ;
start += varintLen - 1 ;
buffer . offset = start ;
buffer . append ( contents ) ;
}
buffer . writeVarint32 ( len , start - varintLen ) ;
} else {
// "If your message definition has repeated elements (without the [packed=true] option), the encoded
// message has zero or more key-value pairs with the same tag number"
for ( i = 0 ; i < value . length ; i ++ )
buffer . writeVarint32 ( ( this . id << 3 ) | this . type . wireType ) ,
this . encodeValue ( value [ i ] , buffer ) ;
}
} else
buffer . writeVarint32 ( ( this . id << 3 ) | this . type . wireType ) ,
this . encodeValue ( value , buffer ) ;
} catch ( e ) {
throw Error ( "Illegal value for " + this . toString ( true ) + ": " + value + " (" + e + ")" ) ;
}
return buffer ;
} ;
/ * *
* Encodes a value to the specified buffer . Does not encode the key .
* @ param { * } value Field value
* @ param { ByteBuffer } buffer ByteBuffer to encode to
* @ return { ByteBuffer } The ByteBuffer for chaining
* @ throws { Error } If the value cannot be encoded
* @ expose
* /
FieldPrototype . encodeValue = function ( value , buffer ) {
if ( value === null ) return buffer ; // Nothing to encode
// Tag has already been written
switch ( this . type ) {
// 32bit signed varint
case ProtoBuf . TYPES [ "int32" ] :
// "If you use int32 or int64 as the type for a negative number, the resulting varint is always ten bytes
// long – it is, effectively, treated like a very large unsigned integer." (see #122)
if ( value < 0 )
buffer . writeVarint64 ( value ) ;
else
buffer . writeVarint32 ( value ) ;
break ;
// 32bit unsigned varint
case ProtoBuf . TYPES [ "uint32" ] :
buffer . writeVarint32 ( value ) ;
break ;
// 32bit varint zig-zag
case ProtoBuf . TYPES [ "sint32" ] :
buffer . writeVarint32ZigZag ( value ) ;
break ;
// Fixed unsigned 32bit
case ProtoBuf . TYPES [ "fixed32" ] :
buffer . writeUint32 ( value ) ;
break ;
// Fixed signed 32bit
case ProtoBuf . TYPES [ "sfixed32" ] :
buffer . writeInt32 ( value ) ;
break ;
// 64bit varint as-is
case ProtoBuf . TYPES [ "int64" ] :
case ProtoBuf . TYPES [ "uint64" ] :
buffer . writeVarint64 ( value ) ; // throws
break ;
// 64bit varint zig-zag
case ProtoBuf . TYPES [ "sint64" ] :
buffer . writeVarint64ZigZag ( value ) ; // throws
break ;
// Fixed unsigned 64bit
case ProtoBuf . TYPES [ "fixed64" ] :
buffer . writeUint64 ( value ) ; // throws
break ;
// Fixed signed 64bit
case ProtoBuf . TYPES [ "sfixed64" ] :
buffer . writeInt64 ( value ) ; // throws
break ;
// Bool
case ProtoBuf . TYPES [ "bool" ] :
if ( typeof value === 'string' )
buffer . writeVarint32 ( value . toLowerCase ( ) === 'false' ? 0 : ! ! value ) ;
else
buffer . writeVarint32 ( value ? 1 : 0 ) ;
break ;
// Constant enum value
case ProtoBuf . TYPES [ "enum" ] :
buffer . writeVarint32 ( value ) ;
break ;
// 32bit float
case ProtoBuf . TYPES [ "float" ] :
buffer . writeFloat32 ( value ) ;
break ;
// 64bit float
case ProtoBuf . TYPES [ "double" ] :
buffer . writeFloat64 ( value ) ;
break ;
// Length-delimited string
case ProtoBuf . TYPES [ "string" ] :
buffer . writeVString ( value ) ;
break ;
// Length-delimited bytes
case ProtoBuf . TYPES [ "bytes" ] :
if ( value . remaining ( ) < 0 )
throw Error ( "Illegal value for " + this . toString ( true ) + ": " + value . remaining ( ) + " bytes remaining" ) ;
var prevOffset = value . offset ;
buffer . writeVarint32 ( value . remaining ( ) ) ;
buffer . append ( value ) ;
value . offset = prevOffset ;
break ;
// Embedded message
case ProtoBuf . TYPES [ "message" ] :
var bb = new ByteBuffer ( ) . LE ( ) ;
this . resolvedType . encode ( value , bb ) ;
buffer . writeVarint32 ( bb . offset ) ;
buffer . append ( bb . flip ( ) ) ;
break ;
// Legacy group
case ProtoBuf . TYPES [ "group" ] :
this . resolvedType . encode ( value , buffer ) ;
buffer . writeVarint32 ( ( this . id << 3 ) | ProtoBuf . WIRE _TYPES . ENDGROUP ) ;
break ;
default :
// We should never end here
throw Error ( "[INTERNAL] Illegal value to encode in " + this . toString ( true ) + ": " + value + " (unknown type)" ) ;
}
return buffer ;
} ;
/ * *
* Calculates the length of this field ' s value on the network level .
* @ param { * } value Field value
* @ returns { number } Byte length
* @ expose
* /
FieldPrototype . calculate = function ( value ) {
value = this . verifyValue ( value ) ; // May throw
if ( this . type === null || typeof this . type !== 'object' )
throw Error ( "[INTERNAL] Unresolved type in " + this . toString ( true ) + ": " + this . type ) ;
if ( value === null || ( this . repeated && value . length == 0 ) )
return 0 ; // Optional omitted
var n = 0 ;
try {
if ( this . repeated ) {
var i , ni ;
if ( this . options [ "packed" ] && ProtoBuf . PACKABLE _WIRE _TYPES . indexOf ( this . type . wireType ) >= 0 ) {
n += ByteBuffer . calculateVarint32 ( ( this . id << 3 ) | ProtoBuf . WIRE _TYPES . LDELIM ) ;
ni = 0 ;
for ( i = 0 ; i < value . length ; i ++ )
ni += this . calculateValue ( value [ i ] ) ;
n += ByteBuffer . calculateVarint32 ( ni ) ;
n += ni ;
} else {
for ( i = 0 ; i < value . length ; i ++ )
n += ByteBuffer . calculateVarint32 ( ( this . id << 3 ) | this . type . wireType ) ,
n += this . calculateValue ( value [ i ] ) ;
}
} else {
n += ByteBuffer . calculateVarint32 ( ( this . id << 3 ) | this . type . wireType ) ;
n += this . calculateValue ( value ) ;
}
} catch ( e ) {
throw Error ( "Illegal value for " + this . toString ( true ) + ": " + value + " (" + e + ")" ) ;
}
return n ;
} ;
/ * *
* Calculates the byte length of a value .
* @ param { * } value Field value
* @ returns { number } Byte length
* @ throws { Error } If the value cannot be calculated
* @ expose
* /
FieldPrototype . calculateValue = function ( value ) {
if ( value === null ) return 0 ; // Nothing to encode
// Tag has already been written
var n ;
switch ( this . type ) {
case ProtoBuf . TYPES [ "int32" ] :
return value < 0 ? ByteBuffer . calculateVarint64 ( value ) : ByteBuffer . calculateVarint32 ( value ) ;
case ProtoBuf . TYPES [ "uint32" ] :
return ByteBuffer . calculateVarint32 ( value ) ;
case ProtoBuf . TYPES [ "sint32" ] :
return ByteBuffer . calculateVarint32 ( ByteBuffer . zigZagEncode32 ( value ) ) ;
case ProtoBuf . TYPES [ "fixed32" ] :
case ProtoBuf . TYPES [ "sfixed32" ] :
case ProtoBuf . TYPES [ "float" ] :
return 4 ;
case ProtoBuf . TYPES [ "int64" ] :
case ProtoBuf . TYPES [ "uint64" ] :
return ByteBuffer . calculateVarint64 ( value ) ;
case ProtoBuf . TYPES [ "sint64" ] :
return ByteBuffer . calculateVarint64 ( ByteBuffer . zigZagEncode64 ( value ) ) ;
case ProtoBuf . TYPES [ "fixed64" ] :
case ProtoBuf . TYPES [ "sfixed64" ] :
return 8 ;
case ProtoBuf . TYPES [ "bool" ] :
return 1 ;
case ProtoBuf . TYPES [ "enum" ] :
return ByteBuffer . calculateVarint32 ( value ) ;
case ProtoBuf . TYPES [ "double" ] :
return 8 ;
case ProtoBuf . TYPES [ "string" ] :
n = ByteBuffer . calculateUTF8Bytes ( value ) ;
return ByteBuffer . calculateVarint32 ( n ) + n ;
case ProtoBuf . TYPES [ "bytes" ] :
if ( value . remaining ( ) < 0 )
throw Error ( "Illegal value for " + this . toString ( true ) + ": " + value . remaining ( ) + " bytes remaining" ) ;
return ByteBuffer . calculateVarint32 ( value . remaining ( ) ) + value . remaining ( ) ;
case ProtoBuf . TYPES [ "message" ] :
n = this . resolvedType . calculate ( value ) ;
return ByteBuffer . calculateVarint32 ( n ) + n ;
case ProtoBuf . TYPES [ "group" ] :
n = this . resolvedType . calculate ( value ) ;
return n + ByteBuffer . calculateVarint32 ( ( this . id << 3 ) | ProtoBuf . WIRE _TYPES . ENDGROUP ) ;
}
// We should never end here
throw Error ( "[INTERNAL] Illegal value to encode in " + this . toString ( true ) + ": " + value + " (unknown type)" ) ;
} ;
/ * *
* Decode the field value from the specified buffer .
* @ param { number } wireType Leading wire type
* @ param { ByteBuffer } buffer ByteBuffer to decode from
* @ param { boolean = } skipRepeated Whether to skip the repeated check or not . Defaults to false .
* @ return { * } Decoded value
* @ throws { Error } If the field cannot be decoded
* @ expose
* /
FieldPrototype . decode = function ( wireType , buffer , skipRepeated ) {
var value , nBytes ;
if ( wireType != this . type . wireType && ( skipRepeated || ( wireType != ProtoBuf . WIRE _TYPES . LDELIM || ! this . repeated ) ) )
throw Error ( "Illegal wire type for field " + this . toString ( true ) + ": " + wireType + " (" + this . type . wireType + " expected)" ) ;
if ( wireType == ProtoBuf . WIRE _TYPES . LDELIM && this . repeated && this . options [ "packed" ] && ProtoBuf . PACKABLE _WIRE _TYPES . indexOf ( this . type . wireType ) >= 0 ) {
if ( ! skipRepeated ) {
nBytes = buffer . readVarint32 ( ) ;
nBytes = buffer . offset + nBytes ; // Limit
var values = [ ] ;
while ( buffer . offset < nBytes )
values . push ( this . decode ( this . type . wireType , buffer , true ) ) ;
return values ;
}
// Read the next value otherwise...
}
switch ( this . type ) {
// 32bit signed varint
case ProtoBuf . TYPES [ "int32" ] :
return buffer . readVarint32 ( ) | 0 ;
// 32bit unsigned varint
case ProtoBuf . TYPES [ "uint32" ] :
return buffer . readVarint32 ( ) >>> 0 ;
// 32bit signed varint zig-zag
case ProtoBuf . TYPES [ "sint32" ] :
return buffer . readVarint32ZigZag ( ) | 0 ;
// Fixed 32bit unsigned
case ProtoBuf . TYPES [ "fixed32" ] :
return buffer . readUint32 ( ) >>> 0 ;
case ProtoBuf . TYPES [ "sfixed32" ] :
return buffer . readInt32 ( ) | 0 ;
// 64bit signed varint
case ProtoBuf . TYPES [ "int64" ] :
return buffer . readVarint64 ( ) ;
// 64bit unsigned varint
case ProtoBuf . TYPES [ "uint64" ] :
return buffer . readVarint64 ( ) . toUnsigned ( ) ;
// 64bit signed varint zig-zag
case ProtoBuf . TYPES [ "sint64" ] :
return buffer . readVarint64ZigZag ( ) ;
// Fixed 64bit unsigned
case ProtoBuf . TYPES [ "fixed64" ] :
return buffer . readUint64 ( ) ;
// Fixed 64bit signed
case ProtoBuf . TYPES [ "sfixed64" ] :
return buffer . readInt64 ( ) ;
// Bool varint
case ProtoBuf . TYPES [ "bool" ] :
return ! ! buffer . readVarint32 ( ) ;
// Constant enum value (varint)
case ProtoBuf . TYPES [ "enum" ] :
// The following Builder.Message#set will already throw
return buffer . readVarint32 ( ) ;
// 32bit float
case ProtoBuf . TYPES [ "float" ] :
return buffer . readFloat ( ) ;
// 64bit float
case ProtoBuf . TYPES [ "double" ] :
return buffer . readDouble ( ) ;
// Length-delimited string
case ProtoBuf . TYPES [ "string" ] :
return buffer . readVString ( ) ;
// Length-delimited bytes
case ProtoBuf . TYPES [ "bytes" ] : {
nBytes = buffer . readVarint32 ( ) ;
if ( buffer . remaining ( ) < nBytes )
throw Error ( "Illegal number of bytes for " + this . toString ( true ) + ": " + nBytes + " required but got only " + buffer . remaining ( ) ) ;
value = buffer . clone ( ) ; // Offset already set
value . limit = value . offset + nBytes ;
buffer . offset += nBytes ;
return value ;
}
// Length-delimited embedded message
case ProtoBuf . TYPES [ "message" ] : {
nBytes = buffer . readVarint32 ( ) ;
return this . resolvedType . decode ( buffer , nBytes ) ;
}
// Legacy group
case ProtoBuf . TYPES [ "group" ] :
return this . resolvedType . decode ( buffer , - 1 , this . id ) ;
}
// We should never end here
throw Error ( "[INTERNAL] Illegal wire type for " + this . toString ( true ) + ": " + wireType ) ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Message . Field
* @ expose
* /
Reflect . Message . Field = Field ;
/ * *
* Constructs a new Message ExtensionField .
* @ exports ProtoBuf . Reflect . Message . ExtensionField
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . Message } message Message reference
* @ param { string } rule Rule , one of requried , optional , repeated
* @ param { string } type Data type , e . g . int32
* @ param { string } name Field name
* @ param { number } id Unique field id
* @ param { Object . < string , * >= } options Options
* @ constructor
* @ extends ProtoBuf . Reflect . Message . Field
* /
var ExtensionField = function ( builder , message , rule , type , name , id , options ) {
Field . call ( this , builder , message , rule , type , name , id , options ) ;
/ * *
* Extension reference .
* @ type { ! ProtoBuf . Reflect . Extension }
* @ expose
* /
this . extension ;
} ;
// Extends Field
ExtensionField . prototype = Object . create ( Field . prototype ) ;
/ * *
* @ alias ProtoBuf . Reflect . Message . ExtensionField
* @ expose
* /
Reflect . Message . ExtensionField = ExtensionField ;
/ * *
* Constructs a new Message OneOf .
* @ exports ProtoBuf . Reflect . Message . OneOf
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . Message } message Message reference
* @ param { string } name OneOf name
* @ constructor
* @ extends ProtoBuf . Reflect . T
* /
var OneOf = function ( builder , message , name ) {
T . call ( this , builder , message , name ) ;
/ * *
* Enclosed fields .
* @ type { ! Array . < ! ProtoBuf . Reflect . Message . Field > }
* @ expose
* /
this . fields = [ ] ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Message . OneOf
* @ expose
* /
Reflect . Message . OneOf = OneOf ;
/ * *
* Constructs a new Enum .
* @ exports ProtoBuf . Reflect . Enum
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . T } parent Parent Reflect object
* @ param { string } name Enum name
* @ param { Object . < string , * >= } options Enum options
* @ constructor
* @ extends ProtoBuf . Reflect . Namespace
* /
var Enum = function ( builder , parent , name , options ) {
Namespace . call ( this , builder , parent , name , options ) ;
/ * *
* @ override
* /
this . className = "Enum" ;
/ * *
* Runtime enum object .
* @ type { Object . < string , number > | null }
* @ expose
* /
this . object = null ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Enum . prototype
* @ inner
* /
var EnumPrototype = Enum . prototype = Object . create ( Namespace . prototype ) ;
/ * *
* Builds this enum and returns the runtime counterpart .
* @ return { Object < string , * > }
* @ expose
* /
EnumPrototype . build = function ( ) {
var enm = { } ,
values = this . getChildren ( Enum . Value ) ;
for ( var i = 0 , k = values . length ; i < k ; ++ i )
enm [ values [ i ] [ 'name' ] ] = values [ i ] [ 'id' ] ;
if ( Object . defineProperty )
Object . defineProperty ( enm , '$options' , { "value" : this . buildOpt ( ) } ) ;
return this . object = enm ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Enum
* @ expose
* /
Reflect . Enum = Enum ;
/ * *
* Constructs a new Enum Value .
* @ exports ProtoBuf . Reflect . Enum . Value
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . Enum } enm Enum reference
* @ param { string } name Field name
* @ param { number } id Unique field id
* @ constructor
* @ extends ProtoBuf . Reflect . T
* /
var Value = function ( builder , enm , name , id ) {
T . call ( this , builder , enm , name ) ;
/ * *
* @ override
* /
this . className = "Enum.Value" ;
/ * *
* Unique enum value id .
* @ type { number }
* @ expose
* /
this . id = id ;
} ;
// Extends T
Value . prototype = Object . create ( T . prototype ) ;
/ * *
* @ alias ProtoBuf . Reflect . Enum . Value
* @ expose
* /
Reflect . Enum . Value = Value ;
/ * *
* An extension ( field ) .
* @ exports ProtoBuf . Reflect . Extension
* @ constructor
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . T } parent Parent object
* @ param { string } name Object name
* @ param { ! ProtoBuf . Reflect . Message . Field } field Extension field
* /
var Extension = function ( builder , parent , name , field ) {
T . call ( this , builder , parent , name ) ;
/ * *
* Extended message field .
* @ type { ! ProtoBuf . Reflect . Message . Field }
* @ expose
* /
this . field = field ;
} ;
// Extends T
Extension . prototype = Object . create ( T . prototype ) ;
/ * *
* @ alias ProtoBuf . Reflect . Extension
* @ expose
* /
Reflect . Extension = Extension ;
/ * *
* Constructs a new Service .
* @ exports ProtoBuf . Reflect . Service
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . Namespace } root Root
* @ param { string } name Service name
* @ param { Object . < string , * >= } options Options
* @ constructor
* @ extends ProtoBuf . Reflect . Namespace
* /
var Service = function ( builder , root , name , options ) {
Namespace . call ( this , builder , root , name , options ) ;
/ * *
* @ override
* /
this . className = "Service" ;
/ * *
* Built runtime service class .
* @ type { ? function ( new : ProtoBuf . Builder . Service ) }
* /
this . clazz = null ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Service . prototype
* @ inner
* /
var ServicePrototype = Service . prototype = Object . create ( Namespace . prototype ) ;
/ * *
* Builds the service and returns the runtime counterpart , which is a fully functional class .
* @ see ProtoBuf . Builder . Service
* @ param { boolean = } rebuild Whether to rebuild or not
* @ return { Function } Service class
* @ throws { Error } If the message cannot be built
* @ expose
* /
ServicePrototype . build = function ( rebuild ) {
if ( this . clazz && ! rebuild )
return this . clazz ;
// Create the runtime Service class in its own scope
return this . clazz = ( function ( ProtoBuf , T ) {
/ * *
* Constructs a new runtime Service .
* @ name ProtoBuf . Builder . Service
* @ param { function ( string , ProtoBuf . Builder . Message , function ( Error , ProtoBuf . Builder . Message = ) ) = } rpcImpl RPC implementation receiving the method name and the message
* @ class Barebone of all runtime services .
* @ constructor
* @ throws { Error } If the service cannot be created
* /
var Service = function ( rpcImpl ) {
ProtoBuf . Builder . Service . call ( this ) ;
/ * *
* Service implementation .
* @ name ProtoBuf . Builder . Service # rpcImpl
* @ type { ! function ( string , ProtoBuf . Builder . Message , function ( Error , ProtoBuf . Builder . Message = ) ) }
* @ expose
* /
this . rpcImpl = rpcImpl || function ( name , msg , callback ) {
// This is what a user has to implement: A function receiving the method name, the actual message to
// send (type checked) and the callback that's either provided with the error as its first
// argument or null and the actual response message.
setTimeout ( callback . bind ( this , Error ( "Not implemented, see: https://github.com/dcodeIO/ProtoBuf.js/wiki/Services" ) ) , 0 ) ; // Must be async!
} ;
} ;
/ * *
* @ alias ProtoBuf . Builder . Service . prototype
* @ inner
* /
var ServicePrototype = Service . prototype = Object . create ( ProtoBuf . Builder . Service . prototype ) ;
if ( Object . defineProperty )
Object . defineProperty ( Service , "$options" , { "value" : T . buildOpt ( ) } ) ,
Object . defineProperty ( ServicePrototype , "$options" , { "value" : Service [ "$options" ] } ) ;
/ * *
* Asynchronously performs an RPC call using the given RPC implementation .
* @ name ProtoBuf . Builder . Service . [ Method ]
* @ function
* @ param { ! function ( string , ProtoBuf . Builder . Message , function ( Error , ProtoBuf . Builder . Message = ) ) } rpcImpl RPC implementation
* @ param { ProtoBuf . Builder . Message } req Request
* @ param { function ( Error , ( ProtoBuf . Builder . Message | ByteBuffer | Buffer | string ) = ) } callback Callback receiving
* the error if any and the response either as a pre - parsed message or as its raw bytes
* @ abstract
* /
/ * *
* Asynchronously performs an RPC call using the instance ' s RPC implementation .
* @ name ProtoBuf . Builder . Service # [ Method ]
* @ function
* @ param { ProtoBuf . Builder . Message } req Request
* @ param { function ( Error , ( ProtoBuf . Builder . Message | ByteBuffer | Buffer | string ) = ) } callback Callback receiving
* the error if any and the response either as a pre - parsed message or as its raw bytes
* @ abstract
* /
var rpc = T . getChildren ( ProtoBuf . Reflect . Service . RPCMethod ) ;
for ( var i = 0 ; i < rpc . length ; i ++ ) {
( function ( method ) {
// service#Method(message, callback)
ServicePrototype [ method . name ] = function ( req , callback ) {
try {
if ( ! req || ! ( req instanceof method . resolvedRequestType . clazz ) ) {
setTimeout ( callback . bind ( this , Error ( "Illegal request type provided to service method " + T . name + "#" + method . name ) ) , 0 ) ;
return ;
}
this . rpcImpl ( method . fqn ( ) , req , function ( err , res ) { // Assumes that this is properly async
if ( err ) {
callback ( err ) ;
return ;
}
try { res = method . resolvedResponseType . clazz . decode ( res ) ; } catch ( notABuffer ) { }
if ( ! res || ! ( res instanceof method . resolvedResponseType . clazz ) ) {
callback ( Error ( "Illegal response type received in service method " + T . name + "#" + method . name ) ) ;
return ;
}
callback ( null , res ) ;
} ) ;
} catch ( err ) {
setTimeout ( callback . bind ( this , err ) , 0 ) ;
}
} ;
// Service.Method(rpcImpl, message, callback)
Service [ method . name ] = function ( rpcImpl , req , callback ) {
new Service ( rpcImpl ) [ method . name ] ( req , callback ) ;
} ;
if ( Object . defineProperty )
Object . defineProperty ( Service [ method . name ] , "$options" , { "value" : method . buildOpt ( ) } ) ,
Object . defineProperty ( ServicePrototype [ method . name ] , "$options" , { "value" : Service [ method . name ] [ "$options" ] } ) ;
} ) ( rpc [ i ] ) ;
}
return Service ;
} ) ( ProtoBuf , this ) ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Service
* @ expose
* /
Reflect . Service = Service ;
/ * *
* Abstract service method .
* @ exports ProtoBuf . Reflect . Service . Method
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . Service } svc Service
* @ param { string } name Method name
* @ param { Object . < string , * >= } options Options
* @ constructor
* @ extends ProtoBuf . Reflect . T
* /
var Method = function ( builder , svc , name , options ) {
T . call ( this , builder , svc , name ) ;
/ * *
* @ override
* /
this . className = "Service.Method" ;
/ * *
* Options .
* @ type { Object . < string , * > }
* @ expose
* /
this . options = options || { } ;
} ;
/ * *
* @ alias ProtoBuf . Reflect . Service . Method . prototype
* @ inner
* /
var MethodPrototype = Method . prototype = Object . create ( T . prototype ) ;
/ * *
* Builds the method 's ' $options ' property .
* @ name ProtoBuf . Reflect . Service . Method # buildOpt
* @ function
* @ return { Object . < string , * > }
* /
MethodPrototype . buildOpt = NamespacePrototype . buildOpt ;
/ * *
* @ alias ProtoBuf . Reflect . Service . Method
* @ expose
* /
Reflect . Service . Method = Method ;
/ * *
* RPC service method .
* @ exports ProtoBuf . Reflect . Service . RPCMethod
* @ param { ! ProtoBuf . Builder } builder Builder reference
* @ param { ! ProtoBuf . Reflect . Service } svc Service
* @ param { string } name Method name
* @ param { string } request Request message name
* @ param { string } response Response message name
* @ param { Object . < string , * >= } options Options
* @ constructor
* @ extends ProtoBuf . Reflect . Service . Method
* /
var RPCMethod = function ( builder , svc , name , request , response , options ) {
Method . call ( this , builder , svc , name , options ) ;
/ * *
* @ override
* /
this . className = "Service.RPCMethod" ;
/ * *
* Request message name .
* @ type { string }
* @ expose
* /
this . requestName = request ;
/ * *
* Response message name .
* @ type { string }
* @ expose
* /
this . responseName = response ;
/ * *
* Resolved request message type .
* @ type { ProtoBuf . Reflect . Message }
* @ expose
* /
this . resolvedRequestType = null ;
/ * *
* Resolved response message type .
* @ type { ProtoBuf . Reflect . Message }
* @ expose
* /
this . resolvedResponseType = null ;
} ;
// Extends Method
RPCMethod . prototype = Object . create ( Method . prototype ) ;
/ * *
* @ alias ProtoBuf . Reflect . Service . RPCMethod
* @ expose
* /
Reflect . Service . RPCMethod = RPCMethod ;
return Reflect ;
} ) ( ProtoBuf ) ;
/ * *
* @ alias ProtoBuf . Builder
* @ expose
* /
ProtoBuf . Builder = ( function ( ProtoBuf , Lang , Reflect ) {
"use strict" ;
/ * *
* Constructs a new Builder .
* @ exports ProtoBuf . Builder
* @ class Provides the functionality to build protocol messages .
* @ param { Object . < string , * >= } options Options
* @ constructor
* /
var Builder = function ( options ) {
/ * *
* Namespace .
* @ type { ProtoBuf . Reflect . Namespace }
* @ expose
* /
this . ns = new Reflect . Namespace ( this , null , "" ) ; // Global namespace
/ * *
* Namespace pointer .
* @ type { ProtoBuf . Reflect . T }
* @ expose
* /
this . ptr = this . ns ;
/ * *
* Resolved flag .
* @ type { boolean }
* @ expose
* /
this . resolved = false ;
/ * *
* The current building result .
* @ type { Object . < string , ProtoBuf . Builder . Message | Object > | null }
* @ expose
* /
this . result = null ;
/ * *
* Imported files .
* @ type { Array . < string > }
* @ expose
* /
this . files = { } ;
/ * *
* Import root override .
* @ type { ? string }
* @ expose
* /
this . importRoot = null ;
/ * *
* Options .
* @ type { ! Object . < string , * > }
* @ expose
* /
this . options = options || { } ;
} ;
/ * *
* @ alias ProtoBuf . Builder . prototype
* @ inner
* /
var BuilderPrototype = Builder . prototype ;
/ * *
* Resets the pointer to the root namespace .
* @ expose
* /
BuilderPrototype . reset = function ( ) {
this . ptr = this . ns ;
} ;
/ * *
* Defines a package on top of the current pointer position and places the pointer on it .
* @ param { string } pkg
* @ param { Object . < string , * >= } options
* @ return { ProtoBuf . Builder } this
* @ throws { Error } If the package name is invalid
* @ expose
* /
BuilderPrototype . define = function ( pkg , options ) {
if ( typeof pkg !== 'string' || ! Lang . TYPEREF . test ( pkg ) )
throw Error ( "Illegal package: " + pkg ) ;
var part = pkg . split ( "." ) , i ;
for ( i = 0 ; i < part . length ; i ++ ) // To be absolutely sure
if ( ! Lang . NAME . test ( part [ i ] ) )
throw Error ( "Illegal package: " + part [ i ] ) ;
for ( i = 0 ; i < part . length ; i ++ ) {
if ( this . ptr . getChild ( part [ i ] ) === null ) // Keep existing namespace
this . ptr . addChild ( new Reflect . Namespace ( this , this . ptr , part [ i ] , options ) ) ;
this . ptr = this . ptr . getChild ( part [ i ] ) ;
}
return this ;
} ;
/ * *
* Tests if a definition is a valid message definition .
* @ param { Object . < string , * > } def Definition
* @ return { boolean } true if valid , else false
* @ expose
* /
Builder . isValidMessage = function ( def ) {
// Messages require a string name
if ( typeof def [ "name" ] !== 'string' || ! Lang . NAME . test ( def [ "name" ] ) )
return false ;
// Messages must not contain values (that'd be an enum) or methods (that'd be a service)
if ( typeof def [ "values" ] !== 'undefined' || typeof def [ "rpc" ] !== 'undefined' )
return false ;
// Fields, enums and messages are arrays if provided
var i ;
if ( typeof def [ "fields" ] !== 'undefined' ) {
if ( ! ProtoBuf . Util . isArray ( def [ "fields" ] ) )
return false ;
var ids = [ ] , id ; // IDs must be unique
for ( i = 0 ; i < def [ "fields" ] . length ; i ++ ) {
if ( ! Builder . isValidMessageField ( def [ "fields" ] [ i ] ) )
return false ;
id = parseInt ( def [ "fields" ] [ i ] [ "id" ] , 10 ) ;
if ( ids . indexOf ( id ) >= 0 )
return false ;
ids . push ( id ) ;
}
ids = null ;
}
if ( typeof def [ "enums" ] !== 'undefined' ) {
if ( ! ProtoBuf . Util . isArray ( def [ "enums" ] ) )
return false ;
for ( i = 0 ; i < def [ "enums" ] . length ; i ++ )
if ( ! Builder . isValidEnum ( def [ "enums" ] [ i ] ) )
return false ;
}
if ( typeof def [ "messages" ] !== 'undefined' ) {
if ( ! ProtoBuf . Util . isArray ( def [ "messages" ] ) )
return false ;
for ( i = 0 ; i < def [ "messages" ] . length ; i ++ )
if ( ! Builder . isValidMessage ( def [ "messages" ] [ i ] ) && ! Builder . isValidExtend ( def [ "messages" ] [ i ] ) )
return false ;
}
if ( typeof def [ "extensions" ] !== 'undefined' )
if ( ! ProtoBuf . Util . isArray ( def [ "extensions" ] ) || def [ "extensions" ] . length !== 2 || typeof def [ "extensions" ] [ 0 ] !== 'number' || typeof def [ "extensions" ] [ 1 ] !== 'number' )
return false ;
return true ;
} ;
/ * *
* Tests if a definition is a valid message field definition .
* @ param { Object } def Definition
* @ return { boolean } true if valid , else false
* @ expose
* /
Builder . isValidMessageField = function ( def ) {
// Message fields require a string rule, name and type and an id
if ( typeof def [ "rule" ] !== 'string' || typeof def [ "name" ] !== 'string' || typeof def [ "type" ] !== 'string' || typeof def [ "id" ] === 'undefined' )
return false ;
if ( ! Lang . RULE . test ( def [ "rule" ] ) || ! Lang . NAME . test ( def [ "name" ] ) || ! Lang . TYPEREF . test ( def [ "type" ] ) || ! Lang . ID . test ( "" + def [ "id" ] ) )
return false ;
if ( typeof def [ "options" ] !== 'undefined' ) {
// Options are objects
if ( typeof def [ "options" ] !== 'object' )
return false ;
// Options are <string,string|number|boolean>
var keys = Object . keys ( def [ "options" ] ) ;
for ( var i = 0 , key ; i < keys . length ; i ++ )
if ( typeof ( key = keys [ i ] ) !== 'string' || ( typeof def [ "options" ] [ key ] !== 'string' && typeof def [ "options" ] [ key ] !== 'number' && typeof def [ "options" ] [ key ] !== 'boolean' ) )
return false ;
}
return true ;
} ;
/ * *
* Tests if a definition is a valid enum definition .
* @ param { Object } def Definition
* @ return { boolean } true if valid , else false
* @ expose
* /
Builder . isValidEnum = function ( def ) {
// Enums require a string name
if ( typeof def [ "name" ] !== 'string' || ! Lang . NAME . test ( def [ "name" ] ) )
return false ;
// Enums require at least one value
if ( typeof def [ "values" ] === 'undefined' || ! ProtoBuf . Util . isArray ( def [ "values" ] ) || def [ "values" ] . length == 0 )
return false ;
for ( var i = 0 ; i < def [ "values" ] . length ; i ++ ) {
// Values are objects
if ( typeof def [ "values" ] [ i ] != "object" )
return false ;
// Values require a string name and an id
if ( typeof def [ "values" ] [ i ] [ "name" ] !== 'string' || typeof def [ "values" ] [ i ] [ "id" ] === 'undefined' )
return false ;
if ( ! Lang . NAME . test ( def [ "values" ] [ i ] [ "name" ] ) || ! Lang . NEGID . test ( "" + def [ "values" ] [ i ] [ "id" ] ) )
return false ;
}
// It's not important if there are other fields because ["values"] is already unique
return true ;
} ;
/ * *
* Creates ths specified protocol types at the current pointer position .
* @ param { Array . < Object . < string , * >> } defs Messages , enums or services to create
* @ return { ProtoBuf . Builder } this
* @ throws { Error } If a message definition is invalid
* @ expose
* /
BuilderPrototype . create = function ( defs ) {
if ( ! defs )
return this ; // Nothing to create
if ( ! ProtoBuf . Util . isArray ( defs ) )
defs = [ defs ] ;
if ( defs . length == 0 )
return this ;
// It's quite hard to keep track of scopes and memory here, so let's do this iteratively.
var stack = [ ] ;
stack . push ( defs ) ; // One level [a, b, c]
while ( stack . length > 0 ) {
defs = stack . pop ( ) ;
if ( ProtoBuf . Util . isArray ( defs ) ) { // Stack always contains entire namespaces
while ( defs . length > 0 ) {
var def = defs . shift ( ) ; // Namespace always contains an array of messages, enums and services
if ( Builder . isValidMessage ( def ) ) {
var obj = new Reflect . Message ( this , this . ptr , def [ "name" ] , def [ "options" ] , def [ "isGroup" ] ) ;
// Create OneOfs
var oneofs = { } ;
if ( def [ "oneofs" ] ) {
var keys = Object . keys ( def [ "oneofs" ] ) ;
for ( var i = 0 , k = keys . length ; i < k ; ++ i )
obj . addChild ( oneofs [ keys [ i ] ] = new Reflect . Message . OneOf ( this , obj , keys [ i ] ) ) ;
}
// Create fields
if ( def [ "fields" ] && def [ "fields" ] . length > 0 ) {
for ( i = 0 , k = def [ "fields" ] . length ; i < k ; ++ i ) { // i:k=Fields
var fld = def [ 'fields' ] [ i ] ;
if ( obj . getChild ( fld [ 'id' ] ) !== null )
throw Error ( "Duplicate field id in message " + obj . name + ": " + fld [ 'id' ] ) ;
if ( fld [ "options" ] ) {
var opts = Object . keys ( fld [ "options" ] ) ;
for ( var j = 0 , l = opts . length ; j < l ; ++ j ) { // j:l=Option names
if ( typeof opts [ j ] !== 'string' )
throw Error ( "Illegal field option name in message " + obj . name + "#" + fld [ "name" ] + ": " + opts [ j ] ) ;
if ( typeof fld [ "options" ] [ opts [ j ] ] !== 'string' && typeof fld [ "options" ] [ opts [ j ] ] !== 'number' && typeof fld [ "options" ] [ opts [ j ] ] !== 'boolean' )
throw Error ( "Illegal field option value in message " + obj . name + "#" + fld [ "name" ] + "#" + opts [ j ] + ": " + fld [ "options" ] [ opts [ j ] ] ) ;
}
}
var oneof = null ;
if ( typeof fld [ "oneof" ] === 'string' ) {
oneof = oneofs [ fld [ "oneof" ] ] ;
if ( typeof oneof === 'undefined' )
throw Error ( "Illegal oneof in message " + obj . name + "#" + fld [ "name" ] + ": " + fld [ "oneof" ] ) ;
}
fld = new Reflect . Message . Field ( this , obj , fld [ "rule" ] , fld [ "type" ] , fld [ "name" ] , fld [ "id" ] , fld [ "options" ] , oneof ) ;
if ( oneof )
oneof . fields . push ( fld ) ;
obj . addChild ( fld ) ;
}
}
// Push enums and messages to stack
var subObj = [ ] ;
if ( typeof def [ "enums" ] !== 'undefined' && def [ 'enums' ] . length > 0 )
for ( i = 0 ; i < def [ "enums" ] . length ; i ++ )
subObj . push ( def [ "enums" ] [ i ] ) ;
if ( def [ "messages" ] && def [ "messages" ] . length > 0 )
for ( i = 0 ; i < def [ "messages" ] . length ; i ++ )
subObj . push ( def [ "messages" ] [ i ] ) ;
// Set extension range
if ( def [ "extensions" ] ) {
obj . extensions = def [ "extensions" ] ;
if ( obj . extensions [ 0 ] < ProtoBuf . ID _MIN )
obj . extensions [ 0 ] = ProtoBuf . ID _MIN ;
if ( obj . extensions [ 1 ] > ProtoBuf . ID _MAX )
obj . extensions [ 1 ] = ProtoBuf . ID _MAX ;
}
this . ptr . addChild ( obj ) ; // Add to current namespace
if ( subObj . length > 0 ) {
stack . push ( defs ) ; // Push the current level back
defs = subObj ; // Continue processing sub level
subObj = null ;
this . ptr = obj ; // And move the pointer to this namespace
obj = null ;
continue ;
}
subObj = null ;
obj = null ;
} else if ( Builder . isValidEnum ( def ) ) {
obj = new Reflect . Enum ( this , this . ptr , def [ "name" ] , def [ "options" ] ) ;
for ( i = 0 ; i < def [ "values" ] . length ; i ++ )
obj . addChild ( new Reflect . Enum . Value ( this , obj , def [ "values" ] [ i ] [ "name" ] , def [ "values" ] [ i ] [ "id" ] ) ) ;
this . ptr . addChild ( obj ) ;
obj = null ;
} else if ( Builder . isValidService ( def ) ) {
obj = new Reflect . Service ( this , this . ptr , def [ "name" ] , def [ "options" ] ) ;
for ( i in def [ "rpc" ] )
if ( def [ "rpc" ] . hasOwnProperty ( i ) )
obj . addChild ( new Reflect . Service . RPCMethod ( this , obj , i , def [ "rpc" ] [ i ] [ "request" ] , def [ "rpc" ] [ i ] [ "response" ] , def [ "rpc" ] [ i ] [ "options" ] ) ) ;
this . ptr . addChild ( obj ) ;
obj = null ;
} else if ( Builder . isValidExtend ( def ) ) {
obj = this . ptr . resolve ( def [ "ref" ] ) ;
if ( obj ) {
for ( i = 0 ; i < def [ "fields" ] . length ; i ++ ) { // i=Fields
if ( obj . getChild ( def [ 'fields' ] [ i ] [ 'id' ] ) !== null )
throw Error ( "Duplicate extended field id in message " + obj . name + ": " + def [ 'fields' ] [ i ] [ 'id' ] ) ;
if ( def [ 'fields' ] [ i ] [ 'id' ] < obj . extensions [ 0 ] || def [ 'fields' ] [ i ] [ 'id' ] > obj . extensions [ 1 ] )
throw Error ( "Illegal extended field id in message " + obj . name + ": " + def [ 'fields' ] [ i ] [ 'id' ] + " (" + obj . extensions . join ( ' to ' ) + " expected)" ) ;
// Convert extension field names to camel case notation if the override is set
var name = def [ "fields" ] [ i ] [ "name" ] ;
if ( this . options [ 'convertFieldsToCamelCase' ] )
name = Reflect . Message . Field . _toCamelCase ( def [ "fields" ] [ i ] [ "name" ] ) ;
// see #161: Extensions use their fully qualified name as their runtime key and...
fld = new Reflect . Message . ExtensionField ( this , obj , def [ "fields" ] [ i ] [ "rule" ] , def [ "fields" ] [ i ] [ "type" ] , this . ptr . fqn ( ) + '.' + name , def [ "fields" ] [ i ] [ "id" ] , def [ "fields" ] [ i ] [ "options" ] ) ;
// ...are added on top of the current namespace as an extension which is used for
// resolving their type later on (the extension always keeps the original name to
// prevent naming collisions)
var ext = new Reflect . Extension ( this , this . ptr , def [ "fields" ] [ i ] [ "name" ] , fld ) ;
fld . extension = ext ;
this . ptr . addChild ( ext ) ;
obj . addChild ( fld ) ;
}
} else if ( ! /\.?google\.protobuf\./ . test ( def [ "ref" ] ) ) // Silently skip internal extensions
throw Error ( "Extended message " + def [ "ref" ] + " is not defined" ) ;
} else
throw Error ( "Not a valid definition: " + JSON . stringify ( def ) ) ;
def = null ;
}
// Break goes here
} else
throw Error ( "Not a valid namespace: " + JSON . stringify ( defs ) ) ;
defs = null ;
this . ptr = this . ptr . parent ; // This namespace is s done
}
this . resolved = false ; // Require re-resolve
this . result = null ; // Require re-build
return this ;
} ;
/ * *
* Imports another definition into this builder .
* @ param { Object . < string , * > } json Parsed import
* @ param { ( string | { root : string , file : string } ) = } filename Imported file name
* @ return { ProtoBuf . Builder } this
* @ throws { Error } If the definition or file cannot be imported
* @ expose
* /
BuilderPrototype [ "import" ] = function ( json , filename ) {
if ( typeof filename === 'string' ) {
if ( ProtoBuf . Util . IS _NODE )
filename = require ( "path" ) [ 'resolve' ] ( filename ) ;
if ( this . files [ filename ] === true ) {
this . reset ( ) ;
return this ; // Skip duplicate imports
}
this . files [ filename ] = true ;
}
if ( ! ! json [ 'imports' ] && json [ 'imports' ] . length > 0 ) {
var importRoot , delim = '/' , resetRoot = false ;
if ( typeof filename === 'object' ) { // If an import root is specified, override
this . importRoot = filename [ "root" ] ; resetRoot = true ; // ... and reset afterwards
importRoot = this . importRoot ;
filename = filename [ "file" ] ;
if ( importRoot . indexOf ( "\\" ) >= 0 || filename . indexOf ( "\\" ) >= 0 ) delim = '\\' ;
} else if ( typeof filename === 'string' ) {
if ( this . importRoot ) // If import root is overridden, use it
importRoot = this . importRoot ;
else { // Otherwise compute from filename
if ( filename . indexOf ( "/" ) >= 0 ) { // Unix
importRoot = filename . replace ( /\/[^\/]*$/ , "" ) ;
if ( /* /file.proto */ importRoot === "" )
importRoot = "/" ;
} else if ( filename . indexOf ( "\\" ) >= 0 ) { // Windows
importRoot = filename . replace ( /\\[^\\]*$/ , "" ) ;
delim = '\\' ;
} else
importRoot = "." ;
}
} else
importRoot = null ;
for ( var i = 0 ; i < json [ 'imports' ] . length ; i ++ ) {
if ( typeof json [ 'imports' ] [ i ] === 'string' ) { // Import file
if ( ! importRoot )
throw Error ( "Cannot determine import root: File name is unknown" ) ;
var importFilename = json [ 'imports' ] [ i ] ;
if ( /^google\/protobuf\// . test ( importFilename ) )
continue ; // Not needed and therefore not used
importFilename = importRoot + delim + importFilename ;
if ( this . files [ importFilename ] === true )
continue ; // Already imported
if ( /\.proto$/i . test ( importFilename ) && ! ProtoBuf . DotProto ) // If this is a NOPARSE build
importFilename = importFilename . replace ( /\.proto$/ , ".json" ) ; // always load the JSON file
var contents = ProtoBuf . Util . fetch ( importFilename ) ;
if ( contents === null )
throw Error ( "Failed to import '" + importFilename + "' in '" + filename + "': File not found" ) ;
if ( /\.json$/i . test ( importFilename ) ) // Always possible
this [ "import" ] ( JSON . parse ( contents + "" ) , importFilename ) ; // May throw
else
this [ "import" ] ( ( new ProtoBuf . DotProto . Parser ( contents + "" ) ) . parse ( ) , importFilename ) ; // May throw
} else // Import structure
if ( ! filename )
this [ "import" ] ( json [ 'imports' ] [ i ] ) ;
else if ( /\.(\w+)$/ . test ( filename ) ) // With extension: Append _importN to the name portion to make it unique
this [ "import" ] ( json [ 'imports' ] [ i ] , filename . replace ( /^(.+)\.(\w+)$/ , function ( $0 , $1 , $2 ) { return $1 + "_import" + i + "." + $2 ; } ) ) ;
else // Without extension: Append _importN to make it unique
this [ "import" ] ( json [ 'imports' ] [ i ] , filename + "_import" + i ) ;
}
if ( resetRoot ) // Reset import root override when all imports are done
this . importRoot = null ;
}
if ( json [ 'messages' ] ) {
if ( json [ 'package' ] )
this . define ( json [ 'package' ] , json [ "options" ] ) ;
this . create ( json [ 'messages' ] ) ;
this . reset ( ) ;
}
if ( json [ 'enums' ] ) {
if ( json [ 'package' ] )
this . define ( json [ 'package' ] , json [ "options" ] ) ;
this . create ( json [ 'enums' ] ) ;
this . reset ( ) ;
}
if ( json [ 'services' ] ) {
if ( json [ 'package' ] )
this . define ( json [ 'package' ] , json [ "options" ] ) ;
this . create ( json [ 'services' ] ) ;
this . reset ( ) ;
}
if ( json [ 'extends' ] ) {
if ( json [ 'package' ] )
this . define ( json [ 'package' ] , json [ "options" ] ) ;
this . create ( json [ 'extends' ] ) ;
this . reset ( ) ;
}
return this ;
} ;
/ * *
* Tests if a definition is a valid service definition .
* @ param { Object } def Definition
* @ return { boolean } true if valid , else false
* @ expose
* /
Builder . isValidService = function ( def ) {
// Services require a string name and an rpc object
return ! ( typeof def [ "name" ] !== 'string' || ! Lang . NAME . test ( def [ "name" ] ) || typeof def [ "rpc" ] !== 'object' ) ;
} ;
/ * *
* Tests if a definition is a valid extension .
* @ param { Object } def Definition
* @ returns { boolean } true if valid , else false
* @ expose
* /
Builder . isValidExtend = function ( def ) {
if ( typeof def [ "ref" ] !== 'string' || ! Lang . TYPEREF . test ( def [ "ref" ] ) )
return false ;
var i ;
if ( typeof def [ "fields" ] !== 'undefined' ) {
if ( ! ProtoBuf . Util . isArray ( def [ "fields" ] ) )
return false ;
var ids = [ ] , id ; // IDs must be unique (does not yet test for the extended message's ids)
for ( i = 0 ; i < def [ "fields" ] . length ; i ++ ) {
if ( ! Builder . isValidMessageField ( def [ "fields" ] [ i ] ) )
return false ;
id = parseInt ( def [ "id" ] , 10 ) ;
if ( ids . indexOf ( id ) >= 0 )
return false ;
ids . push ( id ) ;
}
ids = null ;
}
return true ;
} ;
/ * *
* Resolves all namespace objects .
* @ throws { Error } If a type cannot be resolved
* @ expose
* /
BuilderPrototype . resolveAll = function ( ) {
// Resolve all reflected objects
var res ;
if ( this . ptr == null || typeof this . ptr . type === 'object' )
return ; // Done (already resolved)
if ( this . ptr instanceof Reflect . Namespace ) {
// Build all children
var children = this . ptr . children ;
for ( var i = 0 , k = children . length ; i < k ; ++ i )
this . ptr = children [ i ] ,
this . resolveAll ( ) ;
} else if ( this . ptr instanceof Reflect . Message . Field ) {
if ( ! Lang . TYPE . test ( this . ptr . type ) ) { // Resolve type...
if ( ! Lang . TYPEREF . test ( this . ptr . type ) )
throw Error ( "Illegal type reference in " + this . ptr . toString ( true ) + ": " + this . ptr . type ) ;
res = ( this . ptr instanceof Reflect . Message . ExtensionField ? this . ptr . extension . parent : this . ptr . parent ) . resolve ( this . ptr . type , true ) ;
if ( ! res )
throw Error ( "Unresolvable type reference in " + this . ptr . toString ( true ) + ": " + this . ptr . type ) ;
this . ptr . resolvedType = res ;
if ( res instanceof Reflect . Enum )
this . ptr . type = ProtoBuf . TYPES [ "enum" ] ;
else if ( res instanceof Reflect . Message )
this . ptr . type = res . isGroup ? ProtoBuf . TYPES [ "group" ] : ProtoBuf . TYPES [ "message" ] ;
else
throw Error ( "Illegal type reference in " + this . ptr . toString ( true ) + ": " + this . ptr . type ) ;
} else
this . ptr . type = ProtoBuf . TYPES [ this . ptr . type ] ;
} else if ( this . ptr instanceof ProtoBuf . Reflect . Enum . Value ) {
// No need to build enum values (built in enum)
} else if ( this . ptr instanceof ProtoBuf . Reflect . Service . Method ) {
if ( this . ptr instanceof ProtoBuf . Reflect . Service . RPCMethod ) {
res = this . ptr . parent . resolve ( this . ptr . requestName ) ;
if ( ! res || ! ( res instanceof ProtoBuf . Reflect . Message ) )
throw Error ( "Illegal type reference in " + this . ptr . toString ( true ) + ": " + this . ptr . requestName ) ;
this . ptr . resolvedRequestType = res ;
res = this . ptr . parent . resolve ( this . ptr . responseName ) ;
if ( ! res || ! ( res instanceof ProtoBuf . Reflect . Message ) )
throw Error ( "Illegal type reference in " + this . ptr . toString ( true ) + ": " + this . ptr . responseName ) ;
this . ptr . resolvedResponseType = res ;
} else {
// Should not happen as nothing else is implemented
throw Error ( "Illegal service type in " + this . ptr . toString ( true ) ) ;
}
} else if ( ! ( this . ptr instanceof ProtoBuf . Reflect . Message . OneOf ) && ! ( this . ptr instanceof ProtoBuf . Reflect . Extension ) )
throw Error ( "Illegal object in namespace: " + typeof ( this . ptr ) + ":" + this . ptr ) ;
this . reset ( ) ;
} ;
/ * *
* Builds the protocol . This will first try to resolve all definitions and , if this has been successful ,
* return the built package .
* @ param { string = } path Specifies what to return . If omitted , the entire namespace will be returned .
* @ return { ProtoBuf . Builder . Message | Object . < string , * > }
* @ throws { Error } If a type could not be resolved
* @ expose
* /
BuilderPrototype . build = function ( path ) {
this . reset ( ) ;
if ( ! this . resolved )
this . resolveAll ( ) ,
this . resolved = true ,
this . result = null ; // Require re-build
if ( this . result == null ) // (Re-)Build
this . result = this . ns . build ( ) ;
if ( ! path )
return this . result ;
else {
var part = path . split ( "." ) ;
var ptr = this . result ; // Build namespace pointer (no hasChild etc.)
for ( var i = 0 ; i < part . length ; i ++ )
if ( ptr [ part [ i ] ] )
ptr = ptr [ part [ i ] ] ;
else {
ptr = null ;
break ;
}
return ptr ;
}
} ;
/ * *
* Similar to { @ link ProtoBuf . Builder # build } , but looks up the internal reflection descriptor .
* @ param { string = } path Specifies what to return . If omitted , the entire namespace wiil be returned .
* @ return { ProtoBuf . Reflect . T } Reflection descriptor or ` null ` if not found
* /
BuilderPrototype . lookup = function ( path ) {
return path ? this . ns . resolve ( path ) : this . ns ;
} ;
/ * *
* Returns a string representation of this object .
* @ return { string } String representation as of "Builder"
* @ expose
* /
BuilderPrototype . toString = function ( ) {
return "Builder" ;
} ;
// Pseudo types documented in Reflect.js.
// Exist for the sole purpose of being able to "... instanceof ProtoBuf.Builder.Message" etc.
Builder . Message = function ( ) { } ;
Builder . Service = function ( ) { } ;
return Builder ;
} ) ( ProtoBuf , ProtoBuf . Lang , ProtoBuf . Reflect ) ;
/ * *
* Loads a . proto string and returns the Builder .
* @ param { string } proto . proto file contents
* @ param { ( ProtoBuf . Builder | string | { root : string , file : string } ) = } builder Builder to append to . Will create a new one if omitted .
* @ param { ( string | { root : string , file : string } ) = } filename The corresponding file name if known . Must be specified for imports .
* @ return { ProtoBuf . Builder } Builder to create new messages
* @ throws { Error } If the definition cannot be parsed or built
* @ expose
* /
ProtoBuf . loadProto = function ( proto , builder , filename ) {
if ( typeof builder === 'string' || ( builder && typeof builder [ "file" ] === 'string' && typeof builder [ "root" ] === 'string' ) )
filename = builder ,
builder = undefined ;
return ProtoBuf . loadJson ( ( new ProtoBuf . DotProto . Parser ( proto ) ) . parse ( ) , builder , filename ) ;
} ;
/ * *
* Loads a . proto string and returns the Builder . This is an alias of { @ link ProtoBuf . loadProto } .
* @ function
* @ param { string } proto . proto file contents
* @ param { ( ProtoBuf . Builder | string ) = } builder Builder to append to . Will create a new one if omitted .
* @ param { ( string | { root : string , file : string } ) = } filename The corresponding file name if known . Must be specified for imports .
* @ return { ProtoBuf . Builder } Builder to create new messages
* @ throws { Error } If the definition cannot be parsed or built
* @ expose
* /
ProtoBuf . protoFromString = ProtoBuf . loadProto ; // Legacy
/ * *
* Loads a . proto file and returns the Builder .
* @ param { string | { root : string , file : string } } filename Path to proto file or an object specifying 'file' with
* an overridden 'root' path for all imported files .
* @ param { function ( ? Error , ! ProtoBuf . Builder = ) = } callback Callback that will receive ` null ` as the first and
* the Builder as its second argument on success , otherwise the error as its first argument . If omitted , the
* file will be read synchronously and this function will return the Builder .
* @ param { ProtoBuf . Builder = } builder Builder to append to . Will create a new one if omitted .
* @ return { ? ProtoBuf . Builder | undefined } The Builder if synchronous ( no callback specified , will be NULL if the
* request has failed ) , else undefined
* @ expose
* /
ProtoBuf . loadProtoFile = function ( filename , callback , builder ) {
if ( callback && typeof callback === 'object' )
builder = callback ,
callback = null ;
else if ( ! callback || typeof callback !== 'function' )
callback = null ;
if ( callback )
return ProtoBuf . Util . fetch ( typeof filename === 'string' ? filename : filename [ "root" ] + "/" + filename [ "file" ] , function ( contents ) {
if ( contents === null ) {
callback ( Error ( "Failed to fetch file" ) ) ;
return ;
}
try {
callback ( null , ProtoBuf . loadProto ( contents , builder , filename ) ) ;
} catch ( e ) {
callback ( e ) ;
}
} ) ;
var contents = ProtoBuf . Util . fetch ( typeof filename === 'object' ? filename [ "root" ] + "/" + filename [ "file" ] : filename ) ;
return contents === null ? null : ProtoBuf . loadProto ( contents , builder , filename ) ;
} ;
/ * *
* Loads a . proto file and returns the Builder . This is an alias of { @ link ProtoBuf . loadProtoFile } .
* @ function
* @ param { string | { root : string , file : string } } filename Path to proto file or an object specifying 'file' with
* an overridden 'root' path for all imported files .
* @ param { function ( ? Error , ! ProtoBuf . Builder = ) = } callback Callback that will receive ` null ` as the first and
* the Builder as its second argument on success , otherwise the error as its first argument . If omitted , the
* file will be read synchronously and this function will return the Builder .
* @ param { ProtoBuf . Builder = } builder Builder to append to . Will create a new one if omitted .
* @ return { ! ProtoBuf . Builder | undefined } The Builder if synchronous ( no callback specified , will be NULL if the
* request has failed ) , else undefined
* @ expose
* /
ProtoBuf . protoFromFile = ProtoBuf . loadProtoFile ; // Legacy
/ * *
* Constructs a new empty Builder .
* @ param { Object . < string , * >= } options Builder options , defaults to global options set on ProtoBuf
* @ return { ! ProtoBuf . Builder } Builder
* @ expose
* /
ProtoBuf . newBuilder = function ( options ) {
options = options || { } ;
if ( typeof options [ 'convertFieldsToCamelCase' ] === 'undefined' )
options [ 'convertFieldsToCamelCase' ] = ProtoBuf . convertFieldsToCamelCase ;
if ( typeof options [ 'populateAccessors' ] === 'undefined' )
options [ 'populateAccessors' ] = ProtoBuf . populateAccessors ;
return new ProtoBuf . Builder ( options ) ;
} ;
/ * *
* Loads a . json definition and returns the Builder .
* @ param { ! * | string } json JSON definition
* @ param { ( ProtoBuf . Builder | string | { root : string , file : string } ) = } builder Builder to append to . Will create a new one if omitted .
* @ param { ( string | { root : string , file : string } ) = } filename The corresponding file name if known . Must be specified for imports .
* @ return { ProtoBuf . Builder } Builder to create new messages
* @ throws { Error } If the definition cannot be parsed or built
* @ expose
* /
ProtoBuf . loadJson = function ( json , builder , filename ) {
if ( typeof builder === 'string' || ( builder && typeof builder [ "file" ] === 'string' && typeof builder [ "root" ] === 'string' ) )
filename = builder ,
builder = null ;
if ( ! builder || typeof builder !== 'object' )
builder = ProtoBuf . newBuilder ( ) ;
if ( typeof json === 'string' )
json = JSON . parse ( json ) ;
builder [ "import" ] ( json , filename ) ;
builder . resolveAll ( ) ;
builder . build ( ) ;
return builder ;
} ;
/ * *
* Loads a . json file and returns the Builder .
* @ param { string | ! { root : string , file : string } } filename Path to json file or an object specifying 'file' with
* an overridden 'root' path for all imported files .
* @ param { function ( ? Error , ! ProtoBuf . Builder = ) = } callback Callback that will receive ` null ` as the first and
* the Builder as its second argument on success , otherwise the error as its first argument . If omitted , the
* file will be read synchronously and this function will return the Builder .
* @ param { ProtoBuf . Builder = } builder Builder to append to . Will create a new one if omitted .
* @ return { ? ProtoBuf . Builder | undefined } The Builder if synchronous ( no callback specified , will be NULL if the
* request has failed ) , else undefined
* @ expose
* /
ProtoBuf . loadJsonFile = function ( filename , callback , builder ) {
if ( callback && typeof callback === 'object' )
builder = callback ,
callback = null ;
else if ( ! callback || typeof callback !== 'function' )
callback = null ;
if ( callback )
return ProtoBuf . Util . fetch ( typeof filename === 'string' ? filename : filename [ "root" ] + "/" + filename [ "file" ] , function ( contents ) {
if ( contents === null ) {
callback ( Error ( "Failed to fetch file" ) ) ;
return ;
}
try {
callback ( null , ProtoBuf . loadJson ( JSON . parse ( contents ) , builder , filename ) ) ;
} catch ( e ) {
callback ( e ) ;
}
} ) ;
var contents = ProtoBuf . Util . fetch ( typeof filename === 'object' ? filename [ "root" ] + "/" + filename [ "file" ] : filename ) ;
return contents === null ? null : ProtoBuf . loadJson ( JSON . parse ( contents ) , builder , filename ) ;
} ;
return ProtoBuf ;
}
/* CommonJS */ if ( typeof require === 'function' && typeof module === 'object' && module && typeof exports === 'object' && exports )
module [ 'exports' ] = init ( require ( "bytebuffer" ) ) ;
/* AMD */ else if ( typeof define === 'function' && define [ "amd" ] )
define ( [ "ByteBuffer" ] , init ) ;
/* Global */ else
( global [ "dcodeIO" ] = global [ "dcodeIO" ] || { } ) [ "ProtoBuf" ] = init ( global [ "dcodeIO" ] [ "ByteBuffer" ] ) ;
} ) ( this ) ;
/ * v i m : t s = 4 : s w = 4
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
; ( function ( ) {
window . axolotl = window . axolotl || { } ;
/ *
* axolotl . crypto
* glues together various implementations into a single interface
* for all low - level crypto operations ,
* /
window . axolotl . crypto = {
getRandomBytes : function ( size ) {
var array = new Uint8Array ( size ) ;
window . crypto . getRandomValues ( array ) ;
return array . buffer ;
} ,
encrypt : function ( key , data , iv ) {
return window . crypto . subtle . importKey ( 'raw' , key , { name : 'AES-CBC' } , false , [ 'encrypt' ] ) . then ( function ( key ) {
return window . crypto . subtle . encrypt ( { name : 'AES-CBC' , iv : new Uint8Array ( iv ) } , key , data ) ;
} ) ;
} ,
decrypt : function ( key , data , iv ) {
return window . crypto . subtle . importKey ( 'raw' , key , { name : 'AES-CBC' } , false , [ 'decrypt' ] ) . then ( function ( key ) {
return window . crypto . subtle . decrypt ( { name : 'AES-CBC' , iv : new Uint8Array ( iv ) } , key , data ) ;
} ) ;
} ,
sign : function ( key , data ) {
return window . crypto . subtle . importKey ( 'raw' , key , { name : 'HMAC' , hash : { name : 'SHA-256' } } , false , [ 'sign' ] ) . then ( function ( key ) {
return window . crypto . subtle . sign ( { name : 'HMAC' , hash : 'SHA-256' } , key , data ) ;
} ) ;
} ,
HKDF : function ( input , salt , info ) {
// Specific implementation of RFC 5869 that only returns the first 3 32-byte chunks
// TODO: We dont always need the third chunk, we might skip it
return window . axolotl . crypto . sign ( salt , input ) . then ( function ( PRK ) {
var infoBuffer = new ArrayBuffer ( info . byteLength + 1 + 32 ) ;
var infoArray = new Uint8Array ( infoBuffer ) ;
infoArray . set ( new Uint8Array ( info ) , 32 ) ;
infoArray [ infoArray . length - 1 ] = 1 ;
return window . axolotl . crypto . sign ( PRK , infoBuffer . slice ( 32 ) ) . then ( function ( T1 ) {
infoArray . set ( new Uint8Array ( T1 ) ) ;
infoArray [ infoArray . length - 1 ] = 2 ;
return window . axolotl . crypto . sign ( PRK , infoBuffer ) . then ( function ( T2 ) {
infoArray . set ( new Uint8Array ( T2 ) ) ;
infoArray [ infoArray . length - 1 ] = 3 ;
return window . axolotl . crypto . sign ( PRK , infoBuffer ) . then ( function ( T3 ) {
return [ T1 , T2 , T3 ] ;
} ) ;
} ) ;
} ) ;
} ) ;
} ,
// Curve 25519 crypto
createKeyPair : function ( privKey ) {
if ( privKey === undefined ) {
privKey = axolotl . crypto . getRandomBytes ( 32 ) ;
}
if ( privKey . byteLength != 32 ) {
throw new Error ( "Invalid private key" ) ;
}
return window . curve25519 . keyPair ( privKey ) . then ( function ( raw _keys ) {
// prepend version byte
var origPub = new Uint8Array ( raw _keys . pubKey ) ;
var pub = new Uint8Array ( 33 ) ;
pub . set ( origPub , 1 ) ;
pub [ 0 ] = 5 ;
return { pubKey : pub . buffer , privKey : raw _keys . privKey } ;
} ) ;
} ,
ECDHE : function ( pubKey , privKey ) {
pubKey = validatePubKeyFormat ( pubKey ) ;
if ( privKey === undefined || privKey . byteLength != 32 )
throw new Error ( "Invalid private key" ) ;
if ( pubKey === undefined || pubKey . byteLength != 32 )
throw new Error ( "Invalid public key" ) ;
return window . curve25519 . sharedSecret ( pubKey , privKey ) ;
} ,
Ed25519Sign : function ( privKey , message ) {
if ( privKey === undefined || privKey . byteLength != 32 )
throw new Error ( "Invalid private key" ) ;
if ( message === undefined )
throw new Error ( "Invalid message" ) ;
return window . curve25519 . sign ( privKey , message ) ;
} ,
Ed25519Verify : function ( pubKey , msg , sig ) {
pubKey = validatePubKeyFormat ( pubKey ) ;
if ( pubKey === undefined || pubKey . byteLength != 32 )
throw new Error ( "Invalid public key" ) ;
if ( msg === undefined )
throw new Error ( "Invalid message" ) ;
if ( sig === undefined || sig . byteLength != 64 )
throw new Error ( "Invalid signature" ) ;
return window . curve25519 . verify ( pubKey , msg , sig ) ;
}
} ;
var validatePubKeyFormat = function ( pubKey ) {
if ( pubKey === undefined || ( ( pubKey . byteLength != 33 || new Uint8Array ( pubKey ) [ 0 ] != 5 ) && pubKey . byteLength != 32 ) )
throw new Error ( "Invalid public key" ) ;
if ( pubKey . byteLength == 33 ) {
return pubKey . slice ( 1 ) ;
} else {
console . error ( "WARNING: Expected pubkey of length 33, please report the ST and client that generated the pubkey" ) ;
return pubKey ;
}
} ;
} ) ( ) ;
/ * v i m : t s = 4 : s w = 4
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
; ( function ( ) {
'use strict' ;
window . axolotl = window . axolotl || { } ;
window . axolotl . protocol = function ( ) {
var self = { } ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * Random constants / utils * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
// We consider messages lost after a week and might throw away keys at that point
// (also the time between signedPreKey regenerations)
var MESSAGE _LOST _THRESHOLD _MS = 1000 * 60 * 60 * 24 * 7 ;
function objectContainsKeys ( object ) {
var count = 0 ;
for ( var key in object ) {
count ++ ;
break ;
}
return count != 0 ;
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * Key / session storage * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * /
var crypto _storage = { } ;
crypto _storage . putKeyPair = function ( keyName , keyPair ) {
axolotl . api . storage . put ( "25519Key" + keyName , keyPair ) ;
}
crypto _storage . getNewStoredKeyPair = function ( keyName ) {
return axolotl . crypto . createKeyPair ( ) . then ( function ( keyPair ) {
crypto _storage . putKeyPair ( keyName , keyPair ) ;
return keyPair ;
} ) ;
}
crypto _storage . getStoredKeyPair = function ( keyName ) {
var res = axolotl . api . storage . get ( "25519Key" + keyName ) ;
if ( res === undefined )
return undefined ;
return { pubKey : toArrayBuffer ( res . pubKey ) , privKey : toArrayBuffer ( res . privKey ) } ;
}
crypto _storage . removeStoredKeyPair = function ( keyName ) {
axolotl . api . storage . remove ( "25519Key" + keyName ) ;
}
crypto _storage . getIdentityKey = function ( ) {
return this . getStoredKeyPair ( "identityKey" ) ;
}
crypto _storage . saveSession = function ( encodedNumber , session , registrationId ) {
2015-01-20 22:48:09 -10:00
var record = axolotl . api . storage . sessions . get ( encodedNumber ) ;
if ( record === undefined ) {
if ( registrationId === undefined )
throw new Error ( "Tried to save a session for an existing device that didn't exist" ) ;
else
record = new axolotl . sessions . RecipientRecord ( session . indexInfo . remoteIdentityKey , registrationId ) ;
}
2015-02-10 16:39:50 -08:00
2015-01-20 22:48:09 -10:00
var sessions = record . _sessions ;
2015-02-10 16:39:50 -08:00
2015-01-20 22:48:09 -10:00
if ( record . identityKey === null )
record . identityKey = session . indexInfo . remoteIdentityKey ;
if ( getString ( record . identityKey ) !== getString ( session . indexInfo . remoteIdentityKey ) )
throw new Error ( "Identity key changed at session save time" ) ;
2015-02-10 16:39:50 -08:00
var doDeleteSession = false ;
if ( session . indexInfo . closed != - 1 ) {
doDeleteSession = ( session . indexInfo . closed < ( new Date ( ) . getTime ( ) - MESSAGE _LOST _THRESHOLD _MS ) ) ;
if ( ! doDeleteSession ) {
var keysLeft = false ;
for ( var key in session ) {
if ( key != "indexInfo" && key != "oldRatchetList" && key != "currentRatchet" ) {
keysLeft = true ;
break ;
}
}
doDeleteSession = ! keysLeft ;
console . log ( ( doDeleteSession ? "Deleting " : "Not deleting " ) + "closed session which has not yet timed out" ) ;
} else
console . log ( "Deleting closed session due to timeout (created at " + session . indexInfo . closed + ")" ) ;
}
if ( doDeleteSession )
delete sessions [ getString ( session . indexInfo . baseKey ) ] ;
else
sessions [ getString ( session . indexInfo . baseKey ) ] = session ;
var openSessionRemaining = false ;
for ( var key in sessions )
if ( sessions [ key ] . indexInfo . closed == - 1 )
openSessionRemaining = true ;
2015-01-20 22:48:09 -10:00
if ( ! openSessionRemaining ) // Used as a flag to get new pre keys for the next session
record . registrationId = null ;
else if ( record . registrationId === null && registrationId !== undefined )
record . registrationId = registrationId ;
else if ( record . registrationId === null )
throw new Error ( "Had open sessions on a record that had no registrationId set" ) ;
var identityKey = axolotl . api . storage . identityKeys . get ( encodedNumber ) ;
if ( identityKey === undefined )
axolotl . api . storage . identityKeys . put ( encodedNumber , record . identityKey ) ;
else if ( getString ( identityKey ) !== getString ( record . identityKey ) )
throw new Error ( "Tried to change identity key at save time" ) ;
axolotl . api . storage . sessions . put ( encodedNumber , record ) ;
2015-02-10 16:39:50 -08:00
}
var getSessions = function ( encodedNumber ) {
2015-01-20 22:48:09 -10:00
var record = axolotl . api . storage . sessions . get ( encodedNumber ) ;
if ( record === undefined )
2015-02-10 16:39:50 -08:00
return undefined ;
2015-01-20 22:48:09 -10:00
return record . _sessions ;
2015-02-10 16:39:50 -08:00
}
crypto _storage . getOpenSession = function ( encodedNumber ) {
var sessions = getSessions ( encodedNumber ) ;
if ( sessions === undefined )
return undefined ;
for ( var key in sessions )
if ( sessions [ key ] . indexInfo . closed == - 1 )
return sessions [ key ] ;
return undefined ;
}
crypto _storage . getSessionByRemoteEphemeralKey = function ( encodedNumber , remoteEphemeralKey ) {
var sessions = getSessions ( encodedNumber ) ;
if ( sessions === undefined )
return undefined ;
var searchKey = getString ( remoteEphemeralKey ) ;
var openSession = undefined ;
for ( var key in sessions ) {
if ( sessions [ key ] . indexInfo . closed == - 1 ) {
if ( openSession !== undefined )
throw new Error ( "Datastore inconsistensy: multiple open sessions for " + encodedNumber ) ;
openSession = sessions [ key ] ;
}
if ( sessions [ key ] [ searchKey ] !== undefined )
return sessions [ key ] ;
}
if ( openSession !== undefined )
return openSession ;
return undefined ;
}
crypto _storage . getSessionOrIdentityKeyByBaseKey = function ( encodedNumber , baseKey ) {
2015-01-20 22:48:09 -10:00
var record = axolotl . api . storage . sessions . get ( encodedNumber ) ;
if ( record === undefined ) {
var identityKey = axolotl . api . storage . identityKeys . get ( encodedNumber ) ;
if ( identityKey === undefined )
return undefined ;
return { indexInfo : { remoteIdentityKey : identityKey } } ;
}
var sessions = record . _sessions ;
2015-02-10 16:39:50 -08:00
2015-01-20 22:48:09 -10:00
var preferredSession = record . _sessions [ getString ( baseKey ) ] ;
2015-02-10 16:39:50 -08:00
if ( preferredSession !== undefined )
return preferredSession ;
2015-01-20 22:48:09 -10:00
if ( record . identityKey !== undefined )
return { indexInfo : { remoteIdentityKey : record . identityKey } } ;
2015-02-10 16:39:50 -08:00
throw new Error ( "Datastore inconsistency: device was stored without identity key" ) ;
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * Internal Crypto stuff * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
var HKDF = function ( input , salt , info ) {
// HKDF for TextSecure has a bit of additional handling - salts always end up being 32 bytes
if ( salt == '' )
salt = new ArrayBuffer ( 32 ) ;
if ( salt . byteLength != 32 )
throw new Error ( "Got salt of incorrect length" ) ;
info = toArrayBuffer ( info ) ; // TODO: maybe convert calls?
return axolotl . crypto . HKDF ( input , salt , info ) ;
}
var verifyMAC = function ( data , key , mac ) {
return axolotl . crypto . sign ( key , data ) . then ( function ( calculated _mac ) {
if ( ! isEqual ( calculated _mac , mac , true ) )
throw new Error ( "Bad MAC" ) ;
} ) ;
}
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * Ratchet implementation * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
var calculateRatchet = function ( session , remoteKey , sending ) {
var ratchet = session . currentRatchet ;
return axolotl . crypto . ECDHE ( remoteKey , toArrayBuffer ( ratchet . ephemeralKeyPair . privKey ) ) . then ( function ( sharedSecret ) {
return HKDF ( sharedSecret , toArrayBuffer ( ratchet . rootKey ) , "WhisperRatchet" ) . then ( function ( masterKey ) {
if ( sending )
session [ getString ( ratchet . ephemeralKeyPair . pubKey ) ] = { messageKeys : { } , chainKey : { counter : - 1 , key : masterKey [ 1 ] } } ;
else
session [ getString ( remoteKey ) ] = { messageKeys : { } , chainKey : { counter : - 1 , key : masterKey [ 1 ] } } ;
ratchet . rootKey = masterKey [ 0 ] ;
} ) ;
} ) ;
}
var initSession = function ( isInitiator , ourEphemeralKey , ourSignedKey , encodedNumber , theirIdentityPubKey , theirEphemeralPubKey , theirSignedPubKey ) {
var ourIdentityKey = crypto _storage . getIdentityKey ( ) ;
if ( isInitiator ) {
if ( ourSignedKey !== undefined )
throw new Error ( "Invalid call to initSession" ) ;
ourSignedKey = ourEphemeralKey ;
} else {
if ( theirSignedPubKey !== undefined )
throw new Error ( "Invalid call to initSession" ) ;
theirSignedPubKey = theirEphemeralPubKey ;
}
var sharedSecret ;
if ( ourEphemeralKey === undefined || theirEphemeralPubKey === undefined )
sharedSecret = new Uint8Array ( 32 * 4 ) ;
else
sharedSecret = new Uint8Array ( 32 * 5 ) ;
for ( var i = 0 ; i < 32 ; i ++ )
sharedSecret [ i ] = 0xff ;
return axolotl . crypto . ECDHE ( theirSignedPubKey , ourIdentityKey . privKey ) . then ( function ( ecRes1 ) {
function finishInit ( ) {
return axolotl . crypto . ECDHE ( theirSignedPubKey , ourSignedKey . privKey ) . then ( function ( ecRes ) {
sharedSecret . set ( new Uint8Array ( ecRes ) , 32 * 3 ) ;
return HKDF ( sharedSecret . buffer , '' , "WhisperText" ) . then ( function ( masterKey ) {
var session = { currentRatchet : { rootKey : masterKey [ 0 ] , lastRemoteEphemeralKey : theirSignedPubKey , previousCounter : 0 } ,
indexInfo : { remoteIdentityKey : theirIdentityPubKey , closed : - 1 } ,
oldRatchetList : [ ]
} ;
if ( ! isInitiator )
session . indexInfo . baseKey = theirEphemeralPubKey ;
else
session . indexInfo . baseKey = ourEphemeralKey . pubKey ;
// If we're initiating we go ahead and set our first sending ephemeral key now,
// otherwise we figure it out when we first maybeStepRatchet with the remote's ephemeral key
if ( isInitiator ) {
return axolotl . crypto . createKeyPair ( ) . then ( function ( ourSendingEphemeralKey ) {
session . currentRatchet . ephemeralKeyPair = ourSendingEphemeralKey ;
return calculateRatchet ( session , theirSignedPubKey , true ) . then ( function ( ) {
return session ;
} ) ;
} ) ;
} else {
session . currentRatchet . ephemeralKeyPair = ourSignedKey ;
return session ;
}
} ) ;
} ) ;
}
var promise ;
if ( ourEphemeralKey === undefined || theirEphemeralPubKey === undefined )
promise = Promise . resolve ( new ArrayBuffer ( 0 ) ) ;
else
promise = axolotl . crypto . ECDHE ( theirEphemeralPubKey , ourEphemeralKey . privKey ) ;
return promise . then ( function ( ecRes4 ) {
sharedSecret . set ( new Uint8Array ( ecRes4 ) , 32 * 4 ) ;
if ( isInitiator )
return axolotl . crypto . ECDHE ( theirIdentityPubKey , ourSignedKey . privKey ) . then ( function ( ecRes2 ) {
sharedSecret . set ( new Uint8Array ( ecRes1 ) , 32 ) ;
sharedSecret . set ( new Uint8Array ( ecRes2 ) , 32 * 2 ) ;
} ) . then ( finishInit ) ;
else
return axolotl . crypto . ECDHE ( theirIdentityPubKey , ourSignedKey . privKey ) . then ( function ( ecRes2 ) {
sharedSecret . set ( new Uint8Array ( ecRes1 ) , 32 * 2 ) ;
sharedSecret . set ( new Uint8Array ( ecRes2 ) , 32 )
} ) . then ( finishInit ) ;
} ) ;
} ) ;
}
var removeOldChains = function ( session ) {
// Sending ratchets are always removed when we step because we never need them again
// Receiving ratchets are either removed if we step with all keys used up to previousCounter
// and are otherwise added to the oldRatchetList, which we parse here and remove ratchets
// older than a week (we assume the message was lost and move on with our lives at that point)
var newList = [ ] ;
for ( var i = 0 ; i < session . oldRatchetList . length ; i ++ ) {
var entry = session . oldRatchetList [ i ] ;
var ratchet = getString ( entry . ephemeralKey ) ;
console . log ( "Checking old chain with added time " + ( entry . added / 1000 ) ) ;
if ( ( ! objectContainsKeys ( session [ ratchet ] . messageKeys ) && ( session [ ratchet ] . chainKey === undefined || session [ ratchet ] . chainKey . key === undefined ) )
|| entry . added < new Date ( ) . getTime ( ) - MESSAGE _LOST _THRESHOLD _MS ) {
delete session [ ratchet ] ;
console . log ( "...deleted" ) ;
} else
newList [ newList . length ] = entry ;
}
session . oldRatchetList = newList ;
}
var closeSession = function ( session , sessionClosedByRemote ) {
if ( session . indexInfo . closed > - 1 )
return ;
// After this has run, we can still receive messages on ratchet chains which
// were already open (unless we know we dont need them),
// but we cannot send messages or step the ratchet
// Delete current sending ratchet
delete session [ getString ( session . currentRatchet . ephemeralKeyPair . pubKey ) ] ;
// Move all receive ratchets to the oldRatchetList to mark them for deletion
for ( var i in session ) {
if ( session [ i ] . chainKey !== undefined && session [ i ] . chainKey . key !== undefined ) {
if ( ! sessionClosedByRemote )
session . oldRatchetList [ session . oldRatchetList . length ] = { added : new Date ( ) . getTime ( ) , ephemeralKey : i } ;
else
delete session [ i ] . chainKey . key ;
}
}
// Delete current root key and our ephemeral key pair to disallow ratchet stepping
delete session . currentRatchet [ 'rootKey' ] ;
delete session . currentRatchet [ 'ephemeralKeyPair' ] ;
session . indexInfo . closed = new Date ( ) . getTime ( ) ;
removeOldChains ( session ) ;
}
self . closeOpenSessionForDevice = function ( encodedNumber ) {
var session = crypto _storage . getOpenSession ( encodedNumber ) ;
if ( session === undefined )
return ;
closeSession ( session ) ;
crypto _storage . saveSession ( encodedNumber , session ) ;
}
var refreshPreKeys ;
var initSessionFromPreKeyWhisperMessage = function ( encodedNumber , message ) {
var preKeyPair = crypto _storage . getStoredKeyPair ( "preKey" + message . preKeyId ) ;
var signedPreKeyPair = crypto _storage . getStoredKeyPair ( "signedKey" + message . signedPreKeyId ) ;
//TODO: Call refreshPreKeys when it looks like all our prekeys are used up?
var session = crypto _storage . getSessionOrIdentityKeyByBaseKey ( encodedNumber , toArrayBuffer ( message . baseKey ) ) ;
var open _session = crypto _storage . getOpenSession ( encodedNumber ) ;
if ( signedPreKeyPair === undefined ) {
// Session may or may not be the right one, but if its not, we can't do anything about it
// ...fall through and let decryptWhisperMessage handle that case
if ( session !== undefined && session . currentRatchet !== undefined )
return Promise . resolve ( [ session , undefined ] ) ;
else
throw new Error ( "Missing Signed PreKey for PreKeyWhisperMessage" ) ;
}
if ( session !== undefined ) {
// Duplicate PreKeyMessage for session:
if ( isEqual ( session . indexInfo . baseKey , message . baseKey , false ) )
return Promise . resolve ( [ session , undefined ] ) ;
// We already had a session/known identity key:
if ( isEqual ( session . indexInfo . remoteIdentityKey , message . identityKey , false ) ) {
// If the identity key matches the previous one, close the previous one and use the new one
if ( open _session !== undefined )
closeSession ( open _session ) ; // To be returned and saved later
} else {
// ...otherwise create an error that the UI will pick up and ask the user if they want to re-negotiate
throw new textsecure . IncomingIdentityKeyError ( encodedNumber , getString ( message . encode ( ) ) ) ;
}
}
return initSession ( false , preKeyPair , signedPreKeyPair , encodedNumber , toArrayBuffer ( message . identityKey ) , toArrayBuffer ( message . baseKey ) , undefined )
. then ( function ( new _session ) {
// Note that the session is not actually saved until the very end of decryptWhisperMessage
// ... to ensure that the sender actually holds the private keys for all reported pubkeys
return [ new _session , function ( ) {
if ( open _session !== undefined )
crypto _storage . saveSession ( encodedNumber , open _session ) ;
crypto _storage . removeStoredKeyPair ( "preKey" + message . preKeyId ) ;
} ] ;
} ) ; ;
}
var fillMessageKeys = function ( chain , counter ) {
if ( chain . chainKey . counter + 1000 < counter ) //TODO: maybe 1000 is too low/high in some cases?
return Promise . resolve ( ) ; // Stalker, much?
if ( chain . chainKey . counter >= counter )
return Promise . resolve ( ) ; // Already calculated
if ( chain . chainKey . key === undefined )
throw new Error ( "Got invalid request to extend chain after it was already closed" ) ;
var key = toArrayBuffer ( chain . chainKey . key ) ;
var byteArray = new Uint8Array ( 1 ) ;
byteArray [ 0 ] = 1 ;
return axolotl . crypto . sign ( key , byteArray . buffer ) . then ( function ( mac ) {
byteArray [ 0 ] = 2 ;
return axolotl . crypto . sign ( key , byteArray . buffer ) . then ( function ( key ) {
chain . messageKeys [ chain . chainKey . counter + 1 ] = mac ;
chain . chainKey . key = key
chain . chainKey . counter += 1 ;
return fillMessageKeys ( chain , counter ) ;
} ) ;
} ) ;
}
var maybeStepRatchet = function ( session , remoteKey , previousCounter ) {
if ( session [ getString ( remoteKey ) ] !== undefined )
return Promise . resolve ( ) ;
var ratchet = session . currentRatchet ;
var finish = function ( ) {
return calculateRatchet ( session , remoteKey , false ) . then ( function ( ) {
// Now swap the ephemeral key and calculate the new sending chain
var previousRatchet = getString ( ratchet . ephemeralKeyPair . pubKey ) ;
if ( session [ previousRatchet ] !== undefined ) {
ratchet . previousCounter = session [ previousRatchet ] . chainKey . counter ;
delete session [ previousRatchet ] ;
}
return axolotl . crypto . createKeyPair ( ) . then ( function ( keyPair ) {
ratchet . ephemeralKeyPair = keyPair ;
return calculateRatchet ( session , remoteKey , true ) . then ( function ( ) {
ratchet . lastRemoteEphemeralKey = remoteKey ;
} ) ;
} ) ;
} ) ;
}
var previousRatchet = session [ getString ( ratchet . lastRemoteEphemeralKey ) ] ;
if ( previousRatchet !== undefined ) {
return fillMessageKeys ( previousRatchet , previousCounter ) . then ( function ( ) {
delete previousRatchet . chainKey . key ;
if ( ! objectContainsKeys ( previousRatchet . messageKeys ) )
delete session [ getString ( ratchet . lastRemoteEphemeralKey ) ] ;
else
session . oldRatchetList [ session . oldRatchetList . length ] = { added : new Date ( ) . getTime ( ) , ephemeralKey : ratchet . lastRemoteEphemeralKey } ;
} ) . then ( finish ) ;
} else
return finish ( ) ;
}
2015-01-21 18:56:34 -10:00
var doDecryptWhisperMessage = function ( encodedNumber , messageBytes , session , registrationId ) {
2015-02-10 16:39:50 -08:00
if ( messageBytes [ 0 ] != String . fromCharCode ( ( 3 << 4 ) | 3 ) )
throw new Error ( "Bad version number on WhisperMessage" ) ;
var messageProto = messageBytes . substring ( 1 , messageBytes . length - 8 ) ;
var mac = messageBytes . substring ( messageBytes . length - 8 , messageBytes . length ) ;
var message = axolotl . protobuf . WhisperMessage . decode ( messageProto , 'binary' ) ;
var remoteEphemeralKey = toArrayBuffer ( message . ephemeralKey ) ;
if ( session === undefined ) {
var session = crypto _storage . getSessionByRemoteEphemeralKey ( encodedNumber , remoteEphemeralKey ) ;
if ( session === undefined )
throw new Error ( "No session found to decrypt message from " + encodedNumber ) ;
}
return maybeStepRatchet ( session , remoteEphemeralKey , message . previousCounter ) . then ( function ( ) {
var chain = session [ getString ( message . ephemeralKey ) ] ;
return fillMessageKeys ( chain , message . counter ) . then ( function ( ) {
return HKDF ( toArrayBuffer ( chain . messageKeys [ message . counter ] ) , '' , "WhisperMessageKeys" ) . then ( function ( keys ) {
delete chain . messageKeys [ message . counter ] ;
var messageProtoArray = toArrayBuffer ( messageProto ) ;
var macInput = new Uint8Array ( messageProtoArray . byteLength + 33 * 2 + 1 ) ;
macInput . set ( new Uint8Array ( toArrayBuffer ( session . indexInfo . remoteIdentityKey ) ) ) ;
macInput . set ( new Uint8Array ( toArrayBuffer ( crypto _storage . getIdentityKey ( ) . pubKey ) ) , 33 ) ;
macInput [ 33 * 2 ] = ( 3 << 4 ) | 3 ;
macInput . set ( new Uint8Array ( messageProtoArray ) , 33 * 2 + 1 ) ;
return verifyMAC ( macInput . buffer , keys [ 1 ] , mac ) . then ( function ( ) {
return window . axolotl . crypto . decrypt ( keys [ 0 ] , toArrayBuffer ( message . ciphertext ) , keys [ 2 ] . slice ( 0 , 16 ) )
. then ( function ( paddedPlaintext ) {
paddedPlaintext = new Uint8Array ( paddedPlaintext ) ;
var plaintext ;
for ( var i = paddedPlaintext . length - 1 ; i >= 0 ; i -- ) {
if ( paddedPlaintext [ i ] == 0x80 ) {
plaintext = new Uint8Array ( i ) ;
plaintext . set ( paddedPlaintext . subarray ( 0 , i ) ) ;
plaintext = plaintext . buffer ;
break ;
} else if ( paddedPlaintext [ i ] != 0x00 )
throw new Error ( 'Invalid padding' ) ;
}
delete session [ 'pendingPreKey' ] ;
removeOldChains ( session ) ;
crypto _storage . saveSession ( encodedNumber , session , registrationId ) ;
2015-01-21 18:56:34 -10:00
return [ plaintext , function ( ) {
closeSession ( session , true ) ;
removeOldChains ( session ) ;
crypto _storage . saveSession ( encodedNumber , session ) ;
} ] ;
2015-02-10 16:39:50 -08:00
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
}
2015-01-21 18:56:34 -10:00
/ * * * * * * * * * * * * * * * * * * * * * * * * *
* * * Public crypto API * * *
* * * * * * * * * * * * * * * * * * * * * * * * * /
//TODO: SHARP EDGE HERE
//XXX: Also, you MUST call the session close function before processing another message....except its a promise...so you literally cant!
// returns decrypted plaintext and a function that must be called if the message indicates session close
self . decryptWhisperMessage = function ( encodedNumber , messageBytes , session ) {
return doDecryptWhisperMessage ( encodedNumber , messageBytes , session ) ;
}
2015-02-10 16:39:50 -08:00
// Inits a session (maybe) and then decrypts the message
self . handlePreKeyWhisperMessage = function ( from , encodedMessage ) {
var preKeyProto = axolotl . protobuf . PreKeyWhisperMessage . decode ( encodedMessage , 'binary' ) ;
return initSessionFromPreKeyWhisperMessage ( from , preKeyProto ) . then ( function ( sessions ) {
2015-01-21 18:56:34 -10:00
return doDecryptWhisperMessage ( from , getString ( preKeyProto . message ) , sessions [ 0 ] , preKeyProto . registrationId ) . then ( function ( result ) {
2015-02-10 16:39:50 -08:00
if ( sessions [ 1 ] !== undefined )
sessions [ 1 ] ( ) ;
return result ;
} ) ;
} ) ;
}
// return Promise(encoded [PreKey]WhisperMessage)
self . encryptMessageFor = function ( deviceObject , pushMessageContent ) {
var session = crypto _storage . getOpenSession ( deviceObject . encodedNumber ) ;
2015-01-20 22:48:09 -10:00
var hadSession = session !== undefined ;
2015-02-10 16:39:50 -08:00
var doEncryptPushMessageContent = function ( ) {
var msg = new axolotl . protobuf . WhisperMessage ( ) ;
var plaintext = toArrayBuffer ( pushMessageContent . encode ( ) ) ;
var paddedPlaintext = new Uint8Array ( Math . ceil ( ( plaintext . byteLength + 1 ) / 160.0 ) * 160 - 1 ) ;
paddedPlaintext . set ( new Uint8Array ( plaintext ) ) ;
paddedPlaintext [ plaintext . byteLength ] = 0x80 ;
msg . ephemeralKey = toArrayBuffer ( session . currentRatchet . ephemeralKeyPair . pubKey ) ;
var chain = session [ getString ( msg . ephemeralKey ) ] ;
return fillMessageKeys ( chain , chain . chainKey . counter + 1 ) . then ( function ( ) {
return HKDF ( toArrayBuffer ( chain . messageKeys [ chain . chainKey . counter ] ) , '' , "WhisperMessageKeys" ) . then ( function ( keys ) {
delete chain . messageKeys [ chain . chainKey . counter ] ;
msg . counter = chain . chainKey . counter ;
msg . previousCounter = session . currentRatchet . previousCounter ;
return window . axolotl . crypto . encrypt ( keys [ 0 ] , paddedPlaintext . buffer , keys [ 2 ] . slice ( 0 , 16 ) ) . then ( function ( ciphertext ) {
msg . ciphertext = ciphertext ;
var encodedMsg = toArrayBuffer ( msg . encode ( ) ) ;
var macInput = new Uint8Array ( encodedMsg . byteLength + 33 * 2 + 1 ) ;
macInput . set ( new Uint8Array ( toArrayBuffer ( crypto _storage . getIdentityKey ( ) . pubKey ) ) ) ;
macInput . set ( new Uint8Array ( toArrayBuffer ( session . indexInfo . remoteIdentityKey ) ) , 33 ) ;
macInput [ 33 * 2 ] = ( 3 << 4 ) | 3 ;
macInput . set ( new Uint8Array ( encodedMsg ) , 33 * 2 + 1 ) ;
return axolotl . crypto . sign ( keys [ 1 ] , macInput . buffer ) . then ( function ( mac ) {
var result = new Uint8Array ( encodedMsg . byteLength + 9 ) ;
result [ 0 ] = ( 3 << 4 ) | 3 ;
result . set ( new Uint8Array ( encodedMsg ) , 1 ) ;
result . set ( new Uint8Array ( mac , 0 , 8 ) , encodedMsg . byteLength + 1 ) ;
removeOldChains ( session ) ;
2015-01-20 22:48:09 -10:00
crypto _storage . saveSession ( deviceObject . encodedNumber , session , ! hadSession ? deviceObject . registrationId : undefined ) ;
2015-02-10 16:39:50 -08:00
return result ;
} ) ;
} ) ;
} ) ;
} ) ;
}
var preKeyMsg = new axolotl . protobuf . PreKeyWhisperMessage ( ) ;
preKeyMsg . identityKey = toArrayBuffer ( crypto _storage . getIdentityKey ( ) . pubKey ) ;
preKeyMsg . registrationId = axolotl . api . getMyRegistrationId ( ) ;
if ( session === undefined ) {
2015-01-21 18:56:34 -10:00
var deviceIdentityKey = toArrayBuffer ( deviceObject . identityKey ) ;
var deviceSignedKey = toArrayBuffer ( deviceObject . signedKey ) ;
return axolotl . crypto . Ed25519Verify ( deviceIdentityKey , deviceSignedKey , toArrayBuffer ( deviceObject . signedKeySignature ) ) . then ( function ( ) {
return axolotl . crypto . createKeyPair ( ) . then ( function ( baseKey ) {
preKeyMsg . preKeyId = deviceObject . preKeyId ;
preKeyMsg . signedPreKeyId = deviceObject . signedKeyId ;
preKeyMsg . baseKey = toArrayBuffer ( baseKey . pubKey ) ;
return initSession ( true , baseKey , undefined , deviceObject . encodedNumber ,
deviceIdentityKey , toArrayBuffer ( deviceObject . preKey ) , deviceSignedKey )
. then ( function ( new _session ) {
session = new _session ;
session . pendingPreKey = { preKeyId : deviceObject . preKeyId , signedKeyId : deviceObject . signedKeyId , baseKey : baseKey . pubKey } ;
return doEncryptPushMessageContent ( ) . then ( function ( message ) {
preKeyMsg . message = message ;
var result = String . fromCharCode ( ( 3 << 4 ) | 3 ) + getString ( preKeyMsg . encode ( ) ) ;
return { type : 3 , body : result } ;
} ) ;
2015-02-10 16:39:50 -08:00
} ) ;
} ) ;
} ) ;
} else
return doEncryptPushMessageContent ( ) . then ( function ( message ) {
if ( session . pendingPreKey !== undefined ) {
preKeyMsg . baseKey = toArrayBuffer ( session . pendingPreKey . baseKey ) ;
preKeyMsg . preKeyId = session . pendingPreKey . preKeyId ;
preKeyMsg . signedPreKeyId = session . pendingPreKey . signedKeyId ;
preKeyMsg . message = message ;
var result = String . fromCharCode ( ( 3 << 4 ) | 3 ) + getString ( preKeyMsg . encode ( ) ) ;
return { type : 3 , body : result } ;
} else
return { type : 1 , body : getString ( message ) } ;
} ) ;
}
var GENERATE _KEYS _KEYS _GENERATED = 100 ;
self . generateKeys = function ( ) {
var identityKeyPair = crypto _storage . getIdentityKey ( ) ;
var identityKeyCalculated = function ( identityKeyPair ) {
var firstPreKeyId = axolotl . api . storage . get ( "maxPreKeyId" , 0 ) ;
axolotl . api . storage . put ( "maxPreKeyId" , firstPreKeyId + GENERATE _KEYS _KEYS _GENERATED ) ;
var signedKeyId = axolotl . api . storage . get ( "signedKeyId" , 0 ) ;
axolotl . api . storage . put ( "signedKeyId" , signedKeyId + 1 ) ;
var keys = { } ;
keys . identityKey = identityKeyPair . pubKey ;
keys . preKeys = [ ] ;
var generateKey = function ( keyId ) {
return crypto _storage . getNewStoredKeyPair ( "preKey" + keyId , false ) . then ( function ( keyPair ) {
keys . preKeys [ keyId ] = { keyId : keyId , publicKey : keyPair . pubKey } ;
} ) ;
} ;
var promises = [ ] ;
for ( var i = firstPreKeyId ; i < firstPreKeyId + GENERATE _KEYS _KEYS _GENERATED ; i ++ )
promises [ i ] = generateKey ( i ) ;
promises [ firstPreKeyId + GENERATE _KEYS _KEYS _GENERATED ] = crypto _storage . getNewStoredKeyPair ( "signedKey" + signedKeyId ) . then ( function ( keyPair ) {
return axolotl . crypto . Ed25519Sign ( identityKeyPair . privKey , keyPair . pubKey ) . then ( function ( sig ) {
keys . signedPreKey = { keyId : signedKeyId , publicKey : keyPair . pubKey , signature : sig } ;
} ) ;
} ) ;
//TODO: Process by date added and agressively call generateKeys when we get near maxPreKeyId in a message
crypto _storage . removeStoredKeyPair ( "signedKey" + ( signedKeyId - 2 ) ) ;
return Promise . all ( promises ) . then ( function ( ) {
axolotl . api . storage . put ( "lastPreKeyUpdate" , Date . now ( ) ) ;
return keys ;
} ) ;
}
if ( identityKeyPair === undefined )
return crypto _storage . getNewStoredKeyPair ( "identityKey" ) . then ( function ( keyPair ) { return identityKeyCalculated ( keyPair ) ; } ) ;
else
return identityKeyCalculated ( identityKeyPair ) ;
}
refreshPreKeys = function ( ) {
self . generateKeys ( ) . then ( function ( keys ) {
console . log ( "Pre Keys updated!" ) ;
return axolotl . api . updateKeys ( keys ) ;
} ) . catch ( function ( e ) {
//TODO: Notify the user somehow???
console . error ( e ) ;
} ) ;
}
window . setInterval ( function ( ) {
// Note that this will not ever run until generateKeys has been called at least once
if ( axolotl . api . storage . get ( "lastPreKeyUpdate" , Date . now ( ) ) < Date . now ( ) - MESSAGE _LOST _THRESHOLD _MS )
refreshPreKeys ( ) ;
} , 60 * 1000 ) ;
self . createIdentityKeyRecvSocket = function ( ) {
var socketInfo = { } ;
var keyPair ;
socketInfo . decryptAndHandleDeviceInit = function ( deviceInit ) {
var masterEphemeral = toArrayBuffer ( deviceInit . publicKey ) ;
var message = toArrayBuffer ( deviceInit . body ) ;
return axolotl . crypto . ECDHE ( masterEphemeral , keyPair . privKey ) . then ( function ( ecRes ) {
return HKDF ( ecRes , '' , "TextSecure Provisioning Message" ) . then ( function ( keys ) {
if ( new Uint8Array ( message ) [ 0 ] != 1 )
throw new Error ( "Bad version number on ProvisioningMessage" ) ;
var iv = message . slice ( 1 , 16 + 1 ) ;
var mac = message . slice ( message . byteLength - 32 , message . byteLength ) ;
var ivAndCiphertext = message . slice ( 0 , message . byteLength - 32 ) ;
var ciphertext = message . slice ( 16 + 1 , message . byteLength - 32 ) ;
return verifyMAC ( ivAndCiphertext , keys [ 1 ] , mac ) . then ( function ( ) {
return window . axolotl . crypto . decrypt ( keys [ 0 ] , ciphertext , iv ) . then ( function ( plaintext ) {
var identityKeyMsg = axolotl . protobuf . ProvisionMessage . decode ( plaintext ) ;
return axolotl . crypto . createKeyPair ( toArrayBuffer ( identityKeyMsg . identityKeyPrivate ) ) . then ( function ( identityKeyPair ) {
if ( crypto _storage . getStoredKeyPair ( "identityKey" ) !== undefined )
throw new Error ( "Tried to overwrite identity key" ) ;
crypto _storage . putKeyPair ( "identityKey" , identityKeyPair ) ;
identityKeyMsg . identityKeyPrivate = null ;
return identityKeyMsg ;
} ) ;
} ) ;
} ) ;
} ) ;
} ) ;
}
return axolotl . crypto . createKeyPair ( ) . then ( function ( newKeyPair ) {
keyPair = newKeyPair ;
socketInfo . pubKey = keyPair . pubKey ;
return socketInfo ;
} ) ;
}
return self ;
} ( ) ;
} ) ( ) ;
; ( function ( ) {
function loadProtoBufs ( filename ) {
return dcodeIO . ProtoBuf . loadProtoFile ( { root : 'protos' , file : filename } ) . build ( 'textsecure' ) ;
} ;
var protocolMessages = loadProtoBufs ( 'WhisperTextProtocol.proto' ) ;
var deviceMessages = loadProtoBufs ( 'DeviceMessages.proto' ) ;
window . axolotl = window . axolotl || { } ;
window . axolotl . protobuf = {
WhisperMessage : protocolMessages . WhisperMessage ,
PreKeyWhisperMessage : protocolMessages . PreKeyWhisperMessage ,
DeviceInit : deviceMessages . DeviceInit ,
IdentityKey : deviceMessages . IdentityKey ,
DeviceControl : deviceMessages . DeviceControl ,
2015-02-12 16:34:25 -08:00
ProvisionMessage : deviceMessages . ProvisionMessage ,
2015-02-10 16:39:50 -08:00
} ;
} ) ( ) ;
2015-01-20 22:48:09 -10:00
/ * v i m : t s = 4 : s w = 4
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
* /
; ( function ( ) {
'use strict' ;
window . axolotl = window . axolotl || { } ;
var RecipientRecord = function ( identityKey , registrationId ) {
this . _sessions = { } ;
this . identityKey = identityKey !== undefined ? getString ( identityKey ) : null ;
this . registrationId = registrationId ;
if ( this . registrationId === undefined || typeof this . registrationId !== "number" )
this . registrationId = null ;
} ;
RecipientRecord . prototype . serialize = function ( ) {
return textsecure . utils . jsonThing ( { sessions : this . _sessions , registrationId : this . registrationId , identityKey : this . identityKey } ) ;
}
RecipientRecord . prototype . deserialize = function ( serialized ) {
var data = JSON . parse ( serialized ) ;
this . _sessions = data . sessions ;
if ( this . _sessions === undefined || this . _sessions === null || typeof this . _sessions !== "object" || Array . isArray ( this . _sessions ) )
throw new Error ( "Error deserializing RecipientRecord" ) ;
this . identityKey = data . identityKey ;
this . registrationId = data . registrationId ;
if ( this . identityKey === undefined || this . registrationId === undefined )
throw new Error ( "Error deserializing RecipientRecord" ) ;
}
RecipientRecord . prototype . haveOpenSession = function ( ) {
return this . registrationId !== null ;
}
window . axolotl . sessions = {
RecipientRecord : RecipientRecord ,
} ;
} ) ( ) ;