This repository has been archived by the owner on Oct 13, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 36
/
Copy pathname.js
1353 lines (1216 loc) · 45.4 KB
/
name.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
91
92
93
94
95
96
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/**
* This class represents a Name as an array of components where each is a byte array.
* Copyright (C) 2013-2019 Regents of the University of California.
* @author: Meki Cheraoui, Jeff Thompson <jefft0@remap.ucla.edu>
*
* 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/>.
* A copy of the GNU Lesser General Public License is in the file COPYING.
*/
/** @ignore */
var Blob = require('./util/blob.js').Blob; /** @ignore */
var DataUtils = require('./encoding/data-utils.js').DataUtils; /** @ignore */
var LOG = require('./log.js').Log.LOG; /** @ignore */
var DecodingException = require('./encoding/decoding-exception.js').DecodingException;
/**
* Create a new Name from components.
*
* @constructor
* @param {string|Name|Array<string|Array<number>|ArrayBuffer|Buffer|Name>} components if a string, parse it as a URI. If a Name, add a deep copy of its components.
* Otherwise it is an array of components which are appended according to Name.append, so
* convert each and store it as an array of Buffer. If a component is a string, encode as utf8.
*/
var Name = function Name(components)
{
if (typeof components == 'string') {
if (LOG > 3) console.log('Content Name String ' + components);
this.components = Name.createNameArray(components);
}
else if (typeof components === 'object') {
this.components = [];
if (components instanceof Name)
this.append(components);
else {
for (var i = 0; i < components.length; ++i)
this.append(components[i]);
}
}
else if (components == null)
this.components = [];
else
if (LOG > 1) console.log("NO CONTENT NAME GIVEN");
this.changeCount = 0;
};
/**
* A ComponentType specifies the recognized types of a name component. If
* the component type in the packet is not a recognized enum value, then we
* use ComponentType.OTHER_CODE and you can call
* Name.Component.getOtherTypeCode(). We do this to keep the recognized
* component type values independent of packet encoding details.
*/
var ComponentType = {
IMPLICIT_SHA256_DIGEST: 1,
PARAMETERS_SHA256_DIGEST: 2,
GENERIC: 8,
OTHER_CODE: 0x7fff
};
exports.Name = Name;
exports.ComponentType = ComponentType;
/**
* Create a new Name.Component with a copy of the given value.
* (To create an ImplicitSha256Digest component, use fromImplicitSha256Digest.)
* (To create a ParametersSha256Digest component, use fromParametersSha256Digest.)
* @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer} value If the
* value is a string, encode it as utf8 (but don't unescape).
* @param (number) type (optional) The component type as an int from the
* ComponentType enum. If name component type is not a recognized ComponentType
* enum value, then set this to ComponentType.OTHER_CODE and use the
* otherTypeCode parameter. If omitted, use ComponentType.GENERIC.
* @param (number) otherTypeCode (optional) If type is ComponentType.OTHER_CODE,
* then this is the packet's unrecognized content type code, which must be
* non-negative.
* @constructor
*/
Name.Component = function NameComponent(value, type, otherTypeCode)
{
if (typeof value === 'object' && value instanceof Name.Component) {
// The copy constructor.
this.value_ = value.value_;
this.type_ = value.type_;
this.otherTypeCode_ = value.otherTypeCode_;
return;
}
if (!value)
this.value_ = new Blob([]);
else if (typeof value === 'object' && typeof ArrayBuffer !== 'undefined' &&
value instanceof ArrayBuffer)
// Make a copy. Turn the value into a Uint8Array since the Buffer
// constructor doesn't take an ArrayBuffer.
this.value_ = new Blob(new Buffer(new Uint8Array(value)), false);
else if (typeof value === 'object' && value instanceof Blob)
this.value_ = value;
else
// Blob will make a copy if needed.
this.value_ = new Blob(value);
if (type === ComponentType.OTHER_CODE) {
if (otherTypeCode == undefined)
throw new Error
("To use an other code, call Name.Component(value, ComponentType.OTHER_CODE, otherTypeCode)");
if (otherTypeCode < 0)
throw new Error("Name.Component other type code must be non-negative");
this.otherTypeCode_ = otherTypeCode;
}
else
this.otherTypeCode_ = -1;
this.type_ = (type == undefined ? ComponentType.GENERIC : type);
};
/**
* Get the component value.
* @return {Blob} The component value.
*/
Name.Component.prototype.getValue = function()
{
return this.value_;
};
/**
* @deprecated Use getValue. This method returns a Buffer which is the former
* behavior of getValue, and should only be used while updating your code.
*/
Name.Component.prototype.getValueAsBuffer = function()
{
// Assume the caller won't modify it.
return this.value_.buf();
};
/**
* Get the name component type.
* @return {number} The name component type as an int from the ComponentType
* enum. If this is ComponentType.OTHER_CODE, then call getOtherTypeCode() to
* get the unrecognized component type code.
*/
Name.Component.prototype.getType = function()
{
return this.type_;
};
/**
* Get the component type code from the packet which is other than a
* recognized ComponentType enum value. This is only meaningful if getType()
* is ComponentType.OTHER_CODE.
* @return (Number) The type code.
*/
Name.Component.prototype.getOtherTypeCode = function()
{
return this.otherTypeCode_;
};
/**
* @deprecated Use getValue which returns a Blob.
*/
Object.defineProperty(Name.Component.prototype, "value",
{ get: function() { return this.getValueAsBuffer(); } });
/**
* Convert this component value to a string by escaping characters according to the NDN URI Scheme.
* This also adds "..." to a value with zero or more ".".
* This adds a type code prefix as needed, such as "sha256digest=".
* @return {string} The escaped string.
*/
Name.Component.prototype.toEscapedString = function()
{
if (this.type_ === ComponentType.IMPLICIT_SHA256_DIGEST)
return "sha256digest=" + this.value_.toHex();
if (this.type_ === ComponentType.PARAMETERS_SHA256_DIGEST)
return "params-sha256=" + this.value_.toHex();
var typeString;
if (this.type_ === ComponentType.GENERIC)
typeString = "";
else
typeString = (this.type_ === ComponentType.OTHER_CODE ?
this.otherTypeCode_ : this.type_) + "=";
return typeString + Name.toEscapedString(this.value_.buf());
};
/**
* Check if this component is a segment number according to NDN naming
* conventions for "Segment number" (marker 0x00).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @return {number} True if this is a segment number.
*/
Name.Component.prototype.isSegment = function()
{
return this.value_.size() >= 1 && this.value_.buf()[0] == 0x00 &&
this.isGeneric();
};
/**
* Check if this component is a segment byte offset according to NDN
* naming conventions for segment "Byte offset" (marker 0xFB).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @return True if this is a segment byte offset.
*/
Name.Component.prototype.isSegmentOffset = function()
{
return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFB &&
this.isGeneric();
};
/**
* Check if this component is a version number according to NDN naming
* conventions for "Versioning" (marker 0xFD).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @return {number} True if this is a version number.
*/
Name.Component.prototype.isVersion = function()
{
return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFD &&
this.isGeneric();
};
/**
* Check if this component is a timestamp according to NDN naming
* conventions for "Timestamp" (marker 0xFC).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @return True if this is a timestamp.
*/
Name.Component.prototype.isTimestamp = function()
{
return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFC &&
this.isGeneric();
};
/**
* Check if this component is a sequence number according to NDN naming
* conventions for "Sequencing" (marker 0xFE).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @return True if this is a sequence number.
*/
Name.Component.prototype.isSequenceNumber = function()
{
return this.value_.size() >= 1 && this.value_.buf()[0] == 0xFE &&
this.isGeneric();
};
/**
* Check if this component is a generic component.
* @return {boolean} True if this is an generic component.
*/
Name.Component.prototype.isGeneric = function()
{
return this.type_ === ComponentType.GENERIC;
};
/**
* Check if this component is an ImplicitSha256Digest component.
* @return {boolean} True if this is an ImplicitSha256Digest component.
*/
Name.Component.prototype.isImplicitSha256Digest = function()
{
return this.type_ === ComponentType.IMPLICIT_SHA256_DIGEST;
};
/**
* Check if this component is a ParametersSha256Digest component.
* @return {boolean} True if this is a ParametersSha256Digest component.
*/
Name.Component.prototype.isParametersSha256Digest = function()
{
return this.type_ === ComponentType.PARAMETERS_SHA256_DIGEST;
};
/**
* Interpret this name component as a network-ordered number and return an integer.
* @return {number} The integer number.
*/
Name.Component.prototype.toNumber = function()
{
return DataUtils.bigEndianToUnsignedInt(this.value_.buf());
};
/**
* Interpret this name component as a network-ordered number with a marker and
* return an integer.
* @param {number} marker The required first byte of the component.
* @return {number} The integer number.
* @throws Error If the first byte of the component does not equal the marker.
*/
Name.Component.prototype.toNumberWithMarker = function(marker)
{
if (this.value_.size() == 0 || this.value_.buf()[0] != marker)
throw new Error("Name component does not begin with the expected marker");
return DataUtils.bigEndianToUnsignedInt(this.value_.buf().slice(1));
};
/**
* Interpret this name component as a segment number according to NDN naming
* conventions for "Segment number" (marker 0x00).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @return {number} The integer segment number.
* @throws Error If the first byte of the component is not the expected marker.
*/
Name.Component.prototype.toSegment = function()
{
return this.toNumberWithMarker(0x00);
};
/**
* Interpret this name component as a segment byte offset according to NDN
* naming conventions for segment "Byte offset" (marker 0xFB).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @return The integer segment byte offset.
* @throws Error If the first byte of the component is not the expected marker.
*/
Name.Component.prototype.toSegmentOffset = function()
{
return this.toNumberWithMarker(0xFB);
};
/**
* Interpret this name component as a version number according to NDN naming
* conventions for "Versioning" (marker 0xFD). Note that this returns
* the exact number from the component without converting it to a time
* representation.
* @return {number} The integer version number.
* @throws Error If the first byte of the component is not the expected marker.
*/
Name.Component.prototype.toVersion = function()
{
return this.toNumberWithMarker(0xFD);
};
/**
* Interpret this name component as a timestamp according to NDN naming
* conventions for "Timestamp" (marker 0xFC).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @return The number of microseconds since the UNIX epoch (Thursday,
* 1 January 1970) not counting leap seconds.
* @throws Error If the first byte of the component is not the expected marker.
*/
Name.Component.prototype.toTimestamp = function()
{
return this.toNumberWithMarker(0xFC);
};
/**
* Interpret this name component as a sequence number according to NDN naming
* conventions for "Sequencing" (marker 0xFE).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @return The integer sequence number.
* @throws Error If the first byte of the component is not the expected marker.
*/
Name.Component.prototype.toSequenceNumber = function()
{
return this.toNumberWithMarker(0xFE);
};
/**
* Create a component whose value is the nonNegativeInteger encoding of the
* number.
* @param {number} number The number to be encoded.
* @param (number) type (optional) The component type as an int from the
* ComponentType enum. If name component type is not a recognized ComponentType
* enum value, then set this to ComponentType.OTHER_CODE and use the
* otherTypeCode parameter. If omitted, use ComponentType.GENERIC.
* @param (number) otherTypeCode (optional) If type is ComponentType.OTHER_CODE,
* then this is the packet's unrecognized content type code, which must be
* non-negative.
* @return {Name.Component} The new component value.
*/
Name.Component.fromNumber = function(number, type, otherTypeCode)
{
var encoder = new TlvEncoder(8);
encoder.writeNonNegativeInteger(number);
return new Name.Component
(new Blob(encoder.getOutput(), false), type, otherTypeCode);
};
/**
* Create a component whose value is the marker appended with the
* nonNegativeInteger encoding of the number.
* @param {number} number
* @param {number} marker
* @return {Name.Component}
*/
Name.Component.fromNumberWithMarker = function(number, marker)
{
var encoder = new TlvEncoder(9);
// Encode backwards.
encoder.writeNonNegativeInteger(number);
encoder.writeNonNegativeInteger(marker);
return new Name.Component(new Blob(encoder.getOutput(), false));
};
/**
* Create a component with the encoded segment number according to NDN
* naming conventions for "Segment number" (marker 0x00).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* param {number} segment The segment number.
* returns {Name.Component} The new Component.
*/
Name.Component.fromSegment = function(segment)
{
return Name.Component.fromNumberWithMarker(segment, 0x00);
};
/**
* Create a component with the encoded segment byte offset according to NDN
* naming conventions for segment "Byte offset" (marker 0xFB).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* param {number} segmentOffset The segment byte offset.
* returns {Name.Component} The new Component.
*/
Name.Component.fromSegmentOffset = function(segmentOffset)
{
return Name.Component.fromNumberWithMarker(segmentOffset, 0xFB);
};
/**
* Create a component with the encoded version number according to NDN
* naming conventions for "Versioning" (marker 0xFD).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* Note that this encodes the exact value of version without converting from a
* time representation.
* param {number} version The version number.
* returns {Name.Component} The new Component.
*/
Name.Component.fromVersion = function(version)
{
return Name.Component.fromNumberWithMarker(version, 0xFD);
};
/**
* Create a component with the encoded timestamp according to NDN naming
* conventions for "Timestamp" (marker 0xFC).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* param {number} timestamp The number of microseconds since the UNIX epoch (Thursday,
* 1 January 1970) not counting leap seconds.
* returns {Name.Component} The new Component.
*/
Name.Component.fromTimestamp = function(timestamp)
{
return Name.Component.fromNumberWithMarker(timestamp, 0xFC);
};
/**
* Create a component with the encoded sequence number according to NDN naming
* conventions for "Sequencing" (marker 0xFE).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* param {number} sequenceNumber The sequence number.
* returns {Name.Component} The new Component.
*/
Name.Component.fromSequenceNumber = function(sequenceNumber)
{
return Name.Component.fromNumberWithMarker(sequenceNumber, 0xFE);
};
/**
* Create a component of type ImplicitSha256DigestComponent, so that
* isImplicitSha256Digest() is true.
* @param {Blob|Buffer} digest The SHA-256 digest value.
* @return {Name.Component} The new Component.
* @throws DecodingException If the digest length is not 32 bytes.
*/
Name.Component.fromImplicitSha256Digest = function(digest)
{
digestBlob = typeof digest === 'object' && digest instanceof Blob ?
digest : new Blob(digest, true);
if (digestBlob.size() !== 32)
throw new DecodingException
("Name.Component.fromImplicitSha256Digest: The digest length must be 32 bytes");
var result = new Name.Component(digestBlob);
result.type_ = ComponentType.IMPLICIT_SHA256_DIGEST;
return result;
};
/**
* Create a component of type ParametersSha256DigestComponent, so that
* isParametersSha256Digest() is true.
* @param {Blob|Buffer} digest The SHA-256 digest value.
* @return {Name.Component} The new Component.
* @throws DecodingException If the digest length is not 32 bytes.
*/
Name.Component.fromParametersSha256Digest = function(digest)
{
digestBlob = typeof digest === 'object' && digest instanceof Blob ?
digest : new Blob(digest, true);
if (digestBlob.size() !== 32)
throw new DecodingException
("Name.Component.fromParametersSha256Digest: The digest length must be 32 bytes");
var result = new Name.Component(digestBlob);
result.type_ = ComponentType.PARAMETERS_SHA256_DIGEST;
return result;
};
/**
* Get the successor of this component, as described in Name.getSuccessor.
* @return {Name.Component} A new Name.Component which is the successor of this.
*/
Name.Component.prototype.getSuccessor = function()
{
// Allocate an extra byte in case the result is larger.
var result = new Buffer(this.value_.size() + 1);
var carry = true;
for (var i = this.value_.size() - 1; i >= 0; --i) {
if (carry) {
result[i] = (this.value_.buf()[i] + 1) & 0xff;
carry = (result[i] === 0);
}
else
result[i] = this.value_.buf()[i];
}
if (carry)
// Assume all the bytes were set to zero (or the component was empty). In
// NDN ordering, carry does not mean to prepend a 1, but to make a component
// one byte longer of all zeros.
result[result.length - 1] = 0;
else
// We didn't need the extra byte.
result = result.slice(0, this.value_.size());
return new Name.Component
(new Blob(result, false), this.type_, this.otherTypeCode_);
};
/**
* Check if this is the same component as other.
* @param {Name.Component} other The other Component to compare with.
* @return {Boolean} true if the components are equal, otherwise false.
*/
Name.Component.prototype.equals = function(other)
{
if (!(typeof other === 'object' && other instanceof Name.Component))
return false;
if (this.type_ === ComponentType.OTHER_CODE)
return this.value_.equals(other.value_) &&
other.type_ === ComponentType.OTHER_CODE &&
this.otherTypeCode_ == other.otherTypeCode_;
else
return this.value_.equals(other.value_) && this.type_ === other.type_;
};
/**
* Compare this to the other Component using NDN canonical ordering.
* @param {Name.Component} other The other Component to compare with.
* @return {number} 0 if they compare equal, -1 if this comes before other in
* the canonical ordering, or 1 if this comes after other in the canonical
* ordering.
*
* @see http://named-data.net/doc/0.2/technical/CanonicalOrder.html
*/
Name.Component.prototype.compare = function(other)
{
var myTypeCode = (this.type_ === ComponentType.OTHER_CODE ?
this.otherTypeCode_ : this.type_);
var otherTypeCode = (other.type_ === ComponentType.OTHER_CODE ?
other.otherTypeCode_ : other.type_);
if (myTypeCode < otherTypeCode)
return -1;
if (myTypeCode > otherTypeCode)
return 1;
return Name.Component.compareBuffers(this.value_.buf(), other.value_.buf());
};
/**
* Do the work of Name.Component.compare to compare the component buffers.
* @param {Buffer} component1
* @param {Buffer} component2
* @return {number} 0 if they compare equal, -1 if component1 comes before
* component2 in the canonical ordering, or 1 if component1 comes after
* component2 in the canonical ordering.
*/
Name.Component.compareBuffers = function(component1, component2)
{
if (component1.length < component2.length)
return -1;
if (component1.length > component2.length)
return 1;
for (var i = 0; i < component1.length; ++i) {
if (component1[i] < component2[i])
return -1;
if (component1[i] > component2[i])
return 1;
}
return 0;
};
/**
* @deprecated Use toUri.
*/
Name.prototype.getName = function()
{
return this.toUri();
};
/** Parse uri as a URI and return an array of Buffer components.
*/
Name.createNameArray = function(uri)
{
uri = uri.trim();
if (uri.length <= 0)
return [];
var iColon = uri.indexOf(':');
if (iColon >= 0) {
// Make sure the colon came before a '/'.
var iFirstSlash = uri.indexOf('/');
if (iFirstSlash < 0 || iColon < iFirstSlash)
// Omit the leading protocol such as ndn:
uri = uri.substr(iColon + 1, uri.length - iColon - 1).trim();
}
if (uri[0] == '/') {
if (uri.length >= 2 && uri[1] == '/') {
// Strip the authority following "//".
var iAfterAuthority = uri.indexOf('/', 2);
if (iAfterAuthority < 0)
// Unusual case: there was only an authority.
return [];
else
uri = uri.substr(iAfterAuthority + 1, uri.length - iAfterAuthority - 1).trim();
}
else
uri = uri.substr(1, uri.length - 1).trim();
}
var array = uri.split('/');
// Unescape the components.
var sha256digestPrefix = "sha256digest=";
var paramsSha256Prefix = "params-sha256=";
for (var i = 0; i < array.length; ++i) {
var componentString = array[i];
var component;
if (componentString.substr(0, sha256digestPrefix.length) == sha256digestPrefix) {
var hexString = componentString.substr(sha256digestPrefix.length).trim();
component = Name.Component.fromImplicitSha256Digest
(new Blob(new Buffer(hexString, 'hex')), false);
}
else if (componentString.substr(0, paramsSha256Prefix.length) == paramsSha256Prefix) {
var hexString = componentString.substr(paramsSha256Prefix.length).trim();
component = Name.Component.fromParametersSha256Digest
(new Blob(new Buffer(hexString, 'hex')), false);
}
else {
var type = ComponentType.GENERIC;
var otherTypeCode = -1;
// Check for a component type.
var iTypeCodeEnd = componentString.indexOf("=");
if (iTypeCodeEnd >= 0) {
var typeString = componentString.substring(0, iTypeCodeEnd);
otherTypeCode = parseInt(typeString);
if (isNaN(otherTypeCode))
throw new Error
("Can't parse decimal Name Component type: " + typeString +
" in URI " + uri);
// Allow for a decimal value of recognized component types.
if (otherTypeCode == ComponentType.GENERIC ||
otherTypeCode == ComponentType.IMPLICIT_SHA256_DIGEST ||
otherTypeCode == ComponentType.PARAMETERS_SHA256_DIGEST)
// The enum values are the same as the TLV type codes.
type = otherTypeCode;
else
type = ComponentType.OTHER_CODE;
componentString = componentString.substring(iTypeCodeEnd + 1);
}
component = new Name.Component
(Name.fromEscapedString(componentString), type, otherTypeCode);
}
if (component.getValue().isNull()) {
// Ignore the illegal componenent. This also gets rid of a trailing '/'.
array.splice(i, 1);
--i;
continue;
}
else
array[i] = component;
}
return array;
};
/**
* Parse the uri according to the NDN URI Scheme and set the name with the
* components.
* @param {string} uri The URI string.
*/
Name.prototype.set = function(uri)
{
this.components = Name.createNameArray(uri);
++this.changeCount;
};
/**
* Convert the component to a Buffer and append a component to this Name.
* (To append an ImplicitSha256Digest component, use appendImplicitSha256Digest.)
* (To append a ParametersSha256Digest component, use appendParametersSha256Digest.)
* @param {Name.Component|String|Array<number>|ArrayBuffer|Buffer|Name} component
* If a component is a string, encode as utf8 (but don't unescape).
* @param (number) type (optional) The component type as an int from the
* ComponentType enum. If name component type is not a recognized ComponentType
* enum value, then set this to ComponentType.OTHER_CODE and use the
* otherTypeCode parameter. If omitted, use ComponentType.GENERIC. If the
* component param is a Name or another Name.Component, then this is ignored.
* @param (number) otherTypeCode (optional) If type is ComponentType.OTHER_CODE,
* then this is the packet's unrecognized content type code, which must be
* non-negative. If the component param is a Name or another Name.Component,
* then this is ignored.
* @return {Name} This name so that you can chain calls to append.
*/
Name.prototype.append = function(component, type, otherTypeCode)
{
if (typeof component == 'object' && component instanceof Name) {
var components;
if (component == this)
// special case, when we need to create a copy
components = this.components.slice(0, this.components.length);
else
components = component.components;
for (var i = 0; i < components.length; ++i)
this.components.push(new Name.Component(components[i]));
}
else if (typeof component === 'object' && component instanceof Name.Component)
// The Component is immutable, so use it as is.
this.components.push(component);
else
// Just use the Name.Component constructor.
this.components.push(new Name.Component(component, type, otherTypeCode));
++this.changeCount;
return this;
};
/**
* @deprecated Use append.
*/
Name.prototype.add = function(component)
{
return this.append(component);
};
/**
* Clear all the components.
*/
Name.prototype.clear = function()
{
this.components = [];
++this.changeCount;
};
/**
* Return the escaped name string according to NDN URI Scheme.
* @param {boolean} includeScheme (optional) If true, include the "ndn:" scheme
* in the URI, e.g. "ndn:/example/name". If false, just return the path, e.g.
* "/example/name". If ommitted, then just return the path which is the default
* case where toUri() is used for display.
* @return {String}
*/
Name.prototype.toUri = function(includeScheme)
{
if (this.size() == 0)
return includeScheme ? "ndn:/" : "/";
var result = includeScheme ? "ndn:" : "";
for (var i = 0; i < this.size(); ++i)
result += "/"+ this.components[i].toEscapedString();
return result;
};
/**
* @deprecated Use toUri.
*/
Name.prototype.to_uri = function()
{
return this.toUri();
};
Name.prototype.toString = function() { return this.toUri(); }
/**
* Append a component with the encoded segment number according to NDN
* naming conventions for "Segment number" (marker 0x00).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @param {number} segment The segment number.
* @return {Name} This name so that you can chain calls to append.
*/
Name.prototype.appendSegment = function(segment)
{
return this.append(Name.Component.fromSegment(segment));
};
/**
* Append a component with the encoded segment byte offset according to NDN
* naming conventions for segment "Byte offset" (marker 0xFB).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @param {number} segmentOffset The segment byte offset.
* @return {Name} This name so that you can chain calls to append.
*/
Name.prototype.appendSegmentOffset = function(segmentOffset)
{
return this.append(Name.Component.fromSegmentOffset(segmentOffset));
};
/**
* Append a component with the encoded version number according to NDN
* naming conventions for "Versioning" (marker 0xFD).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* Note that this encodes the exact value of version without converting from a time representation.
* @param {number} version The version number.
* @return {Name} This name so that you can chain calls to append.
*/
Name.prototype.appendVersion = function(version)
{
return this.append(Name.Component.fromVersion(version));
};
/**
* Append a component with the encoded timestamp according to NDN naming
* conventions for "Timestamp" (marker 0xFC).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @param {number} timestamp The number of microseconds since the UNIX epoch (Thursday,
* 1 January 1970) not counting leap seconds.
* @return This name so that you can chain calls to append.
*/
Name.prototype.appendTimestamp = function(timestamp)
{
return this.append(Name.Component.fromTimestamp(timestamp));
};
/**
* Append a component with the encoded sequence number according to NDN naming
* conventions for "Sequencing" (marker 0xFE).
* http://named-data.net/doc/tech-memos/naming-conventions.pdf
* @param {number} sequenceNumber The sequence number.
* @return This name so that you can chain calls to append.
*/
Name.prototype.appendSequenceNumber = function(sequenceNumber)
{
return this.append(Name.Component.fromSequenceNumber(sequenceNumber));
};
/**
* Append a component of type ImplicitSha256DigestComponent, so that
* isImplicitSha256Digest() is true.
* @param {Blob|Buffer} digest The SHA-256 digest value.
* @return This name so that you can chain calls to append.
* @throws DecodingException If the digest length is not 32 bytes.
*/
Name.prototype.appendImplicitSha256Digest = function(digest)
{
return this.append(Name.Component.fromImplicitSha256Digest(digest));
};
/**
* Append a component of type ParametersSha256DigestComponent, so that
* isParametersSha256Digest() is true.
* @param {Blob|Buffer} digest The SHA-256 digest value.
* @return This name so that you can chain calls to append.
* @throws DecodingException If the digest length is not 32 bytes.
*/
Name.prototype.appendParametersSha256Digest = function(digest)
{
return this.append(Name.Component.fromParametersSha256Digest(digest));
};
/**
* @deprecated Use appendSegment.
*/
Name.prototype.addSegment = function(number)
{
return this.appendSegment(number);
};
/**
* Get a new name, constructed as a subset of components.
* @param {number} iStartComponent The index if the first component to get. If
* iStartComponent is -N then return return components starting from
* name.size() - N.
* @param {number} (optional) nComponents The number of components starting at
* iStartComponent. If omitted or greater than the size of this name, get until
* the end of the name.
* @return {Name} A new name.
*/
Name.prototype.getSubName = function(iStartComponent, nComponents)
{
if (iStartComponent < 0)
iStartComponent = this.components.length - (-iStartComponent);
if (nComponents == undefined)
nComponents = this.components.length - iStartComponent;
var result = new Name();
var iEnd = iStartComponent + nComponents;
for (var i = iStartComponent; i < iEnd && i < this.components.length; ++i)
result.components.push(this.components[i]);
return result;
};
/**
* Return a new Name with the first nComponents components of this Name.
* @param {number} nComponents The number of prefix components. If nComponents is -N then return the prefix up
* to name.size() - N. For example getPrefix(-1) returns the name without the final component.
* @return {Name} A new name.
*/
Name.prototype.getPrefix = function(nComponents)
{
if (nComponents < 0)
return this.getSubName(0, this.components.length + nComponents);
else
return this.getSubName(0, nComponents);
};
/**
* @deprecated Use getPrefix(-nComponents).
*/
Name.prototype.cut = function(nComponents)
{
return new Name(this.components.slice(0, this.components.length - nComponents));
};
/**
* Return the number of name components.
* @return {number}
*/
Name.prototype.size = function()
{
return this.components.length;
};
/**
* Get a Name Component by index number.
* @param {Number} i The index of the component, starting from 0. However, if i is negative, return the component
* at size() - (-i).
* @return {Name.Component} The name component at the index. You must not
* change the returned Name.Component object.
*/
Name.prototype.get = function(i)
{
if (i >= 0) {
if (i >= this.components.length)
throw new Error("Name.get: Index is out of bounds");
return this.components[i];
}
else {
// Negative index.
if (i < -this.components.length)
throw new Error("Name.get: Index is out of bounds");
return this.components[this.components.length - (-i)];
}
};
/**
* @deprecated Use size().
*/
Name.prototype.getComponentCount = function()
{
return this.components.length;
};
/**
* @deprecated To get just the component value array, use get(i).getValue().buf().
*/
Name.prototype.getComponent = function(i)
{
return new Buffer(this.components[i].getValue().buf());
};