1 22 package org.xsocket; 23 24 import java.nio.BufferUnderflowException ; 25 import java.nio.ByteBuffer ; 26 import java.util.LinkedList ; 27 28 29 30 36 public final class ByteBufferQueue { 37 38 39 private static final Integer UNKNOWN = null; 40 41 private LinkedList <ByteBuffer > buffers = null; 42 private Integer currentSize = UNKNOWN; 43 private int insertVersion = 0; 44 45 46 47 48 53 public synchronized boolean isEmpty() { 54 55 if (buffers == null) { 56 return true; 57 58 } else { 59 return buffers.isEmpty(); 60 } 61 } 62 63 64 69 public synchronized int getSize() { 70 71 if (currentSize != UNKNOWN) { 73 return currentSize; 74 } 75 76 77 if (isEmpty()) { 78 return 0; 79 80 } else { 81 int size = 0; 82 for (ByteBuffer buffer : buffers) { 83 size += buffer.remaining(); 84 } 85 86 currentSize = size; 87 return size; 88 } 89 } 90 91 92 93 94 95 100 public synchronized int getFirstBufferSize() { 101 if (buffers == null) { 102 return 0; 103 } 104 105 if (buffers.isEmpty()) { 106 buffers = null; 107 return 0; 108 } 109 110 ByteBuffer buffer = buffers.getFirst(); 111 return buffer.remaining(); 112 } 113 114 115 116 121 public synchronized void append(ByteBuffer data) { 122 123 if (data != null) { 125 126 if (data.hasRemaining()) { 128 currentSize = UNKNOWN; 130 insertVersion++; 131 132 if (buffers == null) { 133 buffers= new LinkedList <ByteBuffer >(); 134 } 135 136 buffers.add(data); 137 } 138 } 139 } 140 141 142 149 public synchronized void append(LinkedList <ByteBuffer > bufs) { 150 151 if (bufs != null) { 153 154 if (bufs.size() > 0) { 156 157 currentSize = UNKNOWN; 159 insertVersion++; 160 161 if (buffers == null) { 162 buffers = bufs; 163 164 } else { 165 buffers.addAll(bufs); 166 } 167 } 168 } 169 } 170 171 172 177 public synchronized void addFirst(ByteBuffer buffer) { 178 179 if (buffer != null) { 181 182 if (buffer.hasRemaining()) { 184 185 currentSize = UNKNOWN; 187 insertVersion++; 188 189 if (buffers == null) { 190 buffers= new LinkedList <ByteBuffer >(); 191 } 192 193 buffers.addFirst(buffer); 194 } 195 } 196 } 197 198 199 200 201 209 public synchronized void addFirst(LinkedList <ByteBuffer > bufs) { 210 211 if (bufs != null) { 213 214 if (bufs.size() > 0) { 216 217 currentSize = UNKNOWN; 219 insertVersion++; 220 221 if (buffers == null) { 222 buffers = bufs; 223 224 } else { 225 bufs.addAll(buffers); 226 buffers = bufs; 227 } 228 } 229 } 230 } 231 232 233 234 244 public synchronized void addFirstSilence(LinkedList <ByteBuffer > bufs) { 245 246 if (bufs != null) { 248 249 if (bufs.size() > 0) { 251 252 currentSize = UNKNOWN; 254 255 if (buffers == null) { 256 buffers = bufs; 257 258 } else { 259 bufs.addAll(buffers); 260 buffers = bufs; 261 } 262 } 263 } 264 } 265 266 267 272 public synchronized LinkedList <ByteBuffer > drain() { 273 274 if (buffers != null) { 276 277 if (!buffers.isEmpty()) { 279 280 currentSize = UNKNOWN; 282 283 LinkedList <ByteBuffer > result = buffers; 284 buffers = null; 285 286 return result; 287 288 } else { 289 buffers = null; 291 } 292 } 293 294 return new LinkedList <ByteBuffer >(); 296 } 297 298 299 300 301 305 public synchronized ByteBuffer removeFirst() { 306 307 if (buffers == null) { 309 return null; 310 311 } else { 312 313 if (buffers.isEmpty()) { 315 buffers = null; 316 return null; 317 318 } else { 319 currentSize = UNKNOWN; 321 return buffers.removeFirst(); 322 } 323 } 324 } 325 326 327 328 334 public int getInsertVersionVersion() { 335 return insertVersion; 336 } 337 338 345 public synchronized ByteBuffer read(int length) throws BufferUnderflowException { 346 347 if (buffers == null) { 349 throw new BufferUnderflowException (); 350 } 351 352 if (!isSizeEqualsOrLargerThan(length)) { 354 throw new BufferUnderflowException (); 355 } 356 357 358 currentSize = UNKNOWN; 360 ByteBuffer buffer = buffers.removeFirst(); 361 int remainingFirst = buffer.remaining(); 362 363 364 if (remainingFirst == length) { 366 return buffer; 367 368 369 } else if(remainingFirst > length) { 371 int savedLimit = buffer.limit(); 372 int savedPos = buffer.position(); 373 374 buffer.limit(buffer.position() + length); 375 376 ByteBuffer resultBuf = buffer.slice(); 377 378 buffer.position(savedPos + length); 379 buffer.limit(savedLimit); 380 addFirst(buffer.slice()); 381 382 return resultBuf; 383 384 385 } else { 387 388 ByteBuffer result = ByteBuffer.allocate(length); 389 int written = 0; 390 391 while (true) { 392 while(buffer.hasRemaining()) { 394 result.put(buffer.get()); 395 written++; 396 if (written == length) { 397 if (buffer.position() < buffer.limit()) { 398 buffers.addFirst(buffer.slice()); 399 } 400 result.clear(); 401 return result; 402 } 403 } 404 405 buffer = buffers.poll(); 406 } 407 } 408 } 409 410 411 412 private boolean isSizeEqualsOrLargerThan(int size) { 413 if (buffers == null) { 414 return false; 415 } 416 417 int l = 0; 418 419 for (ByteBuffer buffer : buffers) { 420 l += buffer.remaining(); 421 if (l >= size) { 422 return true; 423 } 424 } 425 426 return false; 427 } 428 429 430 431 434 @Override 435 public String toString() { 436 StringBuilder sb = new StringBuilder (); 437 if (buffers != null) { 438 ByteBuffer [] copy = new ByteBuffer [buffers.size()]; 439 try { 440 for (int i = 0; i < copy.length; i++) { 441 copy[i] = buffers.get(i).duplicate(); 442 } 443 sb.append(DataConverter.toString(copy, "US-ASCII", Integer.MAX_VALUE)); 444 } catch (Exception ignore) { 445 sb.append(DataConverter.toHexString(copy, Integer.MAX_VALUE)); 446 } 447 } 448 449 return sb.toString(); 450 } 451 } 452 | Popular Tags |