5 if ( typeof define ===
"function" && define.amd ) {
7 define( [
'JSRootCore',
'rawinflate'], factory );
9 if (typeof JSROOT ==
'undefined')
10 throw new Error(
"This extension requires JSRootCore.js",
"JSRootIOEvolution.js");
12 if (typeof JSROOT.IO ==
"object")
13 throw new Error(
"This JSROOT IO already loaded",
"JSRootIOEvolution.js");
20 kBase : 0, kOffsetL : 20, kOffsetP : 40, kCounter : 6, kCharStar : 7,
21 kChar : 1, kShort : 2, kInt : 3, kLong : 4, kFloat : 5,
22 kDouble : 8, kDouble32 : 9, kLegacyChar : 10, kUChar : 11, kUShort : 12,
23 kUInt : 13, kULong : 14, kBits : 15, kLong64 : 16, kULong64 : 17, kBool : 18,
25 kObject : 61, kAny : 62, kObjectp : 63, kObjectP : 64, kTString : 65,
26 kTObject : 66, kTNamed : 67, kAnyp : 68, kAnyP : 69, kAnyPnoVT : 70,
28 kSkip : 100, kSkipL : 120, kSkipP : 140,
29 kConv : 200, kConvL : 220, kConvP : 240,
30 kSTL : 300, kSTLstring : 365,
31 kStreamer : 500, kStreamLoop : 501,
33 kByteCountMask : 0x40000000,
34 kNewClassTag : 0xFFFFFFFF,
35 kClassMask : 0x80000000,
42 JSROOT.fUserStreamers = null;
44 JSROOT.addUserStreamer =
function(type, user_streamer) {
45 if (JSROOT.fUserStreamers == null) JSROOT.fUserStreamers = {};
46 JSROOT.fUserStreamers[type] = user_streamer;
49 JSROOT.R__unzip =
function(str, tgtsize, noalert) {
52 var isarr = (typeof str !=
'string') && (
'byteLength' in str),
53 totallen = isarr ? str.byteLength : str.length,
54 curr = 0, fullres = 0, tgtbuf = null;
57 return isarr ? String.fromCharCode(str.getUint8(o)) : str.charAt(o);
61 return isarr ? str.getUint8(o) : str.charCodeAt(o);
64 while (fullres < tgtsize) {
66 if (curr + JSROOT.IO.Z_HDRSIZE >= totallen) {
67 if (!noalert) alert(
"Error R__unzip: header size exceeds buffer size");
72 if (!((getChar(curr) ==
'Z' && getChar(curr+1) ==
'L' && getCode(curr+2) == JSROOT.IO.Z_DEFLATED))) {
73 if (!noalert) alert(
"R__unzip: Old zlib format is not supported!");
77 var srcsize = JSROOT.IO.Z_HDRSIZE +
78 ((getCode(curr+3) & 0xff) | ((getCode(curr+4) & 0xff) << 8) | ((getCode(curr+5) & 0xff) << 16));
82 var uint8arr =
new Uint8Array(str.buffer, str.byteOffset + curr + JSROOT.IO.Z_HDRSIZE + 2, str.byteLength - curr - JSROOT.IO.Z_HDRSIZE - 2);
85 if (tgtbuf===null) tgtbuf =
new ArrayBuffer(tgtsize);
87 var reslen = window.RawInflate.arr_inflate(uint8arr,
new Uint8Array(tgtbuf, fullres));
93 var unpacked = window.RawInflate.inflate(str.substr(JSROOT.IO.Z_HDRSIZE + 2 + curr, srcsize));
94 if ((unpacked === null) || (unpacked.length===0))
break;
95 if (tgtbuf===null) tgtbuf = unpacked;
else tgtbuf += unpacked;
96 fullres += unpacked.length;
102 if (fullres !== tgtsize) {
103 if (!noalert) alert(
"R__unzip: fail to unzip data expacts " + tgtsize +
" , got " + fullres);
107 return isarr ?
new DataView(tgtbuf) : tgtbuf;
112 JSROOT.TBuffer =
function(_o, _file) {
113 this._typename =
"TBuffer";
114 this.o = (_o==null) ? 0 : _o;
116 this.ClearObjectMap();
118 this.last_read_version = 0;
122 JSROOT.TBuffer.prototype.locate =
function(pos) {
126 JSROOT.TBuffer.prototype.shift =
function(cnt) {
130 JSROOT.TBuffer.prototype.GetMappedObject =
function(tag) {
131 return this.fObjectMap[tag];
134 JSROOT.TBuffer.prototype.MapObject =
function(tag, obj) {
136 this.fObjectMap[tag] = obj;
139 JSROOT.TBuffer.prototype.MapClass =
function(tag, classname) {
140 this.fClassMap[tag] = classname;
143 JSROOT.TBuffer.prototype.GetMappedClass =
function(tag) {
144 if (tag in this.fClassMap)
return this.fClassMap[tag];
148 JSROOT.TBuffer.prototype.ClearObjectMap =
function() {
149 this.fObjectMap = {};
151 this.fObjectMap[0] = null;
154 JSROOT.TBuffer.prototype.ReadVersion =
function() {
157 var bytecnt = this.ntou4();
158 if (bytecnt & JSROOT.IO.kByteCountMask)
159 ver.bytecnt = bytecnt - JSROOT.IO.kByteCountMask - 2;
163 this.last_read_version = ver.val = this.ntou2();
168 JSROOT.TBuffer.prototype.CheckBytecount =
function(ver, where) {
169 if ((
'bytecnt' in ver) && (ver.off + ver.bytecnt !== this.o)) {
171 alert(
"Missmatch in " + where +
" bytecount expected = " + ver[
'bytecnt'] +
" got = " + (this.o-ver[
'off']));
172 this.o = ver.off + ver.bytecnt;
178 JSROOT.TBuffer.prototype.ReadString =
function() {
180 var pos0 = this.o, len = this.totalLength();
181 while (this.o < len) {
182 if (this.codeAt(this.o++) == 0)
break;
184 return (this.o > pos0) ? this.substring(pos0, this.o-1) :
"";
187 JSROOT.TBuffer.prototype.ReadTString =
function() {
189 var len = this.ntou1();
191 if (len == 255) len = this.ntou4();
192 if (len==0)
return "";
197 return (this.codeAt(pos) == 0) ?
'' : this.substring(pos, pos + len);
200 JSROOT.TBuffer.prototype.ReadFastArray =
function(n, array_type) {
204 switch (array_type) {
205 case JSROOT.IO.kDouble:
206 array = JSROOT.IO.NativeArray ?
new Float64Array(n) : new Array(n);
207 for (var i = 0; i < n; ++i)
208 array[i] = this.ntod();
210 case JSROOT.IO.kFloat:
211 case JSROOT.IO.kDouble32:
212 array = JSROOT.IO.NativeArray ?
new Float32Array(n) : new Array(n);
213 for (var i = 0; i < n; ++i)
214 array[i] = this.ntof();
216 case JSROOT.IO.kLong:
217 case JSROOT.IO.kLong64:
218 array = JSROOT.IO.NativeArray ?
new Float64Array(n) : new Array(n);
219 for (var i = 0; i < n; ++i)
220 array[i] = this.ntoi8();
222 case JSROOT.IO.kULong:
223 case JSROOT.IO.kULong64:
224 array = JSROOT.IO.NativeArray ?
new Float64Array(n) : new Array(n);
225 for (var i = 0; i < n; ++i)
226 array[i] = this.ntou8();
229 array = JSROOT.IO.NativeArray ?
new Int32Array(n) : new Array(n);
230 for (var i = 0; i < n; ++i)
231 array[i] = this.ntoi4();
233 case JSROOT.IO.kUInt:
234 array = JSROOT.IO.NativeArray ?
new Uint32Array(n) : new Array(n);
235 for (var i = 0; i < n; ++i)
236 array[i] = this.ntou4();
238 case JSROOT.IO.kShort:
239 array = JSROOT.IO.NativeArray ?
new Int16Array(n) : new Array(n);
240 for (var i = 0; i < n; ++i)
241 array[i] = this.ntoi2();
243 case JSROOT.IO.kUShort:
244 array = JSROOT.IO.NativeArray ?
new Uint16Array(n) : new Array(n);
245 for (var i = 0; i < n; ++i)
246 array[i] = this.ntou2();
248 case JSROOT.IO.kChar:
249 array = JSROOT.IO.NativeArray ?
new Int8Array(n) : new Array(n);
250 for (var i = 0; i < n; ++i)
251 array[i] = this.ntoi1();
253 case JSROOT.IO.kUChar:
254 array = JSROOT.IO.NativeArray ?
new Uint8Array(n) : new Array(n);
255 for (var i = 0; i < n; ++i)
256 array[i] = this.ntoi1();
258 case JSROOT.IO.kTString:
259 array =
new Array(n);
260 for (var i = 0; i < n; ++i)
261 array[i] = this.ReadTString();
264 array =
new Array(n);
265 for (var i = 0; i < n; ++i)
266 array[i] = this.ntou4();
272 JSROOT.IO.GetArrayKind =
function(type_name) {
273 if (type_name.length < 7)
return -1;
274 if (type_name.indexOf(
"TArray")!=0)
return -1;
275 if (type_name.length == 7)
276 switch (type_name.charAt(6)) {
277 case 'I':
return JSROOT.IO.kInt;
278 case 'D':
return JSROOT.IO.kDouble;
279 case 'F':
return JSROOT.IO.kFloat;
280 case 'S':
return JSROOT.IO.kShort;
281 case 'C':
return JSROOT.IO.kChar;
282 case 'L':
return JSROOT.IO.kLong;
286 return type_name ==
"TArrayL64" ? JSROOT.IO.kLong64 : -1;
289 JSROOT.TBuffer.prototype.ReadTKey =
function(key) {
290 key.fNbytes = this.ntoi4();
291 key.fVersion = this.ntoi2();
292 key.fObjlen = this.ntou4();
293 var datime = this.ntou4();
294 key.fDatime =
new Date();
295 key.fDatime.setFullYear((datime >>> 26) + 1995);
296 key.fDatime.setMonth((datime << 6) >>> 28);
297 key.fDatime.setDate((datime << 10) >>> 27);
298 key.fDatime.setHours((datime << 15) >>> 27);
299 key.fDatime.setMinutes((datime << 20) >>> 26);
300 key.fDatime.setSeconds((datime << 26) >>> 26);
301 key.fDatime.setMilliseconds(0);
302 key.fKeylen = this.ntou2();
303 key.fCycle = this.ntou2();
304 if (key.fVersion > 1000) {
305 key.fSeekKey = this.ntou8();
308 key.fSeekKey = this.ntou4();
311 key.fClassName = this.ReadTString();
312 key.fName = this.ReadTString();
313 key.fTitle = this.ReadTString();
315 var name = key.fName.replace(/[
'"]/g,'');
317 if (name !== key.fName) {
318 key.fRealName = key.fName;
325 JSROOT.TBuffer.prototype.ReadTBasket = function(obj) {
327 var ver = this.ReadVersion();
328 obj.fBufferSize = this.ntoi4();
329 obj.fNevBufSize = this.ntoi4();
330 obj.fNevBuf = this.ntoi4();
331 obj.fLast = this.ntoi4();
332 var flag = this.ntoi1();
333 // here we implement only data skipping, no real I/O for TBasket is performed
334 if ((flag % 10) != 2) {
335 var sz = this.ntoi4(); this.shift(sz*4); // fEntryOffset
336 if (flag>40) { sz = this.ntoi4(); this.shift(sz*4); } // fDisplacement
339 if (flag == 1 || flag > 10) {
341 if (ver.val <= 1) sz = this.ntoi4();
342 this.o += sz; // fBufferRef
344 return this.CheckBytecount(ver,"ReadTBasket");
347 JSROOT.TBuffer.prototype.ReadClass = function() {
348 // read class definition from I/O buffer
349 var classInfo = { name: -1 };
351 var bcnt = this.ntou4();
353 var startpos = this.o;
354 if (!(bcnt & JSROOT.IO.kByteCountMask) || (bcnt == JSROOT.IO.kNewClassTag)) {
360 if (!(tag & JSROOT.IO.kClassMask)) {
361 classInfo.objtag = tag; // indicate that we have deal with objects tag
364 if (tag == JSROOT.IO.kNewClassTag) {
365 // got a new class description followed by a new object
366 classInfo.name = this.ReadString();
368 if (this.GetMappedClass(this.fTagOffset + startpos + JSROOT.IO.kMapOffset) === -1)
369 this.MapClass(this.fTagOffset + startpos + JSROOT.IO.kMapOffset, classInfo.name);
372 // got a tag to an already seen class
373 var clTag = (tag & ~JSROOT.IO.kClassMask);
374 classInfo.name = this.GetMappedClass(clTag);
376 if (classInfo.name === -1) {
377 alert("Did not found class with tag " + clTag);
385 JSROOT.TBuffer.prototype.ReadObjectAny = function() {
386 var objtag = this.fTagOffset + this.o + JSROOT.IO.kMapOffset;
388 var clRef = this.ReadClass();
390 // class identified as object and should be handled so
391 if ('objtag
' in clRef)
392 return this.GetMappedObject(clRef.objtag);
394 if (clRef.name === -1) return null;
396 var arrkind = JSROOT.IO.GetArrayKind(clRef.name);
401 // reading array, can map array only afterwards
402 obj = this.ReadFastArray(this.ntou4(), arrkind);
403 this.MapObject(objtag, obj);
405 // reading normal object, should map before to
406 this.MapObject(objtag, obj);
407 this.ClassStreamer(obj, clRef.name);
413 JSROOT.TBuffer.prototype.ClassStreamer = function(obj, classname) {
415 if (! ('_typename
' in obj)) obj._typename = classname;
417 var streamer = this.fFile.GetStreamer(classname);
419 if (streamer !== null) {
420 var ver = this.ReadVersion();
422 for (var n = 0; n < streamer.length; ++n)
423 streamer[n].func(this, obj);
425 this.CheckBytecount(ver, classname);
426 // methods will be assigned by last entry in the streamer
428 else if (classname == 'TQObject
') {
431 else if (classname == "TBasket") {
432 this.ReadTBasket(obj);
433 JSROOT.addMethods(obj);
435 // just skip bytes belonging to not-recognized object
436 var ver = this.ReadVersion();
437 this.CheckBytecount(ver);
438 JSROOT.addMethods(obj);
445 // =================================================================================
447 JSROOT.TStrBuffer = function(str, pos, file) {
448 JSROOT.TBuffer.call(this, pos, file);
452 JSROOT.TStrBuffer.prototype = Object.create(JSROOT.TBuffer.prototype);
454 JSROOT.TStrBuffer.prototype.totalLength = function() {
455 return this.b ? this.b.length : 0;
458 JSROOT.TStrBuffer.prototype.extract = function(off,len) {
459 return this.b.substr(off, len);
462 JSROOT.TStrBuffer.prototype.ntou1 = function() {
463 return (this.b.charCodeAt(this.o++) & 0xff) >>> 0;
466 JSROOT.TStrBuffer.prototype.ntou2 = function() {
467 // convert (read) two bytes of buffer b into a UShort_t
468 var n = ((this.b.charCodeAt(this.o++) & 0xff) << 8) >>> 0;
469 n += (this.b.charCodeAt(this.o++) & 0xff) >>> 0;
473 JSROOT.TStrBuffer.prototype.ntou4 = function() {
474 // convert (read) four bytes of buffer b into a UInt_t
475 var n = ((this.b.charCodeAt(this.o++) & 0xff) << 24) >>> 0;
476 n += ((this.b.charCodeAt(this.o++) & 0xff) << 16) >>> 0;
477 n += ((this.b.charCodeAt(this.o++) & 0xff) << 8) >>> 0;
478 n += (this.b.charCodeAt(this.o++) & 0xff) >>> 0;
482 JSROOT.TStrBuffer.prototype.ntou8 = function() {
483 // convert (read) eight bytes of buffer b into a ULong_t
484 var n = ((this.b.charCodeAt(this.o++) & 0xff) << 56) >>> 0;
485 n += ((this.b.charCodeAt(this.o++) & 0xff) << 48) >>> 0;
486 n += ((this.b.charCodeAt(this.o++) & 0xff) << 40) >>> 0;
487 n += ((this.b.charCodeAt(this.o++) & 0xff) << 32) >>> 0;
488 n += ((this.b.charCodeAt(this.o++) & 0xff) << 24) >>> 0;
489 n += ((this.b.charCodeAt(this.o++) & 0xff) << 16) >>> 0;
490 n += ((this.b.charCodeAt(this.o++) & 0xff) << 8) >>> 0;
491 n += (this.b.charCodeAt(this.o++) & 0xff) >>> 0;
495 JSROOT.TStrBuffer.prototype.ntoi1 = function() {
496 return (this.b.charCodeAt(this.o++) & 0xff);
499 JSROOT.TStrBuffer.prototype.ntoi2 = function() {
500 // convert (read) two bytes of buffer b into a Short_t
501 var n = ((this.b.charCodeAt(this.o++) & 0xff) << 8);
502 n += ((this.b.charCodeAt(this.o++) & 0xff));
503 return (n < 0x8000) ? n : -1 - (~n &0xFFFF);
506 JSROOT.TStrBuffer.prototype.ntoi4 = function() {
507 // convert (read) four bytes of buffer b into a Int_t
508 var n = ((this.b.charCodeAt(this.o++) & 0xff) << 24);
509 n += ((this.b.charCodeAt(this.o++) & 0xff) << 16);
510 n += ((this.b.charCodeAt(this.o++) & 0xff) << 8);
511 n += ((this.b.charCodeAt(this.o++) & 0xff));
515 JSROOT.TStrBuffer.prototype.ntoi8 = function(b, o) {
516 // convert (read) eight bytes of buffer b into a Long_t
517 var n = (this.b.charCodeAt(this.o++) & 0xff) << 56;
518 n += (this.b.charCodeAt(this.o++) & 0xff) << 48;
519 n += (this.b.charCodeAt(this.o++) & 0xff) << 40;
520 n += (this.b.charCodeAt(this.o++) & 0xff) << 32;
521 n += (this.b.charCodeAt(this.o++) & 0xff) << 24;
522 n += (this.b.charCodeAt(this.o++) & 0xff) << 16;
523 n += (this.b.charCodeAt(this.o++) & 0xff) << 8;
524 n += (this.b.charCodeAt(this.o++) & 0xff);
528 JSROOT.TStrBuffer.prototype.ntof = function() {
529 // IEEE-754 Floating-Point Conversion (single precision - 32 bits)
530 var inString = this.b.substring(this.o, this.o + 4); this.o+=4;
531 if (inString.length < 4) return Number.NaN;
533 for (var i=0; i<4; ++i) {
534 var curByte = (inString.charCodeAt(i) & 0xff).toString(2);
535 var byteLen = curByte.length;
537 for (var bit=0; bit<(8-byteLen); ++bit)
538 curByte = '0
' + curByte;
540 bits = bits + curByte;
542 //var bsign = parseInt(bits[0]) ? -1 : 1;
543 var bsign = (bits.charAt(0) == '1
') ? -1 : 1;
544 var bexp = parseInt(bits.substring(1, 9), 2) - 127;
550 for (var i=0; i<23; ++i) {
551 if (parseInt(bits.substr(9+i, 1)) == 1)
552 bman = bman + 1 / Math.pow(2, i+1);
555 var res = bsign * Math.pow(2, bexp) * bman;
556 return (Math.abs(res) < 1e-300) ? 0.0 : res;
559 JSROOT.TStrBuffer.prototype.ntod = function() {
560 // IEEE-754 Floating-Point Conversion (double precision - 64 bits)
561 var inString = this.b.substring(this.o, this.o + 8); this.o+=8;
562 if (inString.length < 8) return Number.NaN;
564 for (var i=0; i<8; ++i) {
565 var curByte = (inString.charCodeAt(i) & 0xff).toString(2);
566 var byteLen = curByte.length;
568 for (var bit=0; bit<(8-byteLen); ++bit)
569 curByte = '0
' + curByte;
571 bits = bits + curByte;
573 //var bsign = parseInt(bits[0]) ? -1 : 1;
574 var bsign = (bits.charAt(0) == '1
') ? -1 : 1;
575 var bexp = parseInt(bits.substring(1, 12), 2) - 1023;
581 for (var i=0; i<52; ++i) {
582 if (parseInt(bits.substr(12+i, 1)) == 1)
583 bman = bman + 1 / Math.pow(2, i+1);
586 var res = (bsign * Math.pow(2, bexp) * bman);
587 return (Math.abs(res) < 1e-300) ? 0.0 : res;
590 JSROOT.TStrBuffer.prototype.codeAt = function(pos) {
591 return this.b.charCodeAt(pos) & 0xff;
594 JSROOT.TStrBuffer.prototype.substring = function(beg, end) {
595 return this.b.substring(beg, end);
598 // =======================================================================
600 JSROOT.TArrBuffer = function(arr, pos, file) {
601 // buffer should work with DataView as first argument
602 JSROOT.TBuffer.call(this, pos, file);
606 JSROOT.TArrBuffer.prototype = Object.create(JSROOT.TBuffer.prototype);
608 JSROOT.TArrBuffer.prototype.totalLength = function() {
609 return this.arr && this.arr.buffer ? this.arr.buffer.byteLength : 0;
612 JSROOT.TArrBuffer.prototype.extract = function(off,len) {
613 if (!this.arr || !this.arr.buffer || (this.arr.buffer.byteLength < off+len)) return null;
614 return new DataView(this.arr.buffer, off, len);
617 JSROOT.TArrBuffer.prototype.codeAt = function(pos) {
618 return this.arr.getUint8(pos);
621 JSROOT.TArrBuffer.prototype.substring = function(beg, end) {
623 for (var n=beg;n<end;++n)
624 res += String.fromCharCode(this.arr.getUint8(n));
628 JSROOT.TArrBuffer.prototype.ntou1 = function() {
629 return this.arr.getUint8(this.o++);
632 JSROOT.TArrBuffer.prototype.ntou2 = function() {
633 var o = this.o; this.o+=2;
634 return this.arr.getUint16(o);
637 JSROOT.TArrBuffer.prototype.ntou4 = function() {
638 var o = this.o; this.o+=4;
639 return this.arr.getUint32(o);
642 JSROOT.TArrBuffer.prototype.ntou8 = function() {
643 var high = this.arr.getUint32(this.o); this.o+=4;
644 var low = this.arr.getUint32(this.o); this.o+=4;
645 return high * 0x100000000 + low;
648 JSROOT.TArrBuffer.prototype.ntoi1 = function() {
649 return this.arr.getInt8(this.o++);
652 JSROOT.TArrBuffer.prototype.ntoi2 = function() {
653 var o = this.o; this.o+=2;
654 return this.arr.getInt16(o);
657 JSROOT.TArrBuffer.prototype.ntoi4 = function() {
658 var o = this.o; this.o+=4;
659 return this.arr.getInt32(o);
662 JSROOT.TArrBuffer.prototype.ntoi8 = function() {
663 var high = this.arr.getUint32(this.o); this.o+=4;
664 var low = this.arr.getUint32(this.o); this.o+=4;
665 if (high < 0x80000000) return high * 0x100000000 + low;
666 return -1 - ((~high) * 0x100000000 + ~low);
669 JSROOT.TArrBuffer.prototype.ntof = function() {
670 var o = this.o; this.o+=4;
671 return this.arr.getFloat32(o);
674 JSROOT.TArrBuffer.prototype.ntod = function() {
675 var o = this.o; this.o+=8;
676 return this.arr.getFloat64(o);
679 // =======================================================================
681 JSROOT.CreateTBuffer = function(blob, pos, file) {
682 if ((blob==null) || (typeof(blob) == 'string'))
683 return new JSROOT.TStrBuffer(blob, pos, file);
685 return new JSROOT.TArrBuffer(blob, pos, file);
688 JSROOT.ReconstructObject = function(class_name, obj_rawdata, sinfo_rawdata) {
689 // method can be used to reconstruct ROOT object from binary buffer
690 // Buffer can be requested from online server with request like:
691 // http://localhost:8080/Files/job1.root/hpx/root.bin
692 // One also requires buffer with streamer infos, reqeusted with command
693 // http://localhost:8080/StreamerInfo/root.bin
694 // And one should provide class name of the object
696 // Method provided for convenience only to see how binary JSROOT.IO works.
697 // It is strongly recommended to use JSON representation:
698 // http://localhost:8080/Files/job1.root/hpx/root.json
700 var file = new JSROOT.TFile;
701 var buf = JSROOT.CreateTBuffer(sinfo_rawdata, 0, file);
702 file.ExtractStreamerInfos(buf);
706 buf = JSROOT.CreateTBuffer(obj_rawdata, 0, file);
707 buf.MapObject(obj, 1);
708 buf.ClassStreamer(obj, class_name);
713 // ==============================================================================
715 // A class that reads a TDirectory from a buffer.
718 JSROOT.TDirectory = function(file, dirname, cycle) {
719 if (! (this instanceof arguments.callee) )
720 throw new Error("you must use new to instantiate this class", "JSROOT.TDirectory.ctor");
723 this._typename = "TDirectory";
724 this.dir_name = dirname;
725 this.dir_cycle = cycle;
726 this.fKeys = new Array();
730 JSROOT.TDirectory.prototype.GetKey = function(keyname, cycle, call_back) {
731 // retrieve a key by its name and cycle in the list of keys
732 for (var i=0; i < this.fKeys.length; ++i) {
733 if (this.fKeys[i].fName == keyname && this.fKeys[i].fCycle == cycle) {
734 JSROOT.CallBack(call_back, this.fKeys[i]);
735 return this.fKeys[i];
739 var pos = keyname.lastIndexOf("/");
740 // try to handle situation when object name contains slashed (bad practice anyway)
742 var dirname = keyname.substr(0, pos);
743 var subname = keyname.substr(pos+1);
745 var dirkey = this.GetKey(dirname, 1);
746 if ((dirkey!==null) && (typeof call_back == 'function') &&
747 (dirkey.fClassName.indexOf("TDirectory")==0)) {
749 this.fFile.ReadObject(this.dir_name + "/" + dirname, 1, function(newdir) {
750 if (newdir) newdir.GetKey(subname, cycle, call_back);
755 pos = keyname.lastIndexOf("/", pos-1);
759 JSROOT.CallBack(call_back, null);
763 JSROOT.TDirectory.prototype.ReadKeys = function(readkeys_callback) {
765 var file = this.fFile;
767 //*-*-------------Read directory info
768 var nbytes = this.fNbytesName + 22;
769 nbytes += 4; // fDatimeC.Sizeof();
770 nbytes += 4; // fDatimeM.Sizeof();
771 nbytes += 18; // fUUID.Sizeof();
772 // assume that the file may be above 2 Gbytes if file version is > 4
773 if (file.fVersion >= 40000) nbytes += 12;
775 file.Seek(this.fSeekDir, this.fFile.ERelativeTo.kBeg);
776 file.ReadBuffer(nbytes, function(blob1) {
777 if (blob1==null) return JSROOT.CallBack(readkeys_callback,null);
778 var buf = JSROOT.CreateTBuffer(blob1, thisdir.fNbytesName, file);
780 thisdir.StreamHeader(buf);
782 //*-*---------read TKey::FillBuffer info
783 buf.locate(4); // Skip NBytes;
784 var keyversion = buf.ntoi2();
785 // Skip ObjLen, DateTime, KeyLen, Cycle, SeekKey, SeekPdir
786 if (keyversion > 1000) buf.shift(28); // Large files
790 thisdir.fTitle = buf.ReadTString();
791 if (thisdir.fNbytesName < 10 || thisdir.fNbytesName > 10000) {
792 JSROOT.console("Cannot read directory info of file " + file.fURL);
793 return JSROOT.CallBack(readkeys_callback, null);
795 //*-* -------------Read keys of the top directory
797 if (thisdir.fSeekKeys <=0)
798 return JSROOT.CallBack(readkeys_callback, null);
800 file.Seek(thisdir.fSeekKeys, file.ERelativeTo.kBeg);
801 file.ReadBuffer(thisdir.fNbytesKeys, function(blob2) {
802 if (blob2 == null) return JSROOT.CallBack(readkeys_callback, null);
803 var buf = JSROOT.CreateTBuffer(blob2, 0, file);
805 var key = file.ReadKey(buf);
807 var nkeys = buf.ntoi4();
808 for (var i = 0; i < nkeys; ++i) {
809 key = file.ReadKey(buf);
810 thisdir.fKeys.push(key);
812 file.fDirectories.push(thisdir);
815 JSROOT.CallBack(readkeys_callback, thisdir);
822 JSROOT.TDirectory.prototype.StreamHeader = function(buf) {
823 var version = buf.ntou2();
824 var versiondir = version % 1000;
825 buf.shift(8); // skip fDatimeC and fDatimeM
826 this.fNbytesKeys = buf.ntou4();
827 this.fNbytesName = buf.ntou4();
828 this.fSeekDir = (version > 1000) ? buf.ntou8() : buf.ntou4();
829 this.fSeekParent = (version > 1000) ? buf.ntou8() : buf.ntou4();
830 this.fSeekKeys = (version > 1000) ? buf.ntou8() : buf.ntou4();
831 if (versiondir > 2) buf.shift(18); // skip fUUID
835 // ==============================================================================
836 // A class that reads ROOT files.
839 // A ROOT file is a suite of consecutive data records (TKey's) with
861 JSROOT.TFile =
function(url, newfile_callback) {
862 if (! (
this instanceof arguments.callee) )
863 throw new Error(
"you must use new to instantiate this class",
"JSROOT.TFile.ctor");
865 this._typename =
"TFile";
870 this.fAcceptRanges =
true;
871 this.fUseStampPar =
new Date;
872 this.fFileContent = null;
875 this.ERelativeTo = { kBeg : 0, kCur : 1, kEnd : 2 };
876 this.fDirectories =
new Array();
877 this.fKeys =
new Array();
879 this.fNbytesInfo = 0;
882 this.fStreamerInfos = null;
884 this.fStreamers =
new Array;
886 if (typeof this.fURL !=
'string')
return this;
888 if (this.fURL.charAt(
this.fURL.length-1) ==
"+") {
889 this.fURL = this.fURL.substr(0, this.fURL.length-1);
890 this.fAcceptRanges =
false;
893 var pos = Math.max(this.fURL.lastIndexOf(
"/"), this.fURL.lastIndexOf(
"\\"));
894 this.fFileName = pos>=0 ? this.fURL.substr(pos+1) : this.fURL;
896 if (!this.fAcceptRanges) {
897 this.ReadKeys(newfile_callback);
901 var xhr = JSROOT.NewHttpRequest(this.fURL,
"head",
function(res) {
903 return JSROOT.CallBack(newfile_callback, null);
905 var accept_ranges = res.getResponseHeader(
"Accept-Ranges");
906 if (accept_ranges==null) file.fAcceptRanges =
false;
907 var len = res.getResponseHeader(
"Content-Length");
908 if (len!=null) file.fEND = parseInt(len);
909 else file.fAcceptRanges =
false;
910 file.ReadKeys(newfile_callback);
919 JSROOT.TFile.prototype.ReadBuffer =
function(len, callback) {
921 if ((this.fFileContent!=null) && (!this.fAcceptRanges || (this.fOffset+len <= this.fFileContent.totalLength())))
922 return callback(this.fFileContent.extract(
this.fOffset, len));
927 if (this.fUseStampPar) {
929 if (url.indexOf(
'?')>0) url+=
"&stamp=";
else url +=
"?stamp=";
930 url += this.fUseStampPar.getTime();
933 function read_callback(res) {
935 if ((res==null) && file.fUseStampPar && (file.fOffset==0)) {
937 file.fUseStampPar =
false;
938 var xhr2 = JSROOT.NewHttpRequest(this.fURL, ((JSROOT.IO.Mode ==
"array") ?
"buf" :
"bin"), read_callback);
939 if (this.fAcceptRanges)
940 xhr2.setRequestHeader(
"Range",
"bytes=" + this.fOffset +
"-" + (this.fOffset + len - 1));
944 if ((res!=null) && (file.fOffset==0) && (file.fFileContent == null)) {
947 file.fFileContent = JSROOT.CreateTBuffer((typeof res ==
'string') ? res :
new DataView(res));
949 if (!this.fAcceptRanges)
950 file.fEND = file.fFileContent.totalLength();
952 return callback(file.fFileContent.extract(file.fOffset, len));
955 if ((res==null) || (res === undefined) || (typeof res ==
'string'))
956 return callback(res);
959 callback(
new DataView(res));
962 var xhr = JSROOT.NewHttpRequest(url, ((JSROOT.IO.Mode ==
"array") ?
"buf" :
"bin"), read_callback);
963 if (this.fAcceptRanges)
964 xhr.setRequestHeader(
"Range",
"bytes=" + this.fOffset +
"-" + (this.fOffset + len - 1));
968 JSROOT.TFile.prototype.Seek =
function(offset, pos) {
971 case this.ERelativeTo.kBeg:
972 this.fOffset = offset;
974 case this.ERelativeTo.kCur:
975 this.fOffset += offset;
977 case this.ERelativeTo.kEnd:
980 throw new Error(
"Seek : seeking from end in file with fEND==0 is not supported");
981 this.fOffset = this.fEND - offset;
984 throw new Error(
"Seek : unknown seek option (" + pos +
")");
989 JSROOT.TFile.prototype.ReadKey =
function(buf) {
996 JSROOT.TFile.prototype.GetDir =
function(dirname, cycle) {
999 if ((cycle==null) && (typeof dirname ==
'string')) {
1000 var pos = dirname.lastIndexOf(
';');
1001 if (pos>0) { cycle = dirname.substr(pos+1); dirname = dirname.substr(0,pos); }
1004 for (var j=0; j < this.fDirectories.length; ++j) {
1005 var dir = this.fDirectories[j];
1006 if (dir.dir_name != dirname)
continue;
1007 if ((cycle !== undefined) && (dir.dir_cycle !== cycle))
continue;
1013 JSROOT.TFile.prototype.GetKey =
function(keyname, cycle, getkey_callback) {
1017 for (var i=0; i < this.fKeys.length; ++i) {
1018 if (this.fKeys[i].fName === keyname && this.fKeys[i].fCycle === cycle) {
1019 JSROOT.CallBack(getkey_callback, this.fKeys[i]);
1020 return this.fKeys[i];
1024 var pos = keyname.lastIndexOf(
"/");
1027 var dirname = keyname.substr(0, pos);
1028 var subname = keyname.substr(pos+1);
1030 var dir = this.GetDir(dirname);
1031 if (dir!=null)
return dir.GetKey(subname, cycle, getkey_callback);
1033 var dirkey = this.GetKey(dirname, 1);
1034 if ((dirkey !== null) && (getkey_callback != null) &&
1035 (dirkey.fClassName.indexOf(
"TDirectory")==0)) {
1037 this.ReadObject(dirname,
function(newdir) {
1038 if (newdir) newdir.GetKey(subname, cycle, getkey_callback);
1043 pos = keyname.lastIndexOf(
"/", pos-1);
1046 JSROOT.CallBack(getkey_callback, null);
1050 JSROOT.TFile.prototype.ReadObjBuffer =
function(key, callback) {
1055 this.Seek(key.fSeekKey + key.fKeylen,
this.ERelativeTo.kBeg);
1057 this.ReadBuffer(key.fNbytes - key.fKeylen,
function(blob1) {
1059 if (blob1==null) callback(null);
1063 if (key.fObjlen <= key.fNbytes - key.fKeylen) {
1064 buf = JSROOT.CreateTBuffer(blob1, 0, file);
1066 var objbuf = JSROOT.R__unzip(blob1, key.fObjlen);
1067 if (objbuf==null)
return callback(null);
1068 buf = JSROOT.CreateTBuffer(objbuf, 0, file);
1071 buf.fTagOffset = key.fKeylen;
1077 JSROOT.TFile.prototype.ReadObject =
function(obj_name, cycle, user_call_back) {
1082 if (typeof cycle ==
'function') { user_call_back = cycle; cycle = 1; }
1084 var pos = obj_name.lastIndexOf(
";");
1086 cycle = parseInt(obj_name.slice(pos+1));
1087 obj_name = obj_name.slice(0, pos);
1090 if ((typeof cycle !=
'number') || (cycle<0)) cycle = 1;
1092 while ((obj_name.length>0) && (obj_name[0] ==
"/")) obj_name = obj_name.substr(1);
1099 this.GetKey(obj_name, cycle,
function(key) {
1102 return JSROOT.CallBack(user_call_back, null);
1104 if ((obj_name==
"StreamerInfo") && (key.fClassName==
"TList"))
1105 return file.fStreamerInfos;
1108 if ((key.fClassName ==
'TDirectory' || key.fClassName ==
'TDirectoryFile')) {
1110 var dir = file.GetDir(obj_name, cycle);
1112 return JSROOT.CallBack(user_call_back, dir);
1115 file.ReadObjBuffer(key,
function(buf) {
1116 if (!buf)
return JSROOT.CallBack(user_call_back, null);
1119 var dir =
new JSROOT.TDirectory(file, obj_name, cycle);
1120 dir.StreamHeader(buf);
1121 if (dir.fSeekKeys) {
1122 dir.ReadKeys(user_call_back);
1124 JSROOT.CallBack(user_call_back,dir);
1131 buf.MapObject(1, obj);
1132 buf.ClassStreamer(obj, key.fClassName);
1134 if (key.fClassName===
'TF1')
1135 return file.ReadFormulas(obj, user_call_back, -1);
1137 JSROOT.CallBack(user_call_back, obj);
1142 JSROOT.TFile.prototype.ReadFormulas =
function(tf1, user_call_back, cnt) {
1145 while (++indx < this.fKeys.length) {
1146 if (this.fKeys[indx].fClassName ==
'TFormula')
break;
1149 if (indx >= this.fKeys.length)
1150 return JSROOT.CallBack(user_call_back, tf1);
1154 this.ReadObject(this.fKeys[indx].fName, this.fKeys[indx].fCycle,
function(formula) {
1155 tf1.addFormula(formula);
1156 file.ReadFormulas(tf1, user_call_back, indx);
1160 JSROOT.TFile.prototype.ExtractStreamerInfos =
function(buf) {
1164 buf.MapObject(1, lst);
1165 buf.ClassStreamer(lst,
'TList');
1167 lst._typename =
"TStreamerInfoList";
1169 this.fStreamerInfos = lst;
1171 if (typeof JSROOT.addStreamerInfos ===
'function')
1172 JSROOT.addStreamerInfos(lst);
1176 JSROOT.TFile.prototype.ReadStreamerInfos =
function(si_callback) {
1177 if (this.fSeekInfo == 0 || this.fNbytesInfo == 0)
return si_callback(null);
1178 this.Seek(this.fSeekInfo, this.ERelativeTo.kBeg);
1182 file.ReadBuffer(file.fNbytesInfo,
function(blob1) {
1183 var buf = JSROOT.CreateTBuffer(blob1, 0, file);
1184 var key = file.ReadKey(buf);
1185 if (key == null)
return si_callback(null);
1186 file.fKeys.push(key);
1188 file.ReadObjBuffer(key,
function(blob2) {
1189 if (blob2==null)
return si_callback(null);
1190 file.ExtractStreamerInfos(blob2);
1196 JSROOT.TFile.prototype.ReadKeys =
function(readkeys_callback) {
1202 this.ReadBuffer(1024,
function(blob) {
1203 if (blob==null)
return JSROOT.CallBack(readkeys_callback, null);
1205 var buf = JSROOT.CreateTBuffer(blob, 0, file);
1207 if (buf.substring(0, 4) !==
'root') {
1208 alert(
"NOT A ROOT FILE! " + file.fURL);
1209 return JSROOT.CallBack(readkeys_callback, null);
1213 file.fVersion = buf.ntou4();
1214 file.fBEGIN = buf.ntou4();
1215 if (file.fVersion < 1000000) {
1216 file.fEND = buf.ntou4();
1217 file.fSeekFree = buf.ntou4();
1218 file.fNbytesFree = buf.ntou4();
1219 var nfree = buf.ntoi4();
1220 file.fNbytesName = buf.ntou4();
1221 file.fUnits = buf.ntou1();
1222 file.fCompress = buf.ntou4();
1223 file.fSeekInfo = buf.ntou4();
1224 file.fNbytesInfo = buf.ntou4();
1226 file.fEND = buf.ntou8();
1227 file.fSeekFree = buf.ntou8();
1228 file.fNbytesFree = buf.ntou4();
1229 var nfree = buf.ntou4();
1230 file.fNbytesName = buf.ntou4();
1231 file.fUnits = buf.ntou1();
1232 file.fCompress = buf.ntou4();
1233 file.fSeekInfo = buf.ntou8();
1234 file.fNbytesInfo = buf.ntou4();
1238 if (!file.fSeekInfo && !file.fNbytesInfo)
1239 return JSROOT.CallBack(readkeys_callback, null);
1242 var nbytes = file.fNbytesName + 22;
1247 if (file.fVersion >= 40000) nbytes += 12;
1249 file.Seek(file.fBEGIN, file.ERelativeTo.kBeg);
1251 file.ReadBuffer(Math.max(300, nbytes),
function(blob3) {
1252 if (blob3==null)
return JSROOT.CallBack(readkeys_callback, null);
1254 var buf3 = JSROOT.CreateTBuffer(blob3, file.fNbytesName, file);
1257 JSROOT.TDirectory.prototype.StreamHeader.call(file, buf3);
1261 var keyversion = buf3.ntoi2();
1263 if (keyversion > 1000) buf3.shift(28);
1264 else buf3.shift(20);
1267 file.fTitle = buf3.ReadTString();
1268 if (file.fNbytesName < 10 ||
this.fNbytesName > 10000) {
1269 JSROOT.console(
"Init : cannot read directory info of file " + file.fURL);
1270 return JSROOT.CallBack(readkeys_callback, null);
1274 if (file.fSeekKeys <= 0) {
1275 JSROOT.console(
"Empty keys list - not supported" + file.fURL);
1276 return JSROOT.CallBack(readkeys_callback, null);
1279 file.Seek(file.fSeekKeys, file.ERelativeTo.kBeg);
1280 file.ReadBuffer(file.fNbytesKeys,
function(blob4) {
1282 if (blob4==null)
return JSROOT.CallBack(readkeys_callback, null);
1284 var buf4 = JSROOT.CreateTBuffer(blob4, 0, file);
1285 var key = file.ReadKey(buf4);
1286 var nkeys = buf4.ntoi4();
1287 for (var i = 0; i < nkeys; ++i) {
1288 key = file.ReadKey(buf4);
1289 file.fKeys.push(key);
1291 file.ReadStreamerInfos(readkeys_callback);
1300 JSROOT.TFile.prototype.ReadDirectory =
function(dir_name, cycle, readdir_callback) {
1304 return this.ReadObject(dir_name, cycle, readdir_callback);
1307 JSROOT.TFile.prototype.AddMethods =
function(clname, streamer) {
1310 if (streamer === null)
return streamer;
1312 var methods = JSROOT.getMethods(clname);
1313 if (methods !== null)
1314 for (var key in methods)
1315 if ((typeof methods[key] ===
'function') || (key.indexOf(
"_")==0))
1318 method: methods[key],
1319 func:
function(buf,obj) { obj[this.name] = this.method; }
1325 JSROOT.TFile.prototype.GetStreamer =
function(clname) {
1329 var streamer = this.fStreamers[clname];
1330 if (streamer !== undefined)
return streamer;
1332 if (clname ==
'TQObject' || clname ==
"TBasket") {
1334 this.fStreamers[clname] = null;
1338 this.fStreamers[clname] = streamer =
new Array;
1340 if (clname ==
'TObject'|| clname ==
'TMethodCall') {
1341 streamer.push({ func:
function(buf,obj) {
1342 obj.fUniqueID = buf.ntou4();
1343 obj.fBits = buf.ntou4();
1345 return this.AddMethods(clname, streamer);
1348 if (clname ==
'TNamed') {
1349 streamer.push({ func :
function(buf,obj) {
1351 obj.fUniqueID = buf.ntou4();
1352 obj.fBits = buf.ntou4();
1353 obj.fName = buf.ReadTString();
1354 obj.fTitle = buf.ReadTString();
1356 return this.AddMethods(clname, streamer);
1359 if ((clname ==
'TList') || (clname ==
'THashList')) {
1360 streamer.push({ classname: clname,
1361 func :
function(buf, obj) {
1363 obj._typename = this.classname;
1365 obj.arr =
new Array;
1366 obj.opt =
new Array;
1367 if (buf.last_read_version > 3) {
1368 buf.ClassStreamer(obj,
"TObject");
1369 obj.name = buf.ReadTString();
1370 var nobjects = buf.ntou4();
1371 for (var i = 0; i < nobjects; ++i) {
1372 obj.arr.push(buf.ReadObjectAny());
1373 obj.opt.push(buf.ReadTString());
1377 return this.AddMethods(clname, streamer);
1380 if (clname ==
'TClonesArray') {
1381 streamer.push({ func :
function(buf, list) {
1382 list._typename =
"TClonesArray";
1384 list.arr =
new Array();
1385 var ver = buf.last_read_version;
1387 buf.buf.ClassStreamer(list,
"TObject");
1389 list.name = buf.ReadTString();
1390 var s = buf.ReadTString();
1393 var pos = s.indexOf(
";");
1395 classv = s.slice(0, pos);
1396 s = s.slice(pos+1, s.length-pos-1);
1400 var nobjects = buf.ntou4();
1401 if (nobjects < 0) nobjects = -nobjects;
1402 var lowerbound = buf.ntou4();
1411 return this.AddMethods(clname, streamer);
1414 if (clname ==
'TCanvas') {
1415 streamer.push({ func :
function(buf, obj) {
1417 obj._typename =
"TCanvas";
1419 buf.ClassStreamer(obj,
"TPad");
1421 obj.fDISPLAY = buf.ReadTString();
1422 obj.fDoubleBuffer = buf.ntoi4();
1423 obj.fRetained = (buf.ntou1() !== 0);
1424 obj.fXsizeUser = buf.ntoi4();
1425 obj.fYsizeUser = buf.ntoi4();
1426 obj.fXsizeReal = buf.ntoi4();
1427 obj.fYsizeReal = buf.ntoi4();
1428 obj.fWindowTopX = buf.ntoi4();
1429 obj.fWindowTopY = buf.ntoi4();
1430 obj.fWindowWidth = buf.ntoi4();
1431 obj.fWindowHeight = buf.ntoi4();
1432 obj.fCw = buf.ntou4();
1433 obj.fCh = buf.ntou4();
1435 obj.fCatt = buf.ClassStreamer({},
"TAttCanvas");
1439 obj.fHighLightColor = buf.ntoi2();
1440 obj.fBatch = (buf.ntou1() !== 0);
1445 return this.AddMethods(clname, streamer);
1448 if (clname ==
'TObjArray') {
1449 streamer.push({ func :
function(buf, list) {
1450 list._typename =
"TObjArray";
1452 list.arr =
new Array();
1453 var ver = buf.last_read_version;
1455 buf.ClassStreamer(list,
"TObject");
1457 list.name = buf.ReadTString();
1458 var nobjects = buf.ntou4();
1459 var lowerbound = buf.ntou4();
1460 for (var i = 0; i < nobjects; ++i)
1461 list.arr.push(buf.ReadObjectAny());
1463 return this.AddMethods(clname, streamer);
1466 if (clname ==
'TPolyMarker3D') {
1467 streamer.push({ func :
function(buf, marker) {
1468 var ver = buf.last_read_version;
1470 buf.ClassStreamer(marker,
"TObject");
1472 buf.ClassStreamer(marker,
"TAttMarker");
1474 marker.fN = buf.ntoi4();
1476 marker.fP = buf.ReadFastArray(marker.fN*3, JSROOT.IO.kFloat);
1478 marker.fOption = buf.ReadTString();
1481 marker.fName = buf.ReadTString();
1483 marker.fName =
"TPolyMarker3D";
1485 return this.AddMethods(clname, streamer);
1488 if (clname ==
"TStreamerInfo") {
1489 streamer.push({ func :
function(buf, streamerinfo) {
1491 if (buf.last_read_version > 1) {
1492 buf.ClassStreamer(streamerinfo,
"TNamed");
1494 streamerinfo.fCheckSum = buf.ntou4();
1495 streamerinfo.fClassVersion = buf.ntou4();
1496 streamerinfo.fElements = buf.ReadObjectAny();
1499 return this.AddMethods(clname, streamer);
1502 if (clname ==
"TStreamerElement") {
1503 streamer.push({ func :
function(buf, element) {
1506 var ver = buf.last_read_version;
1507 buf.ClassStreamer(element,
"TNamed");
1508 element.fType = buf.ntou4();
1509 element.fSize = buf.ntou4();
1510 element.fArrayLength = buf.ntou4();
1511 element.fArrayDim = buf.ntou4();
1512 element.fMaxIndex = buf.ReadFastArray((ver == 1) ? buf.ntou4() : 5, JSROOT.IO.kUInt);
1513 element.fTypeName = buf.ReadTString();
1515 if ((element.fType == JSROOT.IO.kUChar) && (element.fTypeName ==
"Bool_t" ||
1516 element.fTypeName ==
"bool"))
1517 element.fType = JSROOT.IO.kBool;
1526 element.fXmin = buf.ntod();
1527 element.fXmax = buf.ntod();
1528 element.fFactor = buf.ntod();
1533 return this.AddMethods(clname, streamer);
1536 if (clname ==
"TStreamerBase") {
1537 streamer.push({ func :
function(buf, elem) {
1540 var ver = buf.last_read_version;
1541 buf.ClassStreamer(elem,
"TStreamerElement");
1543 elem.fBaseVersion = buf.ntou4();
1546 return this.AddMethods(clname, streamer);
1549 if ((clname ==
"TStreamerBasicPointer") || (clname ==
"TStreamerLoop")) {
1550 streamer.push({ func :
function(buf,elem) {
1552 if (buf.last_read_version > 1) {
1553 buf.ClassStreamer(elem,
"TStreamerElement");
1554 elem.fCountVersion = buf.ntou4();
1555 elem.fCountName = buf.ReadTString();
1556 elem.fCountClass = buf.ReadTString();
1559 return this.AddMethods(clname, streamer);
1562 if (clname ==
"TStreamerSTL") {
1563 streamer.push({ func :
function(buf, elem) {
1564 if (buf.last_read_version > 1) {
1565 buf.ClassStreamer(elem,
"TStreamerElement");
1566 elem.fSTLtype = buf.ntou4();
1567 elem.fCtype = buf.ntou4();
1573 if (clname ==
"TStreamerObject" || clname ==
"TStreamerBasicType" ||
1574 clname ==
"TStreamerObjectAny" || clname ==
"TStreamerString" ||
1575 clname ==
"TStreamerObjectPointer") {
1576 streamer.push({ func:
function(buf, elem) {
1577 if (buf.last_read_version > 1)
1578 buf.ClassStreamer(elem,
"TStreamerElement");
1580 return this.AddMethods(clname, streamer);
1583 if (clname ==
"TStreamerObjectAnyPointer") {
1584 streamer.push({ func:
function(buf, elem) {
1585 if (buf.last_read_version > 0)
1586 buf.ClassStreamer(elem,
"TStreamerElement");
1588 return this.AddMethods(clname, streamer);
1592 if (this.fStreamerInfos)
1593 for (var i=0; i < this.fStreamerInfos.arr.length; ++i)
1594 if (this.fStreamerInfos.arr[i].fName == clname) {
1595 s_i = this.fStreamerInfos.arr[i];
break;
1598 delete this.fStreamers[clname];
1602 if (s_i.fElements === null)
1603 return this.AddMethods(clname, streamer);
1606 for (var j=0; j<s_i.fElements.arr.length; ++j) {
1608 var element = s_i.fElements.arr[j];
1610 var member = { name: element.fName, type: element.fType };
1612 if (element.fTypeName ===
'BASE') {
1613 if (JSROOT.IO.GetArrayKind(member.name) > 0) {
1616 member.name =
'fArray';
1617 member.type = JSROOT.IO.kAny;
1620 member.type = JSROOT.IO.kBase;
1621 this.GetStreamer(element.fName);
1625 switch (member.type) {
1626 case JSROOT.IO.kBase:
1627 member.func =
function(buf, obj) {
1628 buf.ClassStreamer(obj, this.name);
1631 case JSROOT.IO.kTString:
1632 member.func =
function(buf,obj) { obj[this.name] = buf.ReadTString(); };
break;
1633 case JSROOT.IO.kAnyP:
1634 case JSROOT.IO.kObjectP:
1635 member.func =
function(buf,obj) { obj[this.name] = buf.ReadObjectAny(); };
break;
1636 case JSROOT.IO.kOffsetL+JSROOT.IO.kInt:
1637 case JSROOT.IO.kOffsetL+JSROOT.IO.kDouble:
1638 case JSROOT.IO.kOffsetL+JSROOT.IO.kShort:
1639 case JSROOT.IO.kOffsetL+JSROOT.IO.kUShort:
1640 case JSROOT.IO.kOffsetL+JSROOT.IO.kUInt:
1641 case JSROOT.IO.kOffsetL+JSROOT.IO.kULong:
1642 case JSROOT.IO.kOffsetL+JSROOT.IO.kULong64:
1643 case JSROOT.IO.kOffsetL+JSROOT.IO.kLong:
1644 case JSROOT.IO.kOffsetL+JSROOT.IO.kLong64:
1645 case JSROOT.IO.kOffsetL+JSROOT.IO.kFloat:
1646 case JSROOT.IO.kOffsetL+JSROOT.IO.kDouble32:
1647 if (element.fArrayDim === 1) {
1648 member.arrlength = element.fArrayLength;
1649 member.func =
function(buf, obj) {
1650 obj[this.name] = buf.ReadFastArray(this.arrlength, this.type - JSROOT.IO.kOffsetL);
1653 if (element.fArrayDim === 2) {
1654 member.arrlength = element.fMaxIndex[1];
1655 member.maxindx = element.fMaxIndex[0];
1656 member.func =
function(buf, obj) {
1657 obj[this.name] = [];
1658 for (var n=0;n<this.maxindx;++n)
1659 obj[this.name].push(buf.ReadFastArray(
this.arrlength,
this.type - JSROOT.IO.kOffsetL));
1662 member.maxdim = element.fArrayDim - 1;
1663 member.maxindx = element.fMaxIndex;
1664 member.arrlength = element.fArrayLength;
1665 member.func =
function(buf, obj) {
1666 var tmp = buf.ReadFastArray(this.arrlength, this.type - JSROOT.IO.kOffsetL),
1667 indx = [], arr = [], i, k;
1668 for (i=0; i<=this.maxdim; ++i) { indx[i] = 0; arr[i] = []; }
1669 for (i=0;i<tmp.length;++i) {
1670 arr[this.maxdim].push(tmp[i]);
1671 ++indx[this.maxdim];
1673 while ((indx[k] === this.maxindx[k]) && (k>0)) {
1675 arr[k-1].push(arr[k]);
1680 obj[this.name] = arr[0];
1684 case JSROOT.IO.kOffsetP+JSROOT.IO.kInt:
1685 case JSROOT.IO.kOffsetP+JSROOT.IO.kDouble:
1686 case JSROOT.IO.kOffsetP+JSROOT.IO.kUChar:
1687 case JSROOT.IO.kOffsetP+JSROOT.IO.kChar:
1688 case JSROOT.IO.kOffsetP+JSROOT.IO.kShort:
1689 case JSROOT.IO.kOffsetP+JSROOT.IO.kUShort:
1690 case JSROOT.IO.kOffsetP+JSROOT.IO.kUInt:
1691 case JSROOT.IO.kOffsetP+JSROOT.IO.kULong:
1692 case JSROOT.IO.kOffsetP+JSROOT.IO.kULong64:
1693 case JSROOT.IO.kOffsetP+JSROOT.IO.kLong:
1694 case JSROOT.IO.kOffsetP+JSROOT.IO.kLong64:
1695 case JSROOT.IO.kOffsetP+JSROOT.IO.kFloat:
1696 case JSROOT.IO.kOffsetP+JSROOT.IO.kDouble32:
1697 member.cntname = element.fCountName;
1698 member.func =
function(buf, obj) {
1699 if (buf.ntou1() === 1)
1700 obj[this.name] = buf.ReadFastArray(obj[
this.cntname],
this.type - JSROOT.IO.kOffsetP);
1702 obj[this.name] =
new Array();
1705 case JSROOT.IO.kAny:
1706 case JSROOT.IO.kAnyp:
1707 case JSROOT.IO.kObjectp:
1708 case JSROOT.IO.kObject:
1709 var classname = (element.fTypeName ===
'BASE') ? element.fName : element.fTypeName;
1710 if (classname.charAt(classname.length-1) ==
"*")
1711 classname = classname.substr(0, classname.length - 1);
1713 var arrkind = JSROOT.IO.GetArrayKind(classname);
1716 member.arrkind = arrkind;
1717 member.func =
function(buf, obj) {
1718 obj[this.name] = buf.ReadFastArray(buf.ntou4(), this.arrkind);
1721 member.classname = classname;
1722 member.func =
function(buf, obj) {
1723 obj[this.name] = buf.ClassStreamer({}, this.classname);
1727 case JSROOT.IO.kOffsetL + JSROOT.IO.kObject:
1728 case JSROOT.IO.kOffsetL + JSROOT.IO.kAny:
1729 case JSROOT.IO.kOffsetL + JSROOT.IO.kAnyp:
1730 case JSROOT.IO.kOffsetL + JSROOT.IO.kObjectp:
1731 member.arrlength = element.fArrayLength;
1732 var classname = element.fTypeName;
1733 if (classname.charAt(classname.length-1) ==
"*")
1734 classname = classname.substr(0, classname.length - 1);
1736 var arrkind = JSROOT.IO.GetArrayKind(classname);
1739 member.arrkind = arrkind;
1740 member.func =
function(buf, obj) {
1741 obj[this.name] = [];
1742 for (var k=0;k<this.arrlength;++k)
1743 obj[this.name].push(buf.ReadFastArray(buf.ntou4(), this.arrkind));
1746 member.classname = classname;
1747 member.func =
function(buf, obj) {
1748 obj[this.name] = [];
1749 for (var k=0;k<this.arrlength;++k)
1750 obj[this.name].push(buf.ClassStreamer({}, this.classname));
1754 case JSROOT.IO.kChar:
1755 member.func =
function(buf,obj) { obj[this.name] = buf.ntoi1(); };
break;
1756 case JSROOT.IO.kShort:
1757 member.func =
function(buf,obj) { obj[this.name] = buf.ntoi2(); };
break;
1758 case JSROOT.IO.kInt:
1759 case JSROOT.IO.kCounter:
1760 member.func =
function(buf,obj) { obj[this.name] = buf.ntoi4(); };
break;
1761 case JSROOT.IO.kLong:
1762 case JSROOT.IO.kLong64:
1763 member.func =
function(buf,obj) { obj[this.name] = buf.ntoi8(); };
break;
1764 case JSROOT.IO.kDouble:
1765 member.func =
function(buf,obj) { obj[this.name] = buf.ntod(); };
break;
1766 case JSROOT.IO.kFloat:
1767 case JSROOT.IO.kDouble32:
1768 member.func =
function(buf,obj) { obj[this.name] = buf.ntof(); };
break;
1769 case JSROOT.IO.kLegacyChar:
1770 case JSROOT.IO.kUChar:
1771 member.func =
function(buf,obj) { obj[this.name] = buf.ntou1(); };
break;
1772 case JSROOT.IO.kUShort:
1773 member.func =
function(buf,obj) { obj[this.name] = buf.ntou2(); };
break;
1774 case JSROOT.IO.kUInt:
1775 member.func =
function(buf,obj) { obj[this.name] = buf.ntou4(); };
break;
1776 case JSROOT.IO.kULong64:
1777 case JSROOT.IO.kULong:
1778 member.func =
function(buf,obj) { obj[this.name] = buf.ntou8(); };
break;
1780 case JSROOT.IO.kBool:
1781 member.func =
function(buf,obj) { obj[this.name] = buf.ntou1() != 0; };
break;
1782 case JSROOT.IO.kStreamLoop:
1783 case JSROOT.IO.kStreamer:
1784 member.cntname = element.fCountName;
1785 member.typename = element.fTypeName;
1786 member.func =
function(buf,obj) {
1787 var ver = buf.ReadVersion();
1790 if (this.
typename ==
"TString*") {
1791 var cnt = obj[this.cntname];
1792 res =
new Array(cnt);
1793 for (var i = 0; i < cnt; ++i )
1794 res[i] = buf.ReadTString();
1796 if (this.
typename ==
"vector<double>") res = buf.ReadFastArray(buf.ntoi4(),JSROOT.IO.kDouble);
else
1797 if (this.
typename ==
"vector<int>") res = buf.ReadFastArray(buf.ntoi4(),JSROOT.IO.kInt);
else
1798 if (this.
typename ==
"vector<float>") res = buf.ReadFastArray(buf.ntoi4(),JSROOT.IO.kFloat);
else
1799 if (this.
typename ==
"vector<TObject*>") {
1800 var n = buf.ntoi4();
1802 for (var i=0;i<n;++i) res.push(buf.ReadObjectAny());
1804 if (this.
typename.indexOf(
"map<TString,int")==0) {
1805 var n = buf.ntoi4();
1807 for (var i=0;i<n;++i) {
1808 var str = buf.ReadTString();
1809 var val = buf.ntoi4();
1810 res.push({ first: str, second: val});
1813 JSROOT.console(
'failed to stream element of type ' + this.
typename);
1816 if (!buf.CheckBytecount(ver,
this.typename)) res = null;
1818 obj[this.name] = res;
1822 if (JSROOT.fUserStreamers !== null)
1823 member.func = JSROOT.fUserStreamers[element.fTypeName];
1825 if (typeof member.func !==
'function') {
1826 alert(
'failed to provide function for ' + element.fName +
' (' + element.fTypeName +
') typ = ' + element.fType);
1827 member.func =
function(buf,obj) {};
1831 streamer.push(member);
1834 return this.AddMethods(clname, streamer);
1837 JSROOT.TFile.prototype.Delete =
function() {
1838 if (this.fDirectories) this.fDirectories.splice(0, this.fDirectories.length);
1839 this.fDirectories = null;
1841 this.fStreamers = null;
1843 this.fNbytesInfo = 0;
1844 this.fTagOffset = 0;
1850 var iomode = JSROOT.GetUrlOption(
"iomode");
1851 if ((iomode==
"str") || (iomode==
"string")) JSROOT.IO.Mode =
"string";
else
1852 if ((iomode==
"bin") || (iomode==
"arr") || (iomode==
"array")) JSROOT.IO.Mode =
"array";
1853 JSROOT.IO.NativeArray = (
'Float64Array' in window);