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 package org.apache.hc.core5.http2.hpack;
29
30 import org.apache.hc.core5.http.Header;
31 import org.apache.hc.core5.util.Args;
32
33 final class FifoLinkedList {
34
35 private final InternalNode master;
36 private int length;
37
38 FifoLinkedList() {
39 this.master = new InternalNode(null);
40 this.master.previous = this.master;
41 this.master.next = this.master;
42 }
43
44 public Header get(final int index) {
45 Args.check(index <= length, "Length %s cannot be greater then index %s ", length, index);
46 Args.notNegative(index, "index");
47 InternalNode current = master.next;
48 int n = 0;
49 while (current != master) {
50 if (index == n) {
51 return current.header;
52 }
53 current = current.next;
54 n++;
55 }
56 return null;
57 }
58
59 public int getIndex(final InternalNode node) {
60 final int seqNum = node.seqNum;
61 if (seqNum < 1) {
62 return -1;
63 }
64 return length - (seqNum - master.previous.seqNum) - 1;
65 }
66
67 public Header getFirst() {
68 return master.next.header;
69 }
70
71 public Header getLast() {
72 return master.previous.header;
73 }
74
75 public int size() {
76 return length;
77 }
78
79 public InternalNode addFirst(final HPackHeader header) {
80
81 final InternalNode newNode = new InternalNode(header);
82 final InternalNode oldNode = master.next;
83 master.next = newNode;
84 newNode.previous = master;
85 newNode.next = oldNode;
86 oldNode.previous = newNode;
87 newNode.seqNum = oldNode.seqNum + 1;
88 length++;
89 return newNode;
90 }
91
92 public InternalNode removeLast() {
93
94 final InternalNode last = master.previous;
95 if (last.header != null) {
96 final InternalNode lastButOne = last.previous;
97 master.previous = lastButOne;
98 lastButOne.next = master;
99 last.previous = null;
100 last.next = null;
101 last.seqNum = 0;
102 length--;
103 return last;
104 }
105 master.seqNum = 0;
106 return null;
107 }
108
109 public void clear() {
110
111 master.previous = master;
112 master.next = master;
113 master.seqNum = 0;
114 length = 0;
115 }
116
117 class InternalNode implements HPackEntry {
118
119 private final HPackHeader header;
120 private InternalNode previous;
121 private InternalNode next;
122 private int seqNum;
123
124 InternalNode(final HPackHeader header) {
125 this.header = header;
126 }
127
128 @Override
129 public HPackHeader getHeader() {
130 return header;
131 }
132
133 @Override
134 public int getIndex() {
135 return StaticTable.INSTANCE.length() + FifoLinkedList.this.getIndex(this) + 1;
136 }
137
138 @Override
139 public String toString() {
140 return "[" +
141 (header != null ? header.toString() : "master") +
142 "; seqNum=" + seqNum +
143 "; previous=" + (previous != null ? previous.header : null) +
144 "; next=" + (next != null ? next.header : null) +
145 ']';
146 }
147
148 }
149
150 }