forked from qpdf/qpdf
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e0d1cd1
commit 2d2f619
Showing
19 changed files
with
352 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright (c) 2005-2015 Jay Berkenbilt | ||
// | ||
// This file is part of qpdf. This software may be distributed under | ||
// the terms of version 2 of the Artistic License which may be found | ||
// in the source distribution. It is provided "as is" without express | ||
// or implied warranty. | ||
|
||
#ifndef __PL_RUNLENGTH_HH__ | ||
#define __PL_RUNLENGTH_HH__ | ||
|
||
#include <qpdf/Pipeline.hh> | ||
|
||
class Pl_RunLength: public Pipeline | ||
{ | ||
public: | ||
enum action_e { a_encode, a_decode }; | ||
|
||
QPDF_DLL | ||
Pl_RunLength(char const* identifier, Pipeline* next, | ||
action_e action); | ||
QPDF_DLL | ||
virtual ~Pl_RunLength(); | ||
|
||
QPDF_DLL | ||
virtual void write(unsigned char* data, size_t len); | ||
QPDF_DLL | ||
virtual void finish(); | ||
|
||
private: | ||
void encode(unsigned char* data, size_t len); | ||
void decode(unsigned char* data, size_t len); | ||
void flush_encode(); | ||
|
||
enum state_e { st_top, st_copying, st_run }; | ||
|
||
action_e action; | ||
state_e state; | ||
unsigned char buf[128]; | ||
unsigned int length; | ||
}; | ||
|
||
#endif // __PL_RUNLENGTH_HH__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
#include <qpdf/Pl_RunLength.hh> | ||
|
||
#include <qpdf/QUtil.hh> | ||
#include <qpdf/QTC.hh> | ||
|
||
Pl_RunLength::Pl_RunLength(char const* identifier, Pipeline* next, | ||
action_e action) : | ||
Pipeline(identifier, next), | ||
action(action), | ||
state(st_top), | ||
length(0) | ||
{ | ||
} | ||
|
||
Pl_RunLength::~Pl_RunLength() | ||
{ | ||
} | ||
|
||
void | ||
Pl_RunLength::write(unsigned char* data, size_t len) | ||
{ | ||
if (this->action == a_encode) | ||
{ | ||
encode(data, len); | ||
} | ||
else | ||
{ | ||
decode(data, len); | ||
} | ||
} | ||
|
||
void | ||
Pl_RunLength::encode(unsigned char* data, size_t len) | ||
{ | ||
for (size_t i = 0; i < len; ++i) | ||
{ | ||
if ((this->state == st_top) != (this->length <= 1)) | ||
{ | ||
throw std::logic_error( | ||
"Pl_RunLength::encode: state/length inconsistency"); | ||
} | ||
unsigned char ch = data[i]; | ||
if ((this->length > 0) && | ||
((this->state == st_copying) || (this->length < 128)) && | ||
(ch == this->buf[this->length-1])) | ||
{ | ||
QTC::TC("libtests", "Pl_RunLength: switch to run", | ||
(this->length == 128) ? 0 : 1); | ||
if (this->state == st_copying) | ||
{ | ||
--this->length; | ||
flush_encode(); | ||
this->buf[0] = ch; | ||
this->length = 1; | ||
} | ||
this->state = st_run; | ||
this->buf[this->length] = ch; | ||
++this->length; | ||
} | ||
else | ||
{ | ||
if ((this->length == 128) || (this->state == st_run)) | ||
{ | ||
flush_encode(); | ||
} | ||
else if (this->length > 0) | ||
{ | ||
this->state = st_copying; | ||
} | ||
this->buf[this->length] = ch; | ||
++this->length; | ||
} | ||
} | ||
} | ||
|
||
void | ||
Pl_RunLength::decode(unsigned char* data, size_t len) | ||
{ | ||
for (size_t i = 0; i < len; ++i) | ||
{ | ||
unsigned char ch = data[i]; | ||
switch (this->state) | ||
{ | ||
case st_top: | ||
if (ch < 128) | ||
{ | ||
// length represents remaining number of bytes to copy | ||
this->length = 1 + ch; | ||
this->state = st_copying; | ||
} | ||
else if (ch > 128) | ||
{ | ||
// length represents number of copies of next byte | ||
this->length = 257 - ch; | ||
this->state = st_run; | ||
} | ||
else // ch == 128 | ||
{ | ||
// EOD; stay in this state | ||
} | ||
break; | ||
|
||
case st_copying: | ||
this->getNext()->write(&ch, 1); | ||
if (--this->length == 0) | ||
{ | ||
this->state = st_top; | ||
} | ||
break; | ||
|
||
case st_run: | ||
for (unsigned int j = 0; j < this->length; ++j) | ||
{ | ||
this->getNext()->write(&ch, 1); | ||
} | ||
this->state = st_top; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
void | ||
Pl_RunLength::flush_encode() | ||
{ | ||
if (this->length == 128) | ||
{ | ||
QTC::TC("libtests", "Pl_RunLength flush full buffer", | ||
(this->state == st_copying ? 0 : | ||
this->state == st_run ? 1 : | ||
-1)); | ||
} | ||
if (this->length == 0) | ||
{ | ||
QTC::TC("libtests", "Pl_RunLength flush empty buffer"); | ||
} | ||
if (this->state == st_run) | ||
{ | ||
if ((this->length < 2) || (this->length > 128)) | ||
{ | ||
throw std::logic_error( | ||
"Pl_RunLength: invalid length in flush_encode for run"); | ||
} | ||
unsigned char ch = static_cast<unsigned char>(257 - this->length); | ||
this->getNext()->write(&ch, 1); | ||
this->getNext()->write(&this->buf[0], 1); | ||
} | ||
else if (this->length > 0) | ||
{ | ||
unsigned char ch = static_cast<unsigned char>(this->length - 1); | ||
this->getNext()->write(&ch, 1); | ||
this->getNext()->write(this->buf, this->length); | ||
} | ||
this->state = st_top; | ||
this->length = 0; | ||
} | ||
|
||
void | ||
Pl_RunLength::finish() | ||
{ | ||
// When decoding, we might have read a length byte not followed by | ||
// data, which means the stream was terminated early, but we will | ||
// just ignore this case since this is the only sensible thing to | ||
// do. | ||
if (this->action == a_encode) | ||
{ | ||
flush_encode(); | ||
unsigned char ch = 128; | ||
this->getNext()->write(&ch, 1); | ||
} | ||
this->getNext()->finish(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
#!/usr/bin/env perl | ||
require 5.008; | ||
use warnings; | ||
use strict; | ||
|
||
chdir("runlength") or die "chdir testdir failed: $!\n"; | ||
|
||
require TestDriver; | ||
|
||
my $td = new TestDriver('runlength'); | ||
|
||
cleanup(); | ||
|
||
my @files = ( | ||
"01", # basic case, ends with copy | ||
"02", # basic case, ends with run | ||
"03", # long run run | ||
"04", # ends with copy, length % 128 == 0 | ||
"05", # run starts at byte 128 | ||
"empty", # empty file | ||
); | ||
|
||
# Create this rather than committing an empty file, which always looks | ||
# like an error. | ||
open(F, ">empty"); | ||
close(F); | ||
|
||
foreach my $f (@files) | ||
{ | ||
$td->runtest("encode $f", | ||
{$td->COMMAND => "runlength -encode $f a"}, | ||
{$td->STRING => "", $td->EXIT_STATUS => 0}); | ||
$td->runtest("check encoded output", | ||
{$td->FILE => "a"}, | ||
{$td->FILE => "$f.encoded"}); | ||
$td->runtest("decode $f.encoded", | ||
{$td->COMMAND => "runlength -decode $f.encoded a"}, | ||
{$td->STRING => "", $td->EXIT_STATUS => 0}); | ||
$td->runtest("check decoded output", | ||
{$td->FILE => "a"}, | ||
{$td->FILE => "$f"}); | ||
} | ||
|
||
concatenate("01.encoded", "02.encoded", "concat.encoded"); | ||
concatenate("01", "02", "concat"); | ||
|
||
$td->runtest("decode with embedded EOD", | ||
{$td->COMMAND => "runlength -decode concat.encoded a"}, | ||
{$td->STRING => "", $td->EXIT_STATUS => 0}); | ||
$td->runtest("check decoded output", | ||
{$td->FILE => "a"}, | ||
{$td->FILE => "concat"}); | ||
|
||
cleanup(); | ||
|
||
$td->report(2 + (4 * scalar(@files))); | ||
|
||
sub cleanup | ||
{ | ||
system("rm -f a concat concat.encoded empty"); | ||
} | ||
|
||
sub concatenate | ||
{ | ||
my ($a, $b, $out) = @_; | ||
open(F, ">$out"); | ||
foreach my $f ($a, $b) | ||
{ | ||
local $/ = undef; | ||
open(G, "<$f"); | ||
print F <G>; | ||
close(G); | ||
} | ||
close(F); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
wwwwwwwwwwwwwwwwwwwwwwwwwqqqqqrstv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
�w�qrstv� |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
wwwwwwwwwwwwwwwwwwwwwwwwwqqqqqrstvxxxxxxxxxxxxxxxxxxxxxxx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
�w�qrstv�x� |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
�wabababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababab� |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababbbbbb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
~abababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababababa�b� |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
� |
Oops, something went wrong.