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