Save work.

This commit is contained in:
Michael R Sweet 2021-04-27 21:22:34 -04:00
parent 11588ce2f5
commit e2e2192ea9
No known key found for this signature in database
GPG Key ID: 999559A027815955
10 changed files with 672 additions and 113 deletions

6
TODO.md Normal file
View File

@ -0,0 +1,6 @@
To-Do List
==========
- Binary data/strings: needed for certain values, particular for the File ID
and user/owner passwords
- Copy methods for array, dict, object, page, value

View File

@ -14,19 +14,6 @@
#include "pdfio-private.h" #include "pdfio-private.h"
//
// Array structure
//
struct _pdfio_array_s
{
pdfio_file_t *pdf; // PDF file
size_t num_values, // Number of values in use
alloc_values; // Number of allocated values
_pdfio_value_t *values; // Array of values
};
// //
// Local functions... // Local functions...
// //
@ -167,6 +154,21 @@ pdfioArrayAppendString(
} }
//
// 'pdfioArrayCopy()' - Copy an array.
//
pdfio_array_t * // O - New array or `NULL` on error
pdfioArrayCopy(pdfio_file_t *pdf, // I - PDF file
pdfio_array_t *a) // I - Original array
{
// TODO: Implement me
(void)pdf;
(void)a;
return (NULL);
}
// //
// 'pdfioArrayCreate()' - Create an empty array. // 'pdfioArrayCreate()' - Create an empty array.
// //
@ -365,6 +367,34 @@ _pdfioArrayGetValue(pdfio_array_t *a, // I - Array
} }
//
// '_pdfioArrayWrite()' - Write an array to a PDF file.
//
bool // O - `true` on success, `false` otherwise
_pdfioArrayWrite(pdfio_array_t *a) // I - Array
{
pdfio_file_t *pdf = a->pdf; // PDF file
size_t i; // Looping var
_pdfio_value_t *v; // Current value
// Arrays are surrounded by square brackets ([ ... ])
if (!_pdfioFilePuts(pdf, "["))
return (false);
// Write each value...
for (i = a->num_values, v = a->values; i > 0; i --, v ++)
{
if (!_pdfioValueWrite(pdf, v))
return (false);
}
// Closing bracket...
return (_pdfioFilePuts(pdf, "]"));
}
// //
// 'append_value()' - Append a value. // 'append_value()' - Append a value.
// //

View File

