Commit b54d2f75d611f67ef449fc6ce292e01e96ca08a0
Merge pull request #334 from biometrics/bytearray_serialization
Explicit bytearray serialization
Showing
2 changed files
with
79 additions
and
28 deletions
openbr/core/qtutils.cpp
| ... | ... | @@ -500,14 +500,15 @@ QString getAbsolutePath(const QString &filename) |
| 500 | 500 | return QFileInfo(filename).absoluteFilePath(); |
| 501 | 501 | } |
| 502 | 502 | |
| 503 | +const int base_block = 100000000; | |
| 504 | + | |
| 503 | 505 | BlockCompression::BlockCompression(QIODevice *_basis) |
| 504 | 506 | { |
| 505 | - blockSize = 100000000; | |
| 507 | + blockSize = base_block; | |
| 506 | 508 | setBasis(_basis); |
| 507 | 509 | } |
| 508 | 510 | |
| 509 | -BlockCompression::BlockCompression() { blockSize = 100000000; }; | |
| 510 | - | |
| 511 | +BlockCompression::BlockCompression() { blockSize = base_block;}; | |
| 511 | 512 | |
| 512 | 513 | bool BlockCompression::open(QIODevice::OpenMode mode) |
| 513 | 514 | { |
| ... | ... | @@ -521,14 +522,22 @@ bool BlockCompression::open(QIODevice::OpenMode mode) |
| 521 | 522 | blockWriter.setDevice(basis); |
| 522 | 523 | |
| 523 | 524 | if (mode & QIODevice::WriteOnly) { |
| 524 | - precompressedBlockWriter = new QBuffer; | |
| 525 | - precompressedBlockWriter->open(QIODevice::ReadWrite); | |
| 525 | + precompressedBlockWriter.open(QIODevice::WriteOnly); | |
| 526 | 526 | } |
| 527 | 527 | else if (mode & QIODevice::ReadOnly) { |
| 528 | + | |
| 529 | + // Read an initial compressed block from the underlying QIODevice, | |
| 530 | + // decompress, and set up a reader on it | |
| 528 | 531 | QByteArray compressedBlock; |
| 529 | - blockReader >> compressedBlock; | |
| 532 | + quint32 block_size; | |
| 533 | + blockReader >> block_size; | |
| 534 | + compressedBlock.resize(block_size); | |
| 535 | + int read_count = blockReader.readRawData(compressedBlock.data(), block_size); | |
| 536 | + if (read_count != block_size) | |
| 537 | + qFatal("Failed to read initial block"); | |
| 530 | 538 | |
| 531 | 539 | decompressedBlock = qUncompress(compressedBlock); |
| 540 | + | |
| 532 | 541 | decompressedBlockReader.setBuffer(&decompressedBlock); |
| 533 | 542 | decompressedBlockReader.open(QIODevice::ReadOnly); |
| 534 | 543 | } |
| ... | ... | @@ -538,11 +547,17 @@ bool BlockCompression::open(QIODevice::OpenMode mode) |
| 538 | 547 | |
| 539 | 548 | void BlockCompression::close() |
| 540 | 549 | { |
| 541 | - // flush output buffer | |
| 542 | - if ((openMode() & QIODevice::WriteOnly) && precompressedBlockWriter) { | |
| 543 | - QByteArray compressedBlock = qCompress(precompressedBlockWriter->buffer(), -1); | |
| 544 | - blockWriter << compressedBlock; | |
| 550 | + // flush output buffer, since we may have a partial block which hasn't been | |
| 551 | + // written to disk yet. | |
| 552 | + if ((openMode() & QIODevice::WriteOnly) && precompressedBlockWriter.isOpen()) { | |
| 553 | + QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer()); | |
| 554 | + precompressedBlockWriter.close(); | |
| 555 | + | |
| 556 | + quint32 bsize= compressedBlock.size(); | |
| 557 | + blockWriter << bsize; | |
| 558 | + blockWriter.writeRawData(compressedBlock.data(), compressedBlock.size()); | |
| 545 | 559 | } |
| 560 | + // close the underlying device. | |
| 546 | 561 | basis->close(); |
| 547 | 562 | } |
| 548 | 563 | |
| ... | ... | @@ -557,8 +572,10 @@ void BlockCompression::setBasis(QIODevice *_basis) |
| 557 | 572 | // block from basis |
| 558 | 573 | qint64 BlockCompression::readData(char *data, qint64 remaining) |
| 559 | 574 | { |
| 575 | + qint64 initial = remaining; | |
| 560 | 576 | qint64 read = 0; |
| 561 | 577 | while (remaining > 0) { |
| 578 | + // attempt to read the target amount of data | |
| 562 | 579 | qint64 single_read = decompressedBlockReader.read(data, remaining); |
| 563 | 580 | if (single_read == -1) |
| 564 | 581 | qFatal("miss read"); |
| ... | ... | @@ -567,13 +584,21 @@ qint64 BlockCompression::readData(char *data, qint64 remaining) |
| 567 | 584 | read += single_read; |
| 568 | 585 | data += single_read; |
| 569 | 586 | |
| 570 | - // need a new block | |
| 587 | + // need a new block if we didn't get enough bytes from the previous read | |
| 571 | 588 | if (remaining > 0) { |
| 572 | 589 | QByteArray compressedBlock; |
| 573 | - blockReader >> compressedBlock; | |
| 574 | - if (compressedBlock.size() == 0) { | |
| 575 | - return read; | |
| 576 | - } | |
| 590 | + | |
| 591 | + // read the size of the next block | |
| 592 | + quint32 block_size; | |
| 593 | + blockReader >> block_size; | |
| 594 | + if (block_size == 0) | |
| 595 | + break; | |
| 596 | + | |
| 597 | + compressedBlock.resize(block_size); | |
| 598 | + int actualRead = blockReader.readRawData(compressedBlock.data(), block_size); | |
| 599 | + if (actualRead != block_size) | |
| 600 | + qFatal("Bad read on nominal block size: %d, only got %d", block_size, remaining); | |
| 601 | + | |
| 577 | 602 | decompressedBlock = qUncompress(compressedBlock); |
| 578 | 603 | |
| 579 | 604 | decompressedBlockReader.close(); |
| ... | ... | @@ -581,7 +606,12 @@ qint64 BlockCompression::readData(char *data, qint64 remaining) |
| 581 | 606 | decompressedBlockReader.open(QIODevice::ReadOnly); |
| 582 | 607 | } |
| 583 | 608 | } |
| 584 | - return blockReader.atEnd() && !basis->isReadable() ? -1 : read; | |
| 609 | + | |
| 610 | + bool condition = blockReader.atEnd() && !basis->isReadable() ; | |
| 611 | + if (condition) | |
| 612 | + qWarning("Returning -1 from read"); | |
| 613 | + | |
| 614 | + return condition ? -1 : read; | |
| 585 | 615 | } |
| 586 | 616 | |
| 587 | 617 | bool BlockCompression::isSequential() const |
| ... | ... | @@ -591,36 +621,57 @@ bool BlockCompression::isSequential() const |
| 591 | 621 | |
| 592 | 622 | qint64 BlockCompression::writeData(const char *data, qint64 remaining) |
| 593 | 623 | { |
| 624 | + const char * endPoint = data + remaining; | |
| 625 | + qint64 initial = remaining; | |
| 626 | + | |
| 594 | 627 | qint64 written = 0; |
| 595 | 628 | |
| 596 | 629 | while (remaining > 0) { |
| 597 | 630 | // how much more can be put in this buffer? |
| 598 | - qint64 capacity = blockSize - precompressedBlockWriter->pos(); | |
| 631 | + qint64 capacity = blockSize - precompressedBlockWriter.pos(); | |
| 632 | + if (capacity < 0) | |
| 633 | + qFatal("Negative capacity!!!"); | |
| 599 | 634 | |
| 600 | 635 | // don't try to write beyond capacity |
| 601 | 636 | qint64 write_size = qMin(capacity, remaining); |
| 602 | 637 | |
| 603 | - qint64 singleWrite = precompressedBlockWriter->write(data, write_size); | |
| 604 | - // ignore the error case here, we consdier basis's failure mode the real | |
| 605 | - // end case | |
| 638 | + qint64 singleWrite = precompressedBlockWriter.write(data, write_size); | |
| 639 | + | |
| 606 | 640 | if (singleWrite == -1) |
| 607 | - singleWrite = 0; | |
| 641 | + qFatal("matrix write failure?"); | |
| 608 | 642 | |
| 609 | 643 | remaining -= singleWrite; |
| 610 | 644 | data += singleWrite; |
| 611 | 645 | written += singleWrite; |
| 646 | + if (data > endPoint) | |
| 647 | + qFatal("Wrote past the end"); | |
| 612 | 648 | |
| 613 | 649 | if (remaining > 0) { |
| 614 | - QByteArray compressedBlock = qCompress(precompressedBlockWriter->buffer(), -1); | |
| 650 | + QByteArray compressedBlock = qCompress(precompressedBlockWriter.buffer(), -1); | |
| 615 | 651 | |
| 616 | - if (compressedBlock.size() != 0) | |
| 617 | - blockWriter << compressedBlock; | |
| 652 | + if (precompressedBlockWriter.buffer().size() != 0) { | |
| 653 | + quint32 block_size = compressedBlock.size(); | |
| 654 | + blockWriter << block_size; | |
| 618 | 655 | |
| 619 | - delete precompressedBlockWriter; | |
| 620 | - precompressedBlockWriter = new QBuffer; | |
| 621 | - precompressedBlockWriter->open(QIODevice::ReadWrite); | |
| 656 | + int write_count = blockWriter.writeRawData(compressedBlock.data(), block_size); | |
| 657 | + if (write_count != block_size) | |
| 658 | + qFatal("Didn't write enough data"); | |
| 659 | + } | |
| 660 | + else | |
| 661 | + qFatal("serialized empty compressed block (?)"); | |
| 662 | + | |
| 663 | + precompressedBlockWriter.close(); | |
| 664 | + precompressedBlockWriter.open(QIODevice::WriteOnly); | |
| 622 | 665 | } |
| 623 | 666 | } |
| 667 | + | |
| 668 | + if (written != initial) | |
| 669 | + qFatal("didn't write enough bytes"); | |
| 670 | + | |
| 671 | + bool condition = basis->isWritable(); | |
| 672 | + if (!condition) | |
| 673 | + qWarning("Returning -1 from write"); | |
| 674 | + | |
| 624 | 675 | return basis->isWritable() ? written : -1; |
| 625 | 676 | } |
| 626 | 677 | ... | ... |
openbr/core/qtutils.h
| ... | ... | @@ -122,7 +122,7 @@ namespace QtUtils |
| 122 | 122 | |
| 123 | 123 | // write to a QByteArray, when max block sized is reached, compress and write |
| 124 | 124 | // it to basis |
| 125 | - QBuffer * precompressedBlockWriter; | |
| 125 | + QBuffer precompressedBlockWriter; | |
| 126 | 126 | QDataStream blockWriter; |
| 127 | 127 | qint64 writeData(const char *data, qint64 remaining); |
| 128 | 128 | }; | ... | ... |