2021-04-17 02:41:46 +02:00
|
|
|
|
//
|
|
|
|
|
// PDF stream functions for pdfio.
|
|
|
|
|
//
|
|
|
|
|
// Copyright © 2021 by Michael R Sweet.
|
|
|
|
|
//
|
|
|
|
|
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
|
|
|
|
// information.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Include necessary headers...
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include "pdfio-private.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// 'pdfioStreamClose()' - Close a (data) stream in a PDF file.
|
2021-04-17 02:41:46 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-30 13:06:56 +02:00
|
|
|
|
bool // O - `true` on success, `false` on failure
|
|
|
|
|
pdfioStreamClose(pdfio_stream_t *st) // I - Stream
|
2021-04-17 02:41:46 +02:00
|
|
|
|
{
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// TODO: Implement me
|
|
|
|
|
(void)st;
|
|
|
|
|
return (false);
|
2021-04-17 02:41:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-05-06 22:07:58 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioStreamCreate()' - Create a stream for writing.
|
|
|
|
|
//
|
|
|
|
|
// Note: pdfioObjCreateStream handles writing the object and its dictionary.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
pdfio_stream_t * // O - Stream or `NULL` on error
|
|
|
|
|
_pdfioStreamCreate(
|
|
|
|
|
pdfio_obj_t *obj, // I - Object
|
|
|
|
|
pdfio_filter_t compression) // I - Compression to apply
|
|
|
|
|
{
|
|
|
|
|
// TODO: Implement me
|
|
|
|
|
(void)obj;
|
|
|
|
|
(void)compression;
|
|
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-05-02 04:38:11 +02:00
|
|
|
|
//
|
|
|
|
|
// 'pdfioStreamConsume()' - Consume bytes from the stream.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `true` on success, `false` on EOF
|
|
|
|
|
pdfioStreamConsume(pdfio_stream_t *st, // I - Stream
|
|
|
|
|
size_t bytes)// I - Number of bytes to consume
|
|
|
|
|
{
|
|
|
|
|
// TODO: Implement me
|
|
|
|
|
(void)st;
|
|
|
|
|
(void)bytes;
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// '_pdfioStreamDelete()' - Free all memory used by a stream.
|
2021-04-17 03:09:43 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-30 13:06:56 +02:00
|
|
|
|
void
|
|
|
|
|
_pdfioStreamDelete(pdfio_stream_t *st) // I - Stream
|
2021-04-17 03:09:43 +02:00
|
|
|
|
{
|
2021-04-30 13:06:56 +02:00
|
|
|
|
if (st->filter == PDFIO_FILTER_FLATE)
|
|
|
|
|
{
|
|
|
|
|
// Free memory used for flate compression/decompression...
|
|
|
|
|
if (st->pdf->mode == _PDFIO_MODE_READ)
|
|
|
|
|
inflateEnd(&st->flate);
|
|
|
|
|
else // mode == _PDFIO_MODE_WRITE
|
|
|
|
|
deflateEnd(&st->flate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(st);
|
2021-04-17 03:09:43 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
//
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// 'pdfioStreamGetToken()' - Read a single PDF token from a stream.
|
2021-04-26 16:42:01 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-30 13:06:56 +02:00
|
|
|
|
bool // O - `true` on success, `false` on EOF
|
|
|
|
|
pdfioStreamGetToken(
|
|
|
|
|
pdfio_stream_t *st, // I - Stream
|
|
|
|
|
char *buffer, // I - String buffer
|
|
|
|
|
size_t bufsize) // I - Size of string buffer
|
2021-05-01 23:50:52 +02:00
|
|
|
|
{
|
2021-05-02 04:38:11 +02:00
|
|
|
|
return (_pdfioTokenRead(st->pdf, buffer, bufsize, (_pdfio_tpeek_cb_t)pdfioStreamPeek, (_pdfio_tconsume_cb_t)pdfioStreamConsume, st));
|
2021-05-01 23:50:52 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-05-06 22:07:58 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioStreamOpen()' - Create a stream for reading.
|
|
|
|
|
//
|
|
|
|
|
// Note: pdfioObjOpenStream handles loading the object's dictionary and
|
|
|
|
|
// getting the start of the stream data.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
pdfio_stream_t * // O - Stream or `NULL` on error
|
|
|
|
|
_pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
|
|
|
|
|
bool decode) // I - Decode/decompress the stream?
|
|
|
|
|
{
|
|
|
|
|
pdfio_stream_t *st; // Stream
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Allocate a new stream object...
|
|
|
|
|
if ((st = (pdfio_stream_t *)calloc(1, sizeof(pdfio_stream_t))) == NULL)
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(obj->pdf, "Unable to allocate memory for a stream.");
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
st->pdf = obj->pdf;
|
|
|
|
|
st->obj = obj;
|
|
|
|
|
|
|
|
|
|
_pdfioFileSeek(st->pdf, obj->stream_offset, SEEK_SET);
|
|
|
|
|
|
|
|
|
|
if (decode)
|
|
|
|
|
{
|
|
|
|
|
// Try to decode/decompress the contents of this object...
|
|
|
|
|
pdfio_dict_t *dict = pdfioObjGetDict(obj);
|
|
|
|
|
// Object dictionary
|
|
|
|
|
const char *filter = pdfioDictGetName(dict, "Filter");
|
|
|
|
|
// Filter value
|
|
|
|
|
|
|
|
|
|
if (!filter)
|
|
|
|
|
{
|
|
|
|
|
// No single filter name, do we have a compound filter?
|
|
|
|
|
if (pdfioDictGetArray(dict, "Filter"))
|
|
|
|
|
{
|
|
|
|
|
// TODO: Implement compound filters...
|
|
|
|
|
_pdfioFileError(st->pdf, "Unsupported compound stream filter.");
|
|
|
|
|
free(st);
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No filter, read as-is...
|
|
|
|
|
st->filter = PDFIO_FILTER_NONE;
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp(filter, "FlateDecode"))
|
|
|
|
|
{
|
|
|
|
|
// Flate compression
|
|
|
|
|
int bpc = (int)pdfioDictGetNumber(dict, "BitsPerComponent");
|
|
|
|
|
// Bits per component
|
|
|
|
|
int colors = (int)pdfioDictGetNumber(dict, "Colors");
|
|
|
|
|
// Number of colors
|
|
|
|
|
int columns = (int)pdfioDictGetNumber(dict, "Columns");
|
|
|
|
|
// Number of columns
|
|
|
|
|
int predictor = (int)pdfioDictGetNumber(dict, "Predictor");
|
|
|
|
|
// Predictory value, if any
|
|
|
|
|
|
|
|
|
|
st->filter = PDFIO_FILTER_FLATE;
|
|
|
|
|
}
|
|
|
|
|
else if (!strcmp(filter, "LZWDecode"))
|
|
|
|
|
{
|
|
|
|
|
// LZW compression
|
|
|
|
|
st->filter = PDFIO_FILTER_LZW;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Something else we don't support
|
|
|
|
|
_pdfioFileError(st->pdf, "Unsupported stream filter '/%s'.", filter);
|
|
|
|
|
free(st);
|
|
|
|
|
return (NULL);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Just return the stream data as-is...
|
|
|
|
|
st->filter = PDFIO_FILTER_NONE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (st);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-05-01 23:50:52 +02:00
|
|
|
|
//
|
|
|
|
|
// 'pdfioStreamPeek()' - Peek at data in a stream.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
ssize_t // O - Bytes returned or `-1` on error
|
|
|
|
|
pdfioStreamPeek(pdfio_stream_t *st, // I - Stream
|
|
|
|
|
void *buffer, // I - Buffer
|
|
|
|
|
size_t bytes) // I - Size of buffer
|
2021-04-26 16:42:01 +02:00
|
|
|
|
{
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// TODO: Implement me
|
|
|
|
|
(void)st;
|
|
|
|
|
(void)buffer;
|
2021-05-01 23:50:52 +02:00
|
|
|
|
(void)bytes;
|
2021-04-30 13:06:56 +02:00
|
|
|
|
|
2021-05-01 23:50:52 +02:00
|
|
|
|
return (-1);
|
2021-04-26 16:42:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-04-17 02:41:46 +02:00
|
|
|
|
//
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// 'pdfioStreamPrintf()' - Write a formatted string to a stream.
|
2021-04-17 02:41:46 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-30 13:06:56 +02:00
|
|
|
|
bool // O - `true` on success, `false` on failure
|
|
|
|
|
pdfioStreamPrintf(
|
|
|
|
|
pdfio_stream_t *st, // I - Stream
|
|
|
|
|
const char *format, // I - `printf`-style format string
|
|
|
|
|
...) // I - Additional arguments as needed
|
2021-04-17 02:41:46 +02:00
|
|
|
|
{
|
2021-04-30 13:06:56 +02:00
|
|
|
|
char buffer[8192]; // String buffer
|
|
|
|
|
va_list ap; // Argument pointer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Format the string...
|
|
|
|
|
va_start(ap, format);
|
|
|
|
|
vsnprintf(buffer, sizeof(buffer), format, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
|
|
// Write the string...
|
|
|
|
|
return (pdfioStreamWrite(st, buffer, strlen(buffer)));
|
2021-04-17 02:41:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// 'pdfioStreamPuts()' - Write a literal string to a stream.
|
2021-04-17 02:41:46 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-30 13:06:56 +02:00
|
|
|
|
bool // O - `true` on success, `false` on failure
|
|
|
|
|
pdfioStreamPuts(pdfio_stream_t *st, // I - Stream
|
|
|
|
|
const char *s) // I - Literal string
|
2021-04-17 02:41:46 +02:00
|
|
|
|
{
|
2021-04-30 13:06:56 +02:00
|
|
|
|
if (!st || !s)
|
|
|
|
|
return (false);
|
|
|
|
|
else
|
|
|
|
|
return (pdfioStreamWrite(st, s, strlen(s)));
|
2021-04-17 02:41:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// 'pdfioStreamRead()' - Read data from a stream.
|
2021-04-17 02:41:46 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-30 13:06:56 +02:00
|
|
|
|
ssize_t // O - Number of bytes read or `-1` on error
|
|
|
|
|
pdfioStreamRead(
|
|
|
|
|
pdfio_stream_t *st, // I - Stream
|
|
|
|
|
void *buffer, // I - Buffer
|
|
|
|
|
size_t bytes) // I - Bytes to read
|
2021-04-17 02:41:46 +02:00
|
|
|
|
{
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// TODO: Implement me
|
|
|
|
|
(void)st;
|
|
|
|
|
(void)buffer;
|
|
|
|
|
(void)bytes;
|
|
|
|
|
|
|
|
|
|
return (-1);
|
2021-04-17 02:41:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// 'pdfioStreamWrite()' - Write data to a stream.
|
2021-04-17 02:41:46 +02:00
|
|
|
|
//
|
|
|
|
|
|
2021-04-30 13:06:56 +02:00
|
|
|
|
bool // O - `true` on success or `false` on failure
|
|
|
|
|
pdfioStreamWrite(
|
|
|
|
|
pdfio_stream_t *st, // I - Stream
|
|
|
|
|
const void *buffer, // I - Data to write
|
|
|
|
|
size_t bytes) // I - Number of bytes to write
|
2021-04-17 02:41:46 +02:00
|
|
|
|
{
|
2021-04-30 13:06:56 +02:00
|
|
|
|
// TODO: Implement me
|
|
|
|
|
(void)st;
|
|
|
|
|
(void)buffer;
|
|
|
|
|
(void)bytes;
|
2021-04-17 02:41:46 +02:00
|
|
|
|
|
2021-04-30 13:06:56 +02:00
|
|
|
|
return (false);
|
|
|
|
|
}
|