@ -65,6 +65,26 @@ _pdfioFileError(pdfio_file_t *pdf, // I - PDF file
} }
//
// '_pdfioFileFlush()' - Flush any pending write data.
//
bool // O - `true` on success, `false` on failure
_pdfioFileFlush(pdfio_file_t *pdf) // I - PDF file
{
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;
pdf->bufptr = pdf->buffer;
}
return (true);
}
// //
// '_pdfioFileGetChar()' - Get a character from a PDF file. // '_pdfioFileGetChar()' - Get a character from a PDF file.
// //
@ -85,6 +105,42 @@ _pdfioFileGetChar(pdfio_file_t *pdf) // I - PDF file
} }
//
// '_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)));
}
// //
// '_pdfioFileRead()' - Read from a PDF file. // '_pdfioFileRead()' - Read from a PDF file.
// //
@ -152,7 +208,7 @@ _pdfioFileSeek(pdfio_file_t *pdf, // I - PDF file
whence = SEEK_SET; whence = SEEK_SET;
} }
if (pdf->mode == PDFIO_MODE_READ) if (pdf->mode == _PDFIO_MODE_READ)
{ {
// Reading, see if we already have the data we need... // Reading, see if we already have the data we need...
if (whence != SEEK_END && offset >= pdf->bufpos && offset < (pdf->bufpos + pdf->bufend - pdf->buffer)) if (whence != SEEK_END && offset >= pdf->bufpos && offset < (pdf->bufpos + pdf->bufend - pdf->buffer))
@ -217,16 +273,9 @@ _pdfioFileWrite(pdfio_file_t *pdf, // I - PDF file
if (bytes > (size_t)(pdf->bufend - pdf->bufptr)) if (bytes > (size_t)(pdf->bufend - pdf->bufptr))
{ {
// No room, flush any current data... // No room, flush any current data...
if (pdf->bufptr > pdf->buffer) if (!_pdfioFileFlush(pdf))
{
if (!write_buffer(pdf, pdf->buffer, (size_t)(pdf->bufptr - pdf->buffer)))
return (false); return (false);
pdf->bufpos += pdf->bufptr - pdf->buffer;
}
pdf->bufptr = pdf->buffer;
if (bytes >= sizeof(pdf->buffer)) if (bytes >= sizeof(pdf->buffer))
{ {
// Write directly... // Write directly...

View File

@ -14,25 +14,6 @@
#include "pdfio-private.h" #include "pdfio-private.h"
//
// Dictionary structures
//
typedef struct _pdfio_pair_s // Key/value pair
{
const char *key; // Key string
_pdfio_value_t value; // Value
} _pdfio_pair_t;
struct _pdfio_dict_s
{
pdfio_file_t *pdf; // PDF file
size_t num_pairs, // Number of pairs in use
alloc_pairs; // Number of allocated pairs
_pdfio_pair_t *pairs; // Array of pairs
};
// //
// Local functions... // Local functions...
// //
@ -40,6 +21,21 @@ struct _pdfio_dict_s
static int compare_pairs(_pdfio_pair_t *a, _pdfio_pair_t *b); static int compare_pairs(_pdfio_pair_t *a, _pdfio_pair_t *b);
//
// 'pdfioDictCopy()' - Copy a dictionary to a PDF file.
//
pdfio_dict_t * // O - New dictionary
pdfioDictCopy(pdfio_file_t *pdf, // I - PDF file
pdfio_dict_t *dict) // I - Original dictionary
{
// TODO: Implement me
(void)pdf;
(void)dict;
return (NULL);
}
// //
// 'pdfioDictCreate()' - Create a dictionary to hold key/value pairs. // 'pdfioDictCreate()' - Create a dictionary to hold key/value pairs.
// //
@ -531,6 +527,48 @@ _pdfioDictSetValue(
} }
//
// '_pdfioDictWrite()' - Write a dictionary to a PDF file.
//
bool // O - `true` on success, `false` on failure
_pdfioDictWrite(pdfio_dict_t *dict, // I - Dictionary
off_t *length) // I - Offset to length value
{
pdfio_file_t *pdf = dict->pdf; // PDF file
size_t i; // Looping var
_pdfio_pair_t *pair; // Current key/value pair
if (length)
*length = 0;
// Dictionaries are bounded by "<<" and ">>"...
if (!_pdfioFilePuts(pdf, "<<"))
return (false);
// Write all of the key/value pairs...
for (i = dict->num_pairs, pair = dict->pairs; i > 0; i --, pair ++)
{
if (!_pdfioFilePrintf(pdf, "/%s", pair->key))
return (false);
if (length && !strcmp(pair->key, "Length"))
{
// Writing an object dictionary with an undefined length
*length = _pdfioFileTell(pdf);
if (!_pdfioFilePuts(pdf, " 999999999"))
return (false);
}
else if (!_pdfioValueWrite(pdf, &pair->value))
return (false);
}
// Close it up...
return (_pdfioFilePuts(pdf, ">>"));
}
// //
// 'compare_pairs()' - Compare the keys for two pairs. // 'compare_pairs()' - Compare the keys for two pairs.
// //

View File

@ -12,95 +12,348 @@
// //
#include "pdfio-private.h" #include "pdfio-private.h"
#ifndef O_BINARY
# define O_BINARY 0
#endif // !O_BINARY
// //
// '()' - . // Local functions...
// //
bool pdfioFileClose(pdfio_file_t *pdf) static bool write_trailer(pdfio_file_t *pdf);
//
// 'pdfioFileClose()' - Close a PDF file and free all memory used for it.
//
bool // O - `true` on success and `false` on failure
pdfioFileClose(pdfio_file_t *pdf) // I - PDF file
{ {
bool ret = true; // Return value
size_t i; // Looping var
// Range check input
if (!pdf)
return (false);
// Close the file itself...
if (pdf->mode == _PDFIO_MODE_WRITE)
ret = write_trailer(pdf);
if (close(pdf->fd) < 0)
ret = false;
// Free all data...
free(pdf->filename);
free(pdf->version);
for (i = 0; i < pdf->num_arrays; i ++)
_pdfioArrayDelete(pdf->arrays[i]);
free(pdf->arrays);
for (i = 0; i < pdf->num_dicts; i ++)
_pdfioDictDelete(pdf->dicts[i]);
free(pdf->dicts);
for (i = 0; i < pdf->num_objs; i ++)
_pdfioObjDelete(pdf->objs[i]);
free(pdf->objs);
free(pdf->pages);
for (i = 0; i < pdf->num_strings; i ++)
free(pdf->strings[i]);
free(pdf->strings);
free(pdf);
return (ret);
} }
// //
// '()' - . // 'pdfioFileCreate()' - Create a PDF file.
// //
pdfio_obj_t *pdfioFileCreateObject(pdfio_file_t *file, pdfio_dict_t *dict) pdfio_file_t * // O - PDF file or `NULL` on error
pdfioFileCreate(
const char *filename, // I - Filename
const char *version, // I - PDF version number or `NULL` for default (2.0)
pdfio_error_cb_t error_cb, // I - Error callback or `NULL` for default
void *error_data) // I - Error callback data, if any
{ {
pdfio_file_t *pdf; // PDF file
// Range check input...
if (!filename)
return (NULL);
if (!version)
version = "2.0";
if (!error_cb)
{
error_cb = _pdfioFileDefaultError;
error_data = NULL;
}
// Allocate a PDF file structure...
if ((pdf = (pdfio_file_t *)calloc(1, sizeof(pdfio_file_t))) == NULL)
{
pdfio_file_t temp; // Dummy file
char message[8192]; // Message string
temp.filename = (char *)filename;
snprintf(message, sizeof(message), "Unable to allocate memory for PDF file - %s", strerror(errno));
(error_cb)(&temp, message, error_data);
return (NULL);
}
pdf->filename = strdup(filename);
pdf->version = strdup(version);
pdf->mode = _PDFIO_MODE_WRITE;
pdf->error_cb = error_cb;
pdf->error_data = error_data;
// Create the file...
if ((pdf->fd = open(filename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0666)) < 0)
{
_pdfioFileError(pdf, "Unable to create file - %s", strerror(errno));
free(pdf->filename);
free(pdf->version);
free(pdf);
return (NULL);
}
// Write a standard PDF header...
if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", version))
{
pdfioFileClose(pdf);
unlink(filename);
return (NULL);
}
return (pdf);
} }
// //
// '()' - . // 'pdfioFileCreateObject()' - Create a new object in a PDF file.
// //
pdfio_obj_t *pdfioFileCreatePage(pdfio_t *pdf, pdfio_dict_t *dict) pdfio_obj_t * // O - New object
pdfioFileCreateObject(
pdfio_file_t *pdf, // I - PDF file
pdfio_dict_t *dict) // I - Object dictionary
{ {
pdfio_obj_t *obj; // New object
// Range check input...
if (!pdf || !dict)
{
if (pdf)
_pdfioFileError(pdf, "Missing object dictionary.");
return (NULL);
}
if (dict->pdf != pdf)
dict = pdfioDictCopy(pdf, dict); // Copy dictionary to new PDF
// Allocate memory for the object...
if ((obj = (pdfio_obj_t *)calloc(1, sizeof(pdfio_obj_t))) == NULL)
{
_pdfioFileError(pdf, "Unable to allocate memory for object - %s", strerror(errno));
return (NULL);
}
// Expand the objects array as needed
if (pdf->num_objs >= pdf->alloc_objs)
{
pdfio_obj_t **temp = (pdfio_obj_t **)realloc(pdf->objs, (pdf->alloc_objs + 32) * sizeof(pdfio_obj_t *));
if (!temp)
{
_pdfioFileError(pdf, "Unable to allocate memory for object - %s", strerror(errno));
return (NULL);
}
pdf->objs = temp;
pdf->alloc_objs += 32;
}
pdf->objs[pdf->num_objs ++] = obj;
// Initialize the object...
obj->pdf = pdf;
obj->number = pdf->num_objs;
obj->dict = dict;
obj->offset = _pdfioFileTell(pdf);
// Don't write anything just yet...
return (obj);
} }
// //
// '()' - . // 'pdfioFileCreatePage()' - Create a page in a PDF file.
// //
void _pdfioFileDelete(pdfio_file_t *file) pdfio_obj_t * // O - New object
pdfioFileCreatePage(pdfio_file_t *pdf, // I - PDF file
pdfio_dict_t *dict) // I - Page dictionary
{ {
// TODO: Implement me
(void)pdf;
(void)dict;
return (NULL);
} }
// //
// '()' - . // 'pdfioFileGetName()' - Get a PDF's filename.
// //
const char *pdfioFileGetName(pdfio_file_t *pdf) const char * // O - Filename
pdfioFileGetName(pdfio_file_t *pdf) // I - PDF file
{ {
return (pdf ? pdf->filename : NULL);
} }
// //
// '()' - . // 'pdfioFileGetNumObjects()' - Get the number of objects in a PDF file.
// //
int pdfioFileGetNumObjects(pdfio_file_t *pdf) size_t // O - Number of objects
pdfioFileGetNumObjects(
pdfio_file_t *pdf) // I - PDF file
{ {
return (pdf ? pdf->num_objs : 0);
} }
// //
// '()' - . // 'pdfioFileGetNumPages()' - Get the number of pages in a PDF file.
// //
int pdfioFileGetNumPages(pdfio_file_t *pdf) size_t // O - Number of pages
pdfioFileGetNumPages(pdfio_file_t *pdf) // I - PDF file
{ {
return (pdf ? pdf->num_pages : 0);
} }
// //
// '()' - . // 'pdfioFileGetObject()' - Get an object from a PDF file.
// //
pdfio_obj_t *pdfioFileGetObject(pdfio_file_t *pdf, int number) pdfio_obj_t * // O - Object
pdfioFileGetObject(pdfio_file_t *pdf, // I - PDF file
size_t number) // I - Object number (starting at 1)
{ {
if (!pdf || number < 1 || number > pdf->num_objs)
return (NULL);
else
return (pdf->objs[number - 1]);
} }
// //
// '()' - . // 'pdfioFileGetPage()' - Get a page object from a PDF file.
// //
pdfio_obj_t *pdfioFileGetPage(pdfio_file_t *pdf, int number) pdfio_obj_t * // O - Object
pdfioFileGetPage(pdfio_file_t *pdf, // I - PDF file
size_t number) // I - Page number (starting at 1)
{ {
if (!pdf || number < 1 || number > pdf->num_pages)
return (NULL);
else
return (pdf->pages[number - 1]);
} }
// //
// '()' - . // '()' - Get the PDF version number for a PDF file.
// //
pdfio_file_t *pdfioFileOpen(const char *filename, const char *mode, pdfio_error_cb_t error_cb, void *error_data) const char * // O - Version number or `NULL`
pdfioFileGetVersion(
pdfio_file_t *pdf) // I - PDF file
{ {
return (pdf ? pdf->version : NULL);
} }
//
// 'pdfioFileOpen()' - Open a PDF file for reading.
//
pdfio_file_t * // O - PDF file
pdfioFileOpen(
const char *filename, // I - Filename
pdfio_error_cb_t error_cb, // I - Error callback or `NULL` for default
void *error_data) // I - Error callback data, if any
{
pdfio_file_t *pdf; // PDF file
// Range check input...
if (!filename)
return (NULL);
if (!error_cb)
{
error_cb = _pdfioFileDefaultError;
error_data = NULL;
}
// Allocate a PDF file structure...
if ((pdf = (pdfio_file_t *)calloc(1, sizeof(pdfio_file_t))) == NULL)
{
pdfio_file_t temp; // Dummy file
char message[8192]; // Message string
temp.filename = (char *)filename;
snprintf(message, sizeof(message), "Unable to allocate memory for PDF file - %s", strerror(errno));
(error_cb)(&temp, message, error_data);
return (NULL);
}
pdf->filename = strdup(filename);
pdf->mode = _PDFIO_MODE_READ;
pdf->error_cb = error_cb;
pdf->error_data = error_data;
// Open the file...
if ((pdf->fd = open(filename, O_RDONLY | O_BINARY)) < 0)
{
_pdfioFileError(pdf, "Unable to open file - %s", strerror(errno));
free(pdf->filename);
free(pdf);
return (NULL);
}
// TODO: read header, trailer, and xref table...
return (pdf);
}
//
// 'write_trailer()' - Write the PDF catalog object, xref table, and trailer.
//
static bool // O - `true` on success, `false` on failure
write_trailer(pdfio_file_t *pdf) // I - PDF file
{
// TODO: Write trailer
(void)pdf;
return (false);
}

View File

@ -14,8 +14,6 @@
#include "pdfio-private.h" #include "pdfio-private.h"
// //
// 'pdfioObjClose()' - Close an object, writing any data as needed to the PDF // 'pdfioObjClose()' - Close an object, writing any data as needed to the PDF
// file. // file.
@ -24,6 +22,9 @@
bool // O - `true` on success, `false` on failure bool // O - `true` on success, `false` on failure
pdfioObjClose(pdfio_obj_t *obj) // I - Object pdfioObjClose(pdfio_obj_t *obj) // I - Object
{ {
// TODO: Implement me
(void)obj;
return (false); return (false);
} }
@ -37,6 +38,11 @@ pdfioObjCreateStream(
pdfio_obj_t *obj, // I - Object pdfio_obj_t *obj, // I - Object
pdfio_filter_t filter) // I - Type of compression to apply pdfio_filter_t filter) // I - Type of compression to apply
{ {
// TODO: Implement me
(void)obj;
(void)filter;
return (NULL);
} }
@ -45,7 +51,7 @@ pdfioObjCreateStream(
// //
void void
_pdfioObjDelete(pdfio_object_t *obj) // I - Object _pdfioObjDelete(pdfio_obj_t *obj) // I - Object
{ {
if (obj) if (obj)
pdfioStreamClose(obj->stream); pdfioStreamClose(obj->stream);
@ -69,29 +75,38 @@ pdfioObjGetDict(pdfio_obj_t *obj) // I - Object
// //
// '()' - . // 'pdfioObjGetGeneration()' - Get the object's generation number.
// //
int pdfioObjGetGeneration(pdfio_obj_t *obj) size_t // O - Generation number (0 to 65535)
pdfioObjGetGeneration(pdfio_obj_t *obj) // I - Object
{ {
return (obj ? obj->generation : 0);
} }
// //
// '()' - . // 'pdfioObjGetNumber()' - Get the object's number.
// //
int pdfioObjGetNumber(pdfio_obj_t *obj) size_t // O - Object number (1 to 9999999999)
pdfioObjGetNumber(pdfio_obj_t *obj) // I - Object
{ {
return (obj ? obj->number : 0);
} }
// //
// '()' - . // 'pdfioObjGetType()' - Get an object's type.
// //
const char *pdfioObjGetType(pdfio_obj_t *obj) const char * // O - Object type
pdfioObjGetType(pdfio_obj_t *obj) // I - Object
{ {
// TODO: Implement me
(void)obj;
return (NULL);
} }
@ -102,4 +117,8 @@ const char *pdfioObjGetType(pdfio_obj_t *obj)
pdfio_stream_t * // O - Stream or `NULL` on error pdfio_stream_t * // O - Stream or `NULL` on error
pdfioObjOpenStream(pdfio_obj_t *obj) // I - Object pdfioObjOpenStream(pdfio_obj_t *obj) // I - Object
{ {
// TODO: Implement me
(void)obj;
return (NULL);
} }

View File

@ -15,9 +15,16 @@
// //
// '()' - . // 'pdfioPageCopy()' - Copy a page to a PDF file.
// //
pdfio_obj_t *pdfioPageCopy(pdfio_t *pdf, pdfio_obj_t *src) pdfio_obj_t * // O - Destination page
pdfioPageCopy(pdfio_file_t *pdf, // I - PDF file
pdfio_obj_t *src) // I - Source page
{ {
// TODO: Implement me
(void)pdf;
(void)src;
return (NULL);
} }

View File

@ -56,10 +56,60 @@
// Types and constants... // Types and constants...
// //
typedef enum _pdfio_mode_e // Read/write mode
{
_PDFIO_MODE_READ, // Read a PDF file
_PDFIO_MODE_WRITE // Write a PDF file
} _pdfio_mode_t;
typedef struct _pdfio_value_s // Value structure
{
pdfio_valtype_t type; // Type of value
union
{
pdfio_array_t *array; // Array value
struct
{
unsigned char *data; // Data
size_t datalen; // Length
} binary; // Binary ("Hex String") data
bool boolean; // Boolean value
time_t date; // Date/time value
pdfio_dict_t *dict; // Dictionary value
pdfio_obj_t *obj; // Indirect object (N G obj) value
const char *name; // Name value
float number; // Number value
const char *string; // String value
} value; // Value union
} _pdfio_value_t;
struct _pdfio_array_s
{
pdfio_file_t *pdf; // PDF file
size_t num_values, // Number of values in use
alloc_values; // Number of allocated values
_pdfio_value_t *values; // Array of values
};
typedef struct _pdfio_pair_s // Key/value pair
{
const char *key; // Key string
_pdfio_value_t value; // Value
} _pdfio_pair_t;
struct _pdfio_dict_s
{
pdfio_file_t *pdf; // PDF file
size_t num_pairs, // Number of pairs in use
alloc_pairs; // Number of allocated pairs
_pdfio_pair_t *pairs; // Array of pairs
};
struct _pdfio_file_s // PDF file structure struct _pdfio_file_s // PDF file structure
{ {
const char *filename; // Filename char *filename; // Filename
pdfio_mode_t mode; // Read/write mode char *version; // Version number
_pdfio_mode_t mode; // Read/write mode
pdfio_error_cb_t error_cb; // Error callback pdfio_error_cb_t error_cb; // Error callback
void *error_data; // Data for error callback void *error_data; // Data for error callback
@ -80,6 +130,9 @@ struct _pdfio_file_s // PDF file structure
size_t num_objs, // Number of objects size_t num_objs, // Number of objects
alloc_objs; // Allocated objects alloc_objs; // Allocated objects
pdfio_obj_t **objs; // Objects pdfio_obj_t **objs; // Objects
size_t num_pages, // Number of pages
alloc_pages; // Allocated pages
pdfio_obj_t **pages; // Pages
size_t num_strings, // Number of strings size_t num_strings, // Number of strings
alloc_strings; // Allocated strings alloc_strings; // Allocated strings
char **strings; // Nul-terminated strings char **strings; // Nul-terminated strings
@ -88,10 +141,10 @@ struct _pdfio_file_s // PDF file structure
struct _pdfio_obj_s // Object struct _pdfio_obj_s // Object
{ {
pdfio_file_t *pdf; // PDF file pdfio_file_t *pdf; // PDF file
int number, // Number size_t number, // Number
generation; // Generation generation; // Generation
off_t dict_offset, // Offset to dict in file off_t offset, // Offset to object in file
length_offset, // Offset to /Length in dict length_offset, // Offset to /Length in object dict
stream_offset; // Offset to start of stream in file stream_offset; // Offset to start of stream in file
size_t stream_length; // Length of stream, if any size_t stream_length; // Length of stream, if any
pdfio_dict_t *dict; // Dictionary pdfio_dict_t *dict; // Dictionary
@ -108,22 +161,6 @@ struct _pdfio_stream_s // Stream
z_stream flate; // Flate filter state z_stream flate; // Flate filter state
}; };
typedef struct _pdfio_value_s // Value structure
{
pdfio_valtype_t type; // Type of value
union
{
pdfio_array_t *array; // Array value
bool boolean; // Boolean value
time_t date; // Date/time value
pdfio_dict_t *dict; // Dictionary value
pdfio_obj_t *obj; // Indirect object (N G obj) value
const char *name; // Name value
float number; // Number value
const char *string; // String value
} value; // Value union
} _pdfio_value_t;
// //
// Functions... // Functions...
@ -131,15 +168,19 @@ typedef struct _pdfio_value_s // Value structure
extern void _pdfioArrayDelete(pdfio_array_t *a) PDFIO_INTERNAL; extern void _pdfioArrayDelete(pdfio_array_t *a) PDFIO_INTERNAL;
extern _pdfio_value_t *_pdfioArrayGetValue(pdfio_array_t *a, size_t n) PDFIO_INTERNAL; extern _pdfio_value_t *_pdfioArrayGetValue(pdfio_array_t *a, size_t n) PDFIO_INTERNAL;
extern bool _pdfioArrayWrite(pdfio_array_t *a) PDFIO_INTERNAL;
extern void _pdfioDictDelete(pdfio_dict_t *dict) PDFIO_INTERNAL; extern void _pdfioDictDelete(pdfio_dict_t *dict) PDFIO_INTERNAL;
extern _pdfio_value_t *_pdfioDictGetValue(pdfio_dict_t *dict, const char *key) PDFIO_INTERNAL; extern _pdfio_value_t *_pdfioDictGetValue(pdfio_dict_t *dict, const char *key) PDFIO_INTERNAL;
extern bool _pdfioDictSetValue(pdfio_dict_t *dict, const char *key, _pdfio_value_t *value) PDFIO_INTERNAL; extern bool _pdfioDictSetValue(pdfio_dict_t *dict, const char *key, _pdfio_value_t *value) PDFIO_INTERNAL;
extern bool _pdfioDictWrite(pdfio_dict_t *dict, off_t *length) PDFIO_INTERNAL;
extern bool _pdfioFileDefaultError(pdfio_file_t *pdf, const char *message, void *data) PDFIO_INTERNAL; extern bool _pdfioFileDefaultError(pdfio_file_t *pdf, const char *message, void *data) PDFIO_INTERNAL;
extern void _pdfioFileDelete(pdfio_file_t *pdf) PDFIO_INTERNAL;
extern bool _pdfioFileError(pdfio_file_t *pdf, const char *format, ...) PDFIO_FORMAT(2,3) PDFIO_INTERNAL; extern bool _pdfioFileError(pdfio_file_t *pdf, const char *format, ...) PDFIO_FORMAT(2,3) PDFIO_INTERNAL;
extern bool _pdfioFileFlush(pdfio_file_t *pdf) PDFIO_INTERNAL;
extern int _pdfioFileGetChar(pdfio_file_t *pdf) PDFIO_INTERNAL; extern int _pdfioFileGetChar(pdfio_file_t *pdf) PDFIO_INTERNAL;
extern bool _pdfioFilePrintf(pdfio_file_t *pdf, const char *format, ...) PDFIO_FORMAT(2,3) PDFIO_INTERNAL;
extern bool _pdfioFilePuts(pdfio_file_t *pdf, const char *s) PDFIO_INTERNAL;
extern ssize_t _pdfioFileRead(pdfio_file_t *pdf, char *buffer, size_t bytes) PDFIO_INTERNAL; extern ssize_t _pdfioFileRead(pdfio_file_t *pdf, char *buffer, size_t bytes) PDFIO_INTERNAL;
extern off_t _pdfioFileSeek(pdfio_file_t *pdf, off_t offset, int whence) PDFIO_INTERNAL; extern off_t _pdfioFileSeek(pdfio_file_t *pdf, off_t offset, int whence) PDFIO_INTERNAL;
extern off_t _pdfioFileTell(pdfio_file_t *pdf) PDFIO_INTERNAL; extern off_t _pdfioFileTell(pdfio_file_t *pdf) PDFIO_INTERNAL;
@ -151,7 +192,8 @@ extern void _pdfioStreamDelete(pdfio_stream_t *obj) PDFIO_INTERNAL;
extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) PDFIO_INTERNAL; extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) PDFIO_INTERNAL;
extern _pdfio_value_t *_pdfioValueCopy(pdfio_file_t *pdfdst, _pdfio_value_t *vdst, pdfio_file_t *pdfsrc, _pdfio_value_t *vsrc) PDFIO_INTERNAL;
extern void _pdfioValueDelete(_pdfio_value_t *v) PDFIO_INTERNAL; extern void _pdfioValueDelete(_pdfio_value_t *v) PDFIO_INTERNAL;
extern bool _pdfioValueWrite(pdfio_file_t *pdf, _pdfio_value_t *v) PDFIO_INTERNAL;
#endif // !PDFIO_PRIVATE_H #endif // !PDFIO_PRIVATE_H

View File

@ -15,11 +15,126 @@
// //
// '()' - . // '_pdfioValueCopy()' - Copy a value to a PDF file.
// //
void _pdfioValueDelete(pdfio_value_t *v) _pdfio_value_t *
_pdfioValueCopy(pdfio_file_t *pdfdst, // I - Destination PDF file
_pdfio_value_t *vdst, // I - Destination value
pdfio_file_t *pdfsrc, // I - Source PDF file
_pdfio_value_t *vsrc) // I - Source value
{ {
// TODO: Implement me
(void)pdfdst;
(void)vdst;
(void)pdfsrc;
(void)vsrc;
return (NULL);
} }
//
// '_pdfioValueDelete()' - Free the memory used by a value.
//
void
_pdfioValueDelete(_pdfio_value_t *v) // I - Value
{
// TODO: Implement me
(void)v;
}
//
// '_pdfioValueWrite()' - Write a value to a PDF file.
//
bool // O - `true` on success, `false` on failure
_pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
_pdfio_value_t *v) // I - Value
{
switch (v->type)
{
default :
return (false);
case PDFIO_VALTYPE_ARRAY :
return (_pdfioArrayWrite(v->value.array));
case PDFIO_VALTYPE_BINARY :
// TODO: Implement binary value support
return (false);
case PDFIO_VALTYPE_BOOLEAN :
if (v->value.boolean)
return (_pdfioFilePuts(pdf, " true"));
else
return (_pdfioFilePuts(pdf, " false"));
case PDFIO_VALTYPE_DATE :
// TODO: Implement date value support
break;
case PDFIO_VALTYPE_DICT :
return (_pdfioDictWrite(v->value.dict, NULL));
case PDFIO_VALTYPE_INDIRECT :
return (_pdfioFilePrintf(pdf, " %lu %lu obj", (unsigned long)v->value.obj->number, (unsigned long)v->value.obj->generation));
case PDFIO_VALTYPE_NAME :
return (_pdfioFilePrintf(pdf, "/%s", v->value.name));
case PDFIO_VALTYPE_NULL :
return (_pdfioFilePuts(pdf, " null"));
case PDFIO_VALTYPE_NUMBER :
return (_pdfioFilePrintf(pdf, " %g", v->value.number));
case PDFIO_VALTYPE_STRING :
{
const char *start, // Start of fragment
*end; // End of fragment
if (!_pdfioFilePuts(pdf, "("))
return (false);
// Write a quoted string value...
for (start = v->value.string; *start; start = end)
{
// Find the next character that needs to be quoted...
for (end = start; *end; end ++)
{
if (*end == '\\' || *end == ')' || (*end & 255) < ' ')
break;
}
if (end > start)
{
// Write unquoted (safe) characters...
if (!_pdfioFileWrite(pdf, start, (size_t)(end - start)))
return (false);
}
if (*end)
{
// Quote this character...
bool success; // Did the write work?
if (*end == '\\' || *end == ')')
success = _pdfioFilePrintf(pdf, "\\%c", *end);
else
success = _pdfioFilePrintf(pdf, "\\%03o", *end);
if (!success)
return (false);
end ++;
}
}
return (_pdfioFilePuts(pdf, ")"));
}
}
return (false);
}

30
pdfio.h
View File

@ -60,11 +60,6 @@ typedef enum pdfio_filter_e // Compression/decompression filters for streams
PDFIO_FILTER_NONE, // No filter PDFIO_FILTER_NONE, // No filter
PDFIO_FILTER_FLATE // Flate filter PDFIO_FILTER_FLATE // Flate filter
} pdfio_filter_t; } pdfio_filter_t;
typedef enum pdfio_mode_e // Read/write mode
{
PDFIO_MODE_READ, // Read a PDF file
PDFIO_MODE_WRITE // Write a PDF file
} pdfio_mode_t;
typedef struct _pdfio_obj_s pdfio_obj_t;// Numbered object in PDF file typedef struct _pdfio_obj_s pdfio_obj_t;// Numbered object in PDF file
typedef struct pdfio_rect_s // PDF rectangle typedef struct pdfio_rect_s // PDF rectangle
{ {
@ -79,6 +74,7 @@ typedef enum pdfio_valtype_e // PDF value types
{ {
PDFIO_VALTYPE_NONE, // No value, not set PDFIO_VALTYPE_NONE, // No value, not set
PDFIO_VALTYPE_ARRAY, // Array PDFIO_VALTYPE_ARRAY, // Array
PDFIO_VALTYPE_BINARY, // Binary data
PDFIO_VALTYPE_BOOLEAN, // Boolean PDFIO_VALTYPE_BOOLEAN, // Boolean
PDFIO_VALTYPE_DATE, // Date/time PDFIO_VALTYPE_DATE, // Date/time
PDFIO_VALTYPE_DICT, // Dictionary PDFIO_VALTYPE_DICT, // Dictionary
@ -103,7 +99,8 @@ extern bool pdfioArrayAppendName(pdfio_array_t *a, const char *value) PDFIO_PUB
extern bool pdfioArrayAppendNumber(pdfio_array_t *a, float value) PDFIO_PUBLIC; extern bool pdfioArrayAppendNumber(pdfio_array_t *a, float value) PDFIO_PUBLIC;
extern bool pdfioArrayAppendObject(pdfio_array_t *a, pdfio_obj_t *value) PDFIO_PUBLIC; extern bool pdfioArrayAppendObject(pdfio_array_t *a, pdfio_obj_t *value) PDFIO_PUBLIC;
extern bool pdfioArrayAppendString(pdfio_array_t *a, const char *value) PDFIO_PUBLIC; extern bool pdfioArrayAppendString(pdfio_array_t *a, const char *value) PDFIO_PUBLIC;
extern pdfio_array_t *pdfioArrayCreate(pdfio_file_t *file) PDFIO_PUBLIC; extern pdfio_array_t *pdfioArrayCopy(pdfio_file_t *pdf, pdfio_array_t *a) PDFIO_PUBLIC;
extern pdfio_array_t *pdfioArrayCreate(pdfio_file_t *pdf) PDFIO_PUBLIC;
extern pdfio_array_t *pdfioArrayGetArray(pdfio_array_t *a, size_t n) PDFIO_PUBLIC; extern pdfio_array_t *pdfioArrayGetArray(pdfio_array_t *a, size_t n) PDFIO_PUBLIC;
extern bool pdfioArrayGetBoolean(pdfio_array_t *a, size_t n) PDFIO_PUBLIC; extern bool pdfioArrayGetBoolean(pdfio_array_t *a, size_t n) PDFIO_PUBLIC;
extern pdfio_dict_t *pdfioArrayGetDict(pdfio_array_t *a, size_t n) PDFIO_PUBLIC; extern pdfio_dict_t *pdfioArrayGetDict(pdfio_array_t *a, size_t n) PDFIO_PUBLIC;
@ -114,7 +111,8 @@ extern size_t pdfioArrayGetSize(pdfio_array_t *a) PDFIO_PUBLIC;
extern const char *pdfioArrayGetString(pdfio_array_t *a, size_t n) PDFIO_PUBLIC; extern const char *pdfioArrayGetString(pdfio_array_t *a, size_t n) PDFIO_PUBLIC;
extern pdfio_valtype_t pdfioArrayGetType(pdfio_array_t *a, size_t n) PDFIO_PUBLIC; extern pdfio_valtype_t pdfioArrayGetType(pdfio_array_t *a, size_t n) PDFIO_PUBLIC;
extern pdfio_dict_t *pdfioDictCreate(pdfio_file_t *file) PDFIO_PUBLIC; extern pdfio_dict_t *pdfioDictCopy(pdfio_file_t *pdf, pdfio_dict_t *dict) PDFIO_PUBLIC;
extern pdfio_dict_t *pdfioDictCreate(pdfio_file_t *pdf) PDFIO_PUBLIC;
extern pdfio_array_t *pdfioDictGetArray(pdfio_dict_t *dict, const char *name) PDFIO_PUBLIC; extern pdfio_array_t *pdfioDictGetArray(pdfio_dict_t *dict, const char *name) PDFIO_PUBLIC;
extern bool pdfioDictGetBoolean(pdfio_dict_t *dict, const char *name) PDFIO_PUBLIC; extern bool pdfioDictGetBoolean(pdfio_dict_t *dict, const char *name) PDFIO_PUBLIC;
extern pdfio_dict_t *pdfioDictGetDict(pdfio_dict_t *dict, const char *name) PDFIO_PUBLIC; extern pdfio_dict_t *pdfioDictGetDict(pdfio_dict_t *dict, const char *name) PDFIO_PUBLIC;
@ -136,20 +134,22 @@ extern bool pdfioDictSetString(pdfio_dict_t *dict, const char *name, const char
extern bool pdfioDictSetStringf(pdfio_dict_t *dict, const char *name, const char *format, ...) PDFIO_PUBLIC PDFIO_FORMAT(3,4); extern bool pdfioDictSetStringf(pdfio_dict_t *dict, const char *name, const char *format, ...) PDFIO_PUBLIC PDFIO_FORMAT(3,4);
extern bool pdfioFileClose(pdfio_file_t *pdf) PDFIO_PUBLIC; extern bool pdfioFileClose(pdfio_file_t *pdf) PDFIO_PUBLIC;
extern pdfio_obj_t *pdfioFileCreateObject(pdfio_file_t *file, pdfio_dict_t *dict) PDFIO_PUBLIC; extern pdfio_file_t *pdfioFileCreate(const char *filename, const char *version, pdfio_error_cb_t error_cb, void *error_data) PDFIO_PUBLIC;
extern pdfio_obj_t *pdfioFileCreateObject(pdfio_file_t *pdf, pdfio_dict_t *dict) PDFIO_PUBLIC;
extern pdfio_obj_t *pdfioFileCreatePage(pdfio_file_t *pdf, pdfio_dict_t *dict) PDFIO_PUBLIC; extern pdfio_obj_t *pdfioFileCreatePage(pdfio_file_t *pdf, pdfio_dict_t *dict) PDFIO_PUBLIC;
extern const char *pdfioFileGetName(pdfio_file_t *pdf) PDFIO_PUBLIC; extern const char *pdfioFileGetName(pdfio_file_t *pdf) PDFIO_PUBLIC;
extern unsigned pdfioFileGetNumObjects(pdfio_file_t *pdf) PDFIO_PUBLIC; extern size_t pdfioFileGetNumObjects(pdfio_file_t *pdf) PDFIO_PUBLIC;
extern unsigned pdfioFileGetNumPages(pdfio_file_t *pdf) PDFIO_PUBLIC; extern size_t pdfioFileGetNumPages(pdfio_file_t *pdf) PDFIO_PUBLIC;
extern pdfio_obj_t *pdfioFileGetObject(pdfio_file_t *pdf, unsigned number) PDFIO_PUBLIC; extern pdfio_obj_t *pdfioFileGetObject(pdfio_file_t *pdf, size_t number) PDFIO_PUBLIC;
extern pdfio_obj_t *pdfioFileGetPage(pdfio_file_t *pdf, unsigned number) PDFIO_PUBLIC; extern pdfio_obj_t *pdfioFileGetPage(pdfio_file_t *pdf, size_t number) PDFIO_PUBLIC;
extern pdfio_file_t *pdfioFileOpen(const char *filename, pdfio_mode_t mode, pdfio_error_cb_t error_cb, void *error_data) PDFIO_PUBLIC; extern const char *pdfioFileGetVersion(pdfio_file_t *pdf) PDFIO_PUBLIC;
extern pdfio_file_t *pdfioFileOpen(const char *filename, pdfio_error_cb_t error_cb, void *error_data) PDFIO_PUBLIC;
extern bool pdfioObjClose(pdfio_obj_t *obj) PDFIO_PUBLIC; extern bool pdfioObjClose(pdfio_obj_t *obj) PDFIO_PUBLIC;
extern pdfio_stream_t *pdfioObjCreateStream(pdfio_obj_t *obj, pdfio_filter_t compression) PDFIO_PUBLIC; extern pdfio_stream_t *pdfioObjCreateStream(pdfio_obj_t *obj, pdfio_filter_t compression) PDFIO_PUBLIC;
extern pdfio_dict_t *pdfioObjGetDict(pdfio_obj_t *obj) PDFIO_PUBLIC; extern pdfio_dict_t *pdfioObjGetDict(pdfio_obj_t *obj) PDFIO_PUBLIC;
extern unsigned pdfioObjGetGeneration(pdfio_obj_t *obj) PDFIO_PUBLIC; extern size_t pdfioObjGetGeneration(pdfio_obj_t *obj) PDFIO_PUBLIC;
extern unsigned pdfioObjGetNumber(pdfio_obj_t *obj) PDFIO_PUBLIC; extern size_t pdfioObjGetNumber(pdfio_obj_t *obj) PDFIO_PUBLIC;
extern const char *pdfioObjGetType(pdfio_obj_t *obj) PDFIO_PUBLIC; extern const char *pdfioObjGetType(pdfio_obj_t *obj) PDFIO_PUBLIC;
extern pdfio_stream_t *pdfioObjOpenStream(pdfio_obj_t *obj) PDFIO_PUBLIC; extern pdfio_stream_t *pdfioObjOpenStream(pdfio_obj_t *obj) PDFIO_PUBLIC;