2021-04-10 14:00:52 +02:00
|
|
|
|
//
|
|
|
|
|
// Common support functions for pdfio.
|
|
|
|
|
//
|
2023-02-04 02:39:04 +01:00
|
|
|
|
// Copyright © 2021-2023 by Michael R Sweet.
|
2021-04-10 14:00:52 +02:00
|
|
|
|
//
|
|
|
|
|
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
|
|
|
|
// information.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// Include necessary headers...
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#include "pdfio-private.h"
|
2021-04-26 02:12:52 +02:00
|
|
|
|
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
//
|
|
|
|
|
// Local functions...
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
static bool fill_buffer(pdfio_file_t *pdf);
|
|
|
|
|
static ssize_t read_buffer(pdfio_file_t *pdf, char *buffer, size_t bytes);
|
2021-05-01 23:50:52 +02:00
|
|
|
|
static bool write_buffer(pdfio_file_t *pdf, const void *buffer, size_t bytes);
|
2021-04-26 16:42:01 +02:00
|
|
|
|
|
|
|
|
|
|
2021-05-02 04:38:11 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileConsume()' - Consume bytes from the file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `true` on sucess, `false` on EOF
|
|
|
|
|
_pdfioFileConsume(pdfio_file_t *pdf, // I - PDF file
|
|
|
|
|
size_t bytes) // I - Bytes to consume
|
|
|
|
|
{
|
2021-05-04 18:59:10 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioFileConsume(pdf=%p, bytes=%u)\n", pdf, (unsigned)bytes);
|
|
|
|
|
|
2021-05-02 04:38:11 +02:00
|
|
|
|
if ((size_t)(pdf->bufend - pdf->bufptr) > bytes)
|
|
|
|
|
pdf->bufptr += bytes;
|
|
|
|
|
else if (_pdfioFileSeek(pdf, (off_t)bytes, SEEK_CUR) < 0)
|
|
|
|
|
return (false);
|
|
|
|
|
|
2023-02-04 02:39:04 +01:00
|
|
|
|
PDFIO_DEBUG("_pdfioFileConsume: pos=%ld\n", (long)(pdf->bufpos + pdf->bufptr - pdf->buffer));
|
|
|
|
|
|
2021-05-02 04:38:11 +02:00
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-04-26 02:12:52 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileDefaultError()' - Default error callback.
|
|
|
|
|
//
|
|
|
|
|
// The default error callback writes the error message to stderr and returns
|
|
|
|
|
// `false` to halt.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `false` to stop
|
|
|
|
|
_pdfioFileDefaultError(
|
|
|
|
|
pdfio_file_t *pdf, // I - PDF file
|
|
|
|
|
const char *message, // I - Error message
|
|
|
|
|
void *data) // I - Callback data (unused)
|
|
|
|
|
{
|
|
|
|
|
(void)data;
|
|
|
|
|
|
|
|
|
|
fprintf(stderr, "%s: %s\n", pdf->filename, message);
|
|
|
|
|
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileError()' - Display an error message.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `true` to continue, `false` to stop
|
|
|
|
|
_pdfioFileError(pdfio_file_t *pdf, // I - PDF file
|
|
|
|
|
const char *format, // I - `printf`-style format string
|
|
|
|
|
...) // I - Additional arguments as needed
|
|
|
|
|
{
|
|
|
|
|
char buffer[8192]; // Message buffer
|
|
|
|
|
va_list ap; // Argument pointer
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
va_start(ap, format);
|
|
|
|
|
vsnprintf(buffer, sizeof(buffer), format, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
|
2021-08-30 16:55:45 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioFileError: %s\n", buffer);
|
|
|
|
|
|
2021-04-26 02:12:52 +02:00
|
|
|
|
return ((pdf->error_cb)(pdf, buffer, pdf->error_data));
|
|
|
|
|
}
|
2021-04-26 16:42:01 +02:00
|
|
|
|
|
|
|
|
|
|
2021-04-28 03:22:34 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileFlush()' - Flush any pending write data.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `true` on success, `false` on failure
|
|
|
|
|
_pdfioFileFlush(pdfio_file_t *pdf) // I - PDF file
|
|
|
|
|
{
|
2021-05-04 18:59:10 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioFileFlush(pdf=%p)\n", pdf);
|
|
|
|
|
|
2021-04-28 03:22:34 +02:00
|
|
|
|
if (pdf->bufptr > pdf->buffer)
|
|
|
|
|
{
|
|
|
|
|
if (!write_buffer(pdf, pdf->buffer, (size_t)(pdf->bufptr - pdf->buffer)))
|
|
|
|
|
return (false);
|
|
|
|
|
|
|
|
|
|
pdf->bufpos += pdf->bufptr - pdf->buffer;
|
|
|
|
|
}
|
|
|
|
|
|
2021-05-16 18:36:44 +02:00
|
|
|
|
pdf->bufptr = pdf->buffer;
|
|
|
|
|
|
2021-04-28 03:22:34 +02:00
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileGetChar()' - Get a character from a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
int // O - Character or `-1` on EOF
|
|
|
|
|
_pdfioFileGetChar(pdfio_file_t *pdf) // I - PDF file
|
|
|
|
|
{
|
|
|
|
|
// If there is a character ready in the buffer, return it now...
|
|
|
|
|
if (pdf->bufptr < pdf->bufend)
|
|
|
|
|
return (*(pdf->bufptr ++));
|
|
|
|
|
|
|
|
|
|
// Otherwise try to fill the read buffer...
|
|
|
|
|
if (!fill_buffer(pdf))
|
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
|
|
// Then return the next character in the buffer...
|
|
|
|
|
return (*(pdf->bufptr ++));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-05-01 17:41:43 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileGets()' - Read a line from a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `true` on success, `false` on error
|
|
|
|
|
_pdfioFileGets(pdfio_file_t *pdf, // I - PDF file
|
|
|
|
|
char *buffer, // I - Line buffer
|
|
|
|
|
size_t bufsize) // I - Size of line buffer
|
|
|
|
|
{
|
|
|
|
|
bool eol = false; // End of line?
|
|
|
|
|
char *bufptr = buffer, // Pointer into buffer
|
|
|
|
|
*bufend = buffer + bufsize - 1; // Pointer to end of buffer
|
|
|
|
|
|
|
|
|
|
|
2021-06-10 16:58:07 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioFileGets(pdf=%p, buffer=%p, bufsize=%lu) bufpos=%ld, buffer=%p, bufptr=%p, bufend=%p\n", pdf, buffer, (unsigned long)bufsize, (long)pdf->bufpos, pdf->buffer, pdf->bufptr, pdf->bufend);
|
|
|
|
|
|
2021-05-01 17:41:43 +02:00
|
|
|
|
while (!eol)
|
|
|
|
|
{
|
|
|
|
|
// If there are characters ready in the buffer, use them...
|
2021-05-01 17:50:17 +02:00
|
|
|
|
while (!eol && pdf->bufptr < pdf->bufend && bufptr < bufend)
|
2021-05-01 17:41:43 +02:00
|
|
|
|
{
|
|
|
|
|
char ch = *(pdf->bufptr++); // Next character in buffer
|
|
|
|
|
|
|
|
|
|
if (ch == '\n' || ch == '\r')
|
|
|
|
|
{
|
|
|
|
|
// CR, LF, or CR + LF end a line...
|
|
|
|
|
eol = true;
|
|
|
|
|
|
|
|
|
|
if (ch == '\r')
|
|
|
|
|
{
|
|
|
|
|
// Check for a LF after CR
|
|
|
|
|
if (pdf->bufptr >= pdf->bufend)
|
2021-06-04 16:56:23 +02:00
|
|
|
|
{
|
|
|
|
|
if (!fill_buffer(pdf))
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-05-01 17:41:43 +02:00
|
|
|
|
|
|
|
|
|
if (pdf->bufptr < pdf->bufend && *(pdf->bufptr) == '\n')
|
|
|
|
|
pdf->bufptr ++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
*bufptr++ = ch;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fill the read buffer as needed...
|
|
|
|
|
if (!eol)
|
|
|
|
|
{
|
|
|
|
|
if (!fill_buffer(pdf))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*bufptr = '\0';
|
|
|
|
|
|
2021-06-10 16:58:07 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioFileGets: Returning %s, '%s'\n", eol ? "true" : "false", buffer);
|
|
|
|
|
|
2021-05-01 17:41:43 +02:00
|
|
|
|
return (eol);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-05-01 23:50:52 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioFilePeek()' - Peek at upcoming data in a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
ssize_t // O - Number of bytes returned
|
|
|
|
|
_pdfioFilePeek(pdfio_file_t *pdf, // I - PDF file
|
|
|
|
|
void *buffer, // I - Buffer
|
|
|
|
|
size_t bytes) // I - Size of bufffer
|
|
|
|
|
{
|
|
|
|
|
ssize_t total; // Total bytes available
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// See how much data is buffered up...
|
|
|
|
|
if (pdf->bufptr >= pdf->bufend)
|
|
|
|
|
{
|
|
|
|
|
// Fill the buffer...
|
|
|
|
|
if (!fill_buffer(pdf))
|
|
|
|
|
return (-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((total = pdf->bufend - pdf->bufptr) < (ssize_t)bytes && total < (ssize_t)(sizeof(pdf->buffer) / 2))
|
|
|
|
|
{
|
|
|
|
|
// Yes, try reading more...
|
|
|
|
|
ssize_t rbytes; // Bytes read
|
|
|
|
|
|
2021-05-10 23:37:57 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioFilePeek: Sliding buffer, total=%ld\n", (long)total);
|
|
|
|
|
|
2021-05-01 23:50:52 +02:00
|
|
|
|
memmove(pdf->buffer, pdf->bufptr, total);
|
|
|
|
|
pdf->bufpos += pdf->bufptr - pdf->buffer;
|
|
|
|
|
pdf->bufptr = pdf->buffer;
|
|
|
|
|
pdf->bufend = pdf->buffer + total;
|
|
|
|
|
|
|
|
|
|
// Read until we have bytes or a non-recoverable error...
|
|
|
|
|
while ((rbytes = read(pdf->fd, pdf->bufend, sizeof(pdf->buffer) - (size_t)total)) < 0)
|
|
|
|
|
{
|
|
|
|
|
if (errno != EINTR && errno != EAGAIN)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rbytes > 0)
|
|
|
|
|
{
|
|
|
|
|
// Expand the buffer...
|
|
|
|
|
pdf->bufend += rbytes;
|
|
|
|
|
total += rbytes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copy anything we have to the buffer...
|
|
|
|
|
if (total > (ssize_t)bytes)
|
|
|
|
|
total = (ssize_t)bytes;
|
|
|
|
|
|
|
|
|
|
if (total > 0)
|
|
|
|
|
memcpy(buffer, pdf->bufptr, total);
|
|
|
|
|
|
|
|
|
|
return (total);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-04-28 03:22:34 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioFilePrintf()' - Write a formatted string to a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `true` on success, `false` on failure
|
|
|
|
|
_pdfioFilePrintf(pdfio_file_t *pdf, // I - PDF file
|
|
|
|
|
const char *format, // I - `printf`-style format string
|
|
|
|
|
...) // I - Additional arguments as needed
|
|
|
|
|
{
|
|
|
|
|
char buffer[8102]; // String buffer
|
|
|
|
|
va_list ap; // Argument list
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Format the string...
|
|
|
|
|
va_start(ap, format);
|
|
|
|
|
vsnprintf(buffer, sizeof(buffer), format, ap);
|
|
|
|
|
va_end(ap);
|
|
|
|
|
|
|
|
|
|
// Write it...
|
|
|
|
|
return (_pdfioFileWrite(pdf, buffer, strlen(buffer)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// '_pdfioFilePuts()' - Write a literal string to a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `true` on success, `false` on failure
|
|
|
|
|
_pdfioFilePuts(pdfio_file_t *pdf, // I - PDF file
|
|
|
|
|
const char *s) // I - Literal string
|
|
|
|
|
{
|
|
|
|
|
// Write it...
|
|
|
|
|
return (_pdfioFileWrite(pdf, s, strlen(s)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileRead()' - Read from a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
ssize_t // O - Number of bytes read or `-1` on error
|
|
|
|
|
_pdfioFileRead(pdfio_file_t *pdf, // I - PDF file
|
2021-05-01 23:50:52 +02:00
|
|
|
|
void *buffer, // I - Read buffer
|
2021-04-26 16:42:01 +02:00
|
|
|
|
size_t bytes) // I - Number of bytes to read
|
|
|
|
|
{
|
2021-05-01 23:50:52 +02:00
|
|
|
|
char *bufptr = (char *)buffer;
|
|
|
|
|
// Pointer into buffer
|
2021-04-26 16:42:01 +02:00
|
|
|
|
ssize_t total, // Total bytes read
|
|
|
|
|
rbytes; // Bytes read this time
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Loop until we have read all of the requested bytes or hit an error...
|
2021-05-01 23:50:52 +02:00
|
|
|
|
for (total = 0; bytes > 0; total += rbytes, bytes -= (size_t)rbytes, bufptr += rbytes)
|
2021-04-26 16:42:01 +02:00
|
|
|
|
{
|
|
|
|
|
// First read from the file buffer...
|
|
|
|
|
if ((rbytes = pdf->bufend - pdf->bufptr) > 0)
|
|
|
|
|
{
|
|
|
|
|
if ((size_t)rbytes > bytes)
|
|
|
|
|
rbytes = (ssize_t)bytes;
|
|
|
|
|
|
2021-05-01 23:50:52 +02:00
|
|
|
|
memcpy(bufptr, pdf->bufptr, rbytes);
|
2021-04-26 16:42:01 +02:00
|
|
|
|
pdf->bufptr += rbytes;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Nothing buffered...
|
|
|
|
|
if (bytes > 1024)
|
|
|
|
|
{
|
2021-06-10 16:58:07 +02:00
|
|
|
|
// Advance current position in file as needed...
|
|
|
|
|
if (pdf->bufend)
|
|
|
|
|
{
|
|
|
|
|
pdf->bufpos += pdf->bufend - pdf->buffer;
|
|
|
|
|
pdf->bufptr = pdf->bufend = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
// Read directly from the file...
|
2021-05-01 23:50:52 +02:00
|
|
|
|
if ((rbytes = read_buffer(pdf, bufptr, bytes)) > 0)
|
2021-04-26 16:42:01 +02:00
|
|
|
|
{
|
|
|
|
|
pdf->bufpos += rbytes;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-10-31 16:12:54 +01:00
|
|
|
|
else if (rbytes < 0 && (errno == EINTR || errno == EAGAIN))
|
|
|
|
|
{
|
|
|
|
|
rbytes = 0;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2021-04-26 16:42:01 +02:00
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Fill buffer and try again...
|
|
|
|
|
if (!fill_buffer(pdf))
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (total);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileSeek()' - Seek within a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
off_t // O - New offset from beginning of file or `-1` on error
|
|
|
|
|
_pdfioFileSeek(pdfio_file_t *pdf, // I - PDF file
|
|
|
|
|
off_t offset, // I - Offset
|
|
|
|
|
int whence) // I - Offset base
|
|
|
|
|
{
|
2021-05-10 23:37:57 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioFileSeek(pdf=%p, offset=%ld, whence=%d)\n", pdf, (long)offset, whence);
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
// Adjust offset for relative seeks...
|
|
|
|
|
if (whence == SEEK_CUR)
|
|
|
|
|
{
|
|
|
|
|
offset += pdf->bufpos;
|
|
|
|
|
whence = SEEK_SET;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-28 03:22:34 +02:00
|
|
|
|
if (pdf->mode == _PDFIO_MODE_READ)
|
2021-04-26 16:42:01 +02:00
|
|
|
|
{
|
|
|
|
|
// Reading, see if we already have the data we need...
|
|
|
|
|
if (whence != SEEK_END && offset >= pdf->bufpos && offset < (pdf->bufpos + pdf->bufend - pdf->buffer))
|
|
|
|
|
{
|
|
|
|
|
// Yes, seek within existing buffer...
|
|
|
|
|
pdf->bufptr = pdf->buffer + offset - pdf->bufpos;
|
2021-06-10 16:58:07 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioFileSeek: Seek within buffer, bufpos=%ld.\n", (long)pdf->bufpos);
|
|
|
|
|
PDFIO_DEBUG("_pdfioFileSeek: buffer=%p, bufptr=%p, bufend=%p\n", pdf->buffer, pdf->bufptr, pdf->bufend);
|
2021-04-26 16:42:01 +02:00
|
|
|
|
return (offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// No, reset the read buffer
|
|
|
|
|
pdf->bufptr = pdf->bufend = NULL;
|
|
|
|
|
}
|
2021-09-27 13:41:50 +02:00
|
|
|
|
else if (pdf->output_cb)
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(pdf, "Unable to seek within output stream.");
|
|
|
|
|
return (-1);
|
|
|
|
|
}
|
2021-04-26 16:42:01 +02:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Writing, make sure we write any buffered data...
|
|
|
|
|
if (pdf->bufptr > pdf->buffer)
|
|
|
|
|
{
|
|
|
|
|
if (!write_buffer(pdf, pdf->buffer, (size_t)(pdf->bufptr - pdf->buffer)))
|
|
|
|
|
return (-1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pdf->bufptr = pdf->buffer;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Seek within the file...
|
|
|
|
|
if ((offset = lseek(pdf->fd, offset, whence)) < 0)
|
|
|
|
|
{
|
|
|
|
|
_pdfioFileError(pdf, "Unable to seek within file - %s", strerror(errno));
|
|
|
|
|
return (-1);
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-10 16:58:07 +02:00
|
|
|
|
PDFIO_DEBUG("_pdfioFileSeek: Reset bufpos=%ld.\n", (long)pdf->bufpos);
|
|
|
|
|
PDFIO_DEBUG("_pdfioFileSeek: buffer=%p, bufptr=%p, bufend=%p\n", pdf->buffer, pdf->bufptr, pdf->bufend);
|
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
pdf->bufpos = offset;
|
|
|
|
|
|
|
|
|
|
return (offset);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileTell()' - Return the offset within a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
off_t // O - Offset from beginning of file
|
|
|
|
|
_pdfioFileTell(pdfio_file_t *pdf) // I - PDF file
|
|
|
|
|
{
|
|
|
|
|
if (pdf->bufptr)
|
|
|
|
|
return (pdf->bufpos + (pdf->bufptr - pdf->buffer));
|
|
|
|
|
else
|
|
|
|
|
return (pdf->bufpos);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// '_pdfioFileWrite()' - Write to a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
bool // O - `true` on success and `false` on error
|
|
|
|
|
_pdfioFileWrite(pdfio_file_t *pdf, // I - PDF file
|
2021-05-01 23:50:52 +02:00
|
|
|
|
const void *buffer, // I - Write buffer
|
2021-04-26 16:42:01 +02:00
|
|
|
|
size_t bytes) // I - Bytes to write
|
|
|
|
|
{
|
|
|
|
|
// See if the data will fit in the write buffer...
|
|
|
|
|
if (bytes > (size_t)(pdf->bufend - pdf->bufptr))
|
|
|
|
|
{
|
|
|
|
|
// No room, flush any current data...
|
2021-04-28 03:22:34 +02:00
|
|
|
|
if (!_pdfioFileFlush(pdf))
|
|
|
|
|
return (false);
|
2021-04-26 16:42:01 +02:00
|
|
|
|
|
|
|
|
|
if (bytes >= sizeof(pdf->buffer))
|
|
|
|
|
{
|
|
|
|
|
// Write directly...
|
|
|
|
|
if (!write_buffer(pdf, buffer, bytes))
|
|
|
|
|
return (false);
|
|
|
|
|
|
|
|
|
|
pdf->bufpos += bytes;
|
|
|
|
|
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copy data to the buffer and return...
|
|
|
|
|
memcpy(pdf->bufptr, buffer, bytes);
|
|
|
|
|
pdf->bufptr += bytes;
|
|
|
|
|
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 'fill_buffer()' - Fill the read buffer in a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
static bool // O - `true` on success, `false` on failure
|
|
|
|
|
fill_buffer(pdfio_file_t *pdf) // I - PDF file
|
|
|
|
|
{
|
|
|
|
|
ssize_t bytes; // Bytes read...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Advance current position in file as needed...
|
|
|
|
|
if (pdf->bufend)
|
|
|
|
|
pdf->bufpos += pdf->bufend - pdf->buffer;
|
|
|
|
|
|
|
|
|
|
// Try reading from the file...
|
|
|
|
|
if ((bytes = read_buffer(pdf, pdf->buffer, sizeof(pdf->buffer))) <= 0)
|
|
|
|
|
{
|
|
|
|
|
// EOF or hard error...
|
|
|
|
|
pdf->bufptr = pdf->bufend = NULL;
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Successful read...
|
|
|
|
|
pdf->bufptr = pdf->buffer;
|
|
|
|
|
pdf->bufend = pdf->buffer + bytes;
|
|
|
|
|
return (true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// 'read_buffer()' - Read a buffer from a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
static ssize_t // O - Number of bytes read or -1 on error
|
|
|
|
|
read_buffer(pdfio_file_t *pdf, // I - PDF file
|
|
|
|
|
char *buffer, // I - Buffer
|
|
|
|
|
size_t bytes) // I - Number of bytes to read
|
|
|
|
|
{
|
|
|
|
|
ssize_t rbytes; // Bytes read...
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Read from the file...
|
|
|
|
|
while ((rbytes = read(pdf->fd, buffer, bytes)) < 0)
|
|
|
|
|
{
|
|
|
|
|
// Stop if we have an error that shouldn't be retried...
|
|
|
|
|
if (errno != EINTR && errno != EAGAIN)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rbytes < 0)
|
|
|
|
|
{
|
|
|
|
|
// Hard error...
|
|
|
|
|
_pdfioFileError(pdf, "Unable to read from file - %s", strerror(errno));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (rbytes);
|
|
|
|
|
}
|
|
|
|
|
|
2023-02-04 02:39:04 +01:00
|
|
|
|
|
2021-04-26 16:42:01 +02:00
|
|
|
|
//
|
|
|
|
|
// 'write_buffer()' - Write a buffer to a PDF file.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
static bool // O - `true` on success and `false` on error
|
|
|
|
|
write_buffer(pdfio_file_t *pdf, // I - PDF file
|
2021-05-01 23:50:52 +02:00
|
|
|
|
const void *buffer, // I - Write buffer
|
2021-04-26 16:42:01 +02:00
|
|
|
|
size_t bytes) // I - Bytes to write
|
|
|
|
|
{
|
2021-05-01 23:50:52 +02:00
|
|
|
|
const char *bufptr = (const char *)buffer;
|
|
|
|
|
// Pointer into buffer
|
2021-04-26 16:42:01 +02:00
|
|
|
|
ssize_t wbytes; // Bytes written...
|
|
|
|
|
|
|
|
|
|
|
2021-09-27 13:41:50 +02:00
|
|
|
|
if (pdf->output_cb)
|
2021-04-26 16:42:01 +02:00
|
|
|
|
{
|
2021-09-27 13:41:50 +02:00
|
|
|
|
// Write to a stream...
|
|
|
|
|
if ((pdf->output_cb)(pdf->output_ctx, buffer, bytes) < 0)
|
2021-04-26 16:42:01 +02:00
|
|
|
|
{
|
2021-09-27 13:41:50 +02:00
|
|
|
|
_pdfioFileError(pdf, "Unable to write to output callback.");
|
2021-04-26 16:42:01 +02:00
|
|
|
|
return (false);
|
|
|
|
|
}
|
2021-09-27 13:41:50 +02:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
// Write to the file...
|
|
|
|
|
while (bytes > 0)
|
|
|
|
|
{
|
|
|
|
|
while ((wbytes = write(pdf->fd, bufptr, bytes)) < 0)
|
|
|
|
|
{
|
|
|
|
|
// Stop if we have an error that shouldn't be retried...
|
|
|
|
|
if (errno != EINTR && errno != EAGAIN)
|
|
|
|
|
break;
|
|
|
|
|
}
|
2021-04-26 16:42:01 +02:00
|
|
|
|
|
2021-09-27 13:41:50 +02:00
|
|
|
|
if (wbytes < 0)
|
|
|
|
|
{
|
|
|
|
|
// Hard error...
|
|
|
|
|
_pdfioFileError(pdf, "Unable to write to file - %s", strerror(errno));
|
|
|
|
|
return (false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bufptr += wbytes;
|
|
|
|
|
bytes -= (size_t)wbytes;
|
|
|
|
|
}
|
2021-04-26 16:42:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (true);
|
|
|
|
|
}
|