From 98c48e66c25efd23a6414c369d05bd37a06f355e Mon Sep 17 00:00:00 2001 From: Michael R Sweet Date: Sun, 25 Apr 2021 11:28:56 -0400 Subject: [PATCH] Add string array, have the pdfio_file_t object manage allocated data. --- Makefile | 1 + pdfio-array.c | 69 ++++++++++++++++++++++++- pdfio-private.h | 47 ++++++++++++++--- pdfio-string.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ pdfio.h | 48 ++++++++++-------- 5 files changed, 268 insertions(+), 29 deletions(-) create mode 100644 pdfio-string.c diff --git a/Makefile b/Makefile index 5675ced..7f3adf3 100644 --- a/Makefile +++ b/Makefile @@ -44,6 +44,7 @@ LIBOBJS = \ pdfio-object.o \ pdfio-page.o \ pdfio-stream.o \ + pdfio-string.o \ pdfio-value.o OBJS = \ $(LIBOBJS) \ diff --git a/pdfio-array.c b/pdfio-array.c index 8b25011..90f3cc9 100644 --- a/pdfio-array.c +++ b/pdfio-array.c @@ -15,11 +15,40 @@ // -// '()' - . +// Array structure // -bool pdfioArrayAppendArray(pdfio_array_t *a, pdfio_array_t *value) +struct _pdfio_array_s { + size_t num_values, // Number of values in use + alloc_values; // Number of allocated values + _pdfio_value_t *values; // Array of values +}; + + +// +// Local functions... +// + +static bool append_value(pdfio_array_t *a, _pdfio_value_t *v); + + +// +// 'pdfioArrayAppendArray()' - Add an array value to an array. +// + +bool // O - `true` on success, `false` on failure +pdfioArrayAppendArray( + pdfio_array_t *a, // I - Array + pdfio_array_t *value) // I - Value +{ + _pdfio_value_t v; // Value for array + + + v.type = PDFIO_VALTYPE_ARRAY; + v.value.array = value; + + return (append_value(a, &v)); } @@ -176,3 +205,39 @@ pdfio_valtype_t pdfioArrayGetType(pdfio_array_t *a, int n) } +// +// '()' - . +// + +_pdfio_value_t * +_pdfioArrayGetValue(pdfio_array_t *a, int n) +{ +} + + +// +// 'append_value()' - Append a value. +// + +static bool // O - `true` on success, `false` otherwise +append_value(pdfio_array_t *a, // I - Array + _pdfio_value_t *v) // I - Value +{ + if (!a) + return (false); + + if (a->num_values >= a->alloc_values) + { + _pdfio_value_t *temp = (_pdfio_value_t *)realloc(a->values, (a->alloc_values + 16) * sizeof(_pdfio_value_t)); + + if (!temp) + return (false); + + a->values = temp; + a->alloc_values += 16; + } + + a->values[a->num_values ++] = *v; + + return (true); +} diff --git a/pdfio-private.h b/pdfio-private.h index dd823a8..ceb0a1b 100644 --- a/pdfio-private.h +++ b/pdfio-private.h @@ -15,6 +15,11 @@ // # include "pdfio.h" +# include +# include +# include +# include +# include // @@ -49,6 +54,34 @@ // Types and constants... // +struct _pdfio_file_s // PDF file structure +{ + int fd; // File descriptor + + // Allocated data elements + size_t num_arrays, // Number of arrays + alloc_arrays; // Allocated arrays + pdfio_array_t **arrays; // Arrays + size_t num_dicts, // Number of dictionaries + alloc_dicts; // Allocated dictionaries + pdfio_dict_t **dicts; // Dictionaries + size_t num_objs, // Number of objects + alloc_objs; // Allocated objects + pdfio_obj_t **objs; // Objects + size_t num_strings, // Number of strings + alloc_strings; // Allocated strings + char **strings; // Nul-terminated strings +}; + +struct _pdfio_obj_s // Object +{ + int number, // Number + generation; // Generation + off_t offset; // Offset in file + size_t length; // Length + pdfio_dict_t *dict; // Dictionary +}; + typedef struct _pdfio_value_s // Value structure { pdfio_valtype_t type; // Type of value @@ -70,12 +103,14 @@ typedef struct _pdfio_value_s // Value structure // Functions... // -extern void _pdfioArrayDelete(pdfio_array_t *a) PDFIO_INTERNAL; -extern void _pdfioDictDelete(pdfio_dict_t *dict) PDFIO_INTERNAL; -extern void _pdfioFileDelete(pdfio_file_t *file) PDFIO_INTERNAL; -extern void _pdfioObjDelete(pdfio_object_t *obj) PDFIO_INTERNAL; -extern void _pdfioStreamDelete(pdfio_stream_t *obj) PDFIO_INTERNAL; -extern void _pdfioValueDelete(pdfio_value_t *v) 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 void _pdfioDictDelete(pdfio_dict_t *dict) PDFIO_INTERNAL; +extern void _pdfioFileDelete(pdfio_file_t *file) PDFIO_INTERNAL; +extern void _pdfioObjDelete(pdfio_obj_t *obj) PDFIO_INTERNAL; +extern void _pdfioStreamDelete(pdfio_stream_t *obj) PDFIO_INTERNAL; +extern bool _pdfioStringIsAllocated(pdfio_file_t *pdf, const char *s) PDFIO_INTERNAL; +extern void _pdfioValueDelete(_pdfio_value_t *v) PDFIO_INTERNAL; #endif // !PDFIO_PRIVATE_H diff --git a/pdfio-string.c b/pdfio-string.c new file mode 100644 index 0000000..c287b68 --- /dev/null +++ b/pdfio-string.c @@ -0,0 +1,132 @@ +// +// PDF dictionary 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" + + +// +// Local functions... +// + +static int compare_strings(char **a, char **b); + + +// +// 'pdfioStringCreate()' - Create a literal string. +// +// This function creates a literal string associated with the PDF file +// "pwg". The "s" string points to a nul-terminated C string. +// +// `NULL` is returned on error, otherwise a `char *` that is valid until +// `pdfioFileClose` is called. +// + +char * // O - New string or `NULL` on error +pdfioStringCreate( + pdfio_file_t *pdf, // I - PDF file + const char *s) // I - Nul-terminated string +{ + char *news; // New string + + + // Range check input... + if (!pdf || !s) + return (NULL); + + // See if the string has already been added... + if (pdf->num_strings > 0 && (news = (char *)bsearch(&s, pdf->strings, pdf->num_strings, sizeof(char *), (int (*)(const void *, const void *))compare_strings)) != NULL) + return (news); + + // Not already added, so add it... + if ((news = strdup(s)) == NULL) + return (NULL); + + if (pdf->num_strings >= pdf->alloc_strings) + { + // Expand the string array... + char **temp = realloc(pdf->strings, (pdf->alloc_strings + 32) * sizeof(char *)); + + if (!temp) + return (NULL); + + pdf->strings = temp; + pdf->alloc_strings += 32; + } + + // TODO: Change to insertion sort as needed... + pdf->strings[pdf->num_strings ++] = news; + + if (pdf->num_strings > 1) + qsort(pdf->strings, pdf->num_strings, sizeof(char *), (int (*)(const void *, const void *))compare_strings); + + return (news); +} + + +// +// 'pdfioStringCreatef()' - Create a formatted string. +// +// This function creates a formatted string associated with the PDF file +// "pwg". The "format" string contains `printf`-style format characters. +// +// `NULL` is returned on error, otherwise a `char *` that is valid until +// `pdfioFileClose` is called. +// + +char * // O - New string or `NULL` on error +pdfioStringCreatef( + pdfio_file_t *pdf, // I - PDF file + const char *format, // I - `printf`-style format string + ...) // I - Additional args as needed +{ + char buffer[8192]; // String buffer + va_list ap; // Argument list + + + // Range check input... + if (!pdf || !format) + return (NULL); + + // Format the string... + va_start(ap, format); + vsnprintf(buffer, sizeof(buffer), format, ap); + va_end(ap); + + // Create the string from the buffer... + return (pdfioStringCreate(pdf, buffer)); +} + + +// +// '()' - Check whether a string has been allocated. +// + +bool // O - `true` if allocated, `false` otherwise +_pdfioStringIsAllocated( + pdfio_file_t *pdf, // I - PDF file + const char *s) // I - String +{ + return (pdf->num_strings > 0 && bsearch(&s, pdf->strings, pdf->num_strings, sizeof(char *), (int (*)(const void *, const void *))compare_strings) != NULL); +} + + +// +// 'compare_strings()' - Compare two strings. +// + +static int // O - Result of comparison +compare_strings(char **a, // I - First string + char **b) // I - Second string +{ + return (strcmp(*a, *b)); +} diff --git a/pdfio.h b/pdfio.h index 6125627..1cad71a 100644 --- a/pdfio.h +++ b/pdfio.h @@ -14,7 +14,10 @@ // Include necessary headers... // +# include +# include # include +# include # include @@ -53,10 +56,10 @@ typedef enum pdfio_compress_e // Types of compression to use when writing strea } pdfio_compress_t; typedef struct _pdfio_dict_s pdfio_dict_t; // Key/value dictionary -typedef bool (pdfio_error_cb_t)(pdfio_t *pdf, const char *message, void *data); - // Error callback typedef struct _pdfio_file_s pdfio_file_t; // PDF file +typedef bool (pdfio_error_cb_t)(pdfio_file_t *pdf, const char *message, void *data); + // Error callback typedef struct _pdfio_obj_s pdfio_obj_t;// Numbered object in PDF file typedef struct pdfio_rect_s // PDF rectangle { @@ -89,22 +92,22 @@ typedef struct _pdfio_value_s pdf_value_t; // extern bool pdfioArrayAppendArray(pdfio_array_t *a, pdfio_array_t *value) PDFIO_PUBLIC; -extern bool pdfioArrayAppendBoolean(pdfio_array_t *a, boolean value) PDFIO_PUBLIC; +extern bool pdfioArrayAppendBoolean(pdfio_array_t *a, bool value) PDFIO_PUBLIC; extern bool pdfioArrayAppendDict(pdfio_array_t *a, pdfio_dict_t *value) PDFIO_PUBLIC; extern bool pdfioArrayAppendName(pdfio_array_t *a, const char *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 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 *pdfioArrayGetArray(pdfio_array_t *a, int n) PDFIO_PUBLIC; -extern bool pdfioArrayGetBoolean(pdfio_array_t *a, int n) PDFIO_PUBLIC; -extern pdfio_dict_t *pdfioArrayGetDict(pdfio_array_t *a, int n) PDFIO_PUBLIC; -extern const char *pdfioArrayGetName(pdfio_array_t *a, int n) PDFIO_PUBLIC; -extern float pdfioArrayGetNumber(pdfio_array_t *a, int n) PDFIO_PUBLIC; -extern pdfio_obj_t *pdfioArrayGetObject(pdfio_array_t *a, int n) PDFIO_PUBLIC; -extern int pdfioArrayGetSize(pdfio_array_t *a) PDFIO_PUBLIC; -extern const char *pdfioArrayGetString(pdfio_array_t *a, int n) PDFIO_PUBLIC; -extern pdfio_valtype_t pdfioArrayGetType(pdfio_array_t *a, int 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 pdfio_dict_t *pdfioArrayGetDict(pdfio_array_t *a, size_t n) PDFIO_PUBLIC; +extern const char *pdfioArrayGetName(pdfio_array_t *a, size_t n) PDFIO_PUBLIC; +extern float pdfioArrayGetNumber(pdfio_array_t *a, size_t n) PDFIO_PUBLIC; +extern pdfio_obj_t *pdfioArrayGetObject(pdfio_array_t *a, size_t n) PDFIO_PUBLIC; +extern size_t pdfioArrayGetSize(pdfio_array_t *a) 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_dict_t *pdfioDictCreate(pdfio_file_t *file) PDFIO_PUBLIC; extern pdfio_array_t *pdfioDictGetArray(pdfio_dict_t *dict, const char *name) PDFIO_PUBLIC; @@ -129,23 +132,23 @@ extern bool pdfioDictSetStringf(pdfio_dict_t *dict, const char *name, const cha 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_obj_t *pdfioFileCreatePage(pdfio_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 int pdfioFileGetNumObjects(pdfio_file_t *pdf) PDFIO_PUBLIC; -extern int pdfioFileGetNumPages(pdfio_file_t *pdf) PDFIO_PUBLIC; -extern pdfio_obj_t *pdfioFileGetObject(pdfio_file_t *pdf, int number) PDFIO_PUBLIC; -extern pdfio_obj_t *pdfioFileGetPage(pdfio_file_t *pdf, int number) PDFIO_PUBLIC; +extern unsigned pdfioFileGetNumObjects(pdfio_file_t *pdf) PDFIO_PUBLIC; +extern unsigned pdfioFileGetNumPages(pdfio_file_t *pdf) PDFIO_PUBLIC; +extern pdfio_obj_t *pdfioFileGetObject(pdfio_file_t *pdf, unsigned number) PDFIO_PUBLIC; +extern pdfio_obj_t *pdfioFileGetPage(pdfio_file_t *pdf, unsigned number) PDFIO_PUBLIC; extern pdfio_file_t *pdfioFileOpen(const char *filename, const char *mode, pdfio_error_cb_t error_cb, void *error_data) PDFIO_PUBLIC; -extern bool pdfioObjClose(pdfio_object_t *obj) PDFIO_PUBLIC; +extern bool pdfioObjClose(pdfio_obj_t *obj) PDFIO_PUBLIC; extern pdfio_stream_t *pdfioObjCreateStream(pdfio_obj_t *obj, pdfio_compress_t compression) PDFIO_PUBLIC; extern pdfio_dict_t *pdfioObjGetDict(pdfio_obj_t *obj) PDFIO_PUBLIC; -extern int pdfioObjGetGeneration(pdfio_obj_t *obj) PDFIO_PUBLIC; -extern int pdfioObjGetNumber(pdfio_obj_t *obj) PDFIO_PUBLIC; +extern unsigned pdfioObjGetGeneration(pdfio_obj_t *obj) PDFIO_PUBLIC; +extern unsigned pdfioObjGetNumber(pdfio_obj_t *obj) PDFIO_PUBLIC; extern pdfio_stream_t *pdfioObjGetStream(pdfio_obj_t *obj) PDFIO_PUBLIC; extern const char *pdfioObjGetType(pdfio_obj_t *obj) PDFIO_PUBLIC; -extern pdfio_obj_t *pdfioPageCopy(pdfio_t *pdf, pdfio_obj_t *src) PDFIO_PUBLIC; +extern pdfio_obj_t *pdfioPageCopy(pdfio_file_t *pdf, pdfio_obj_t *src) PDFIO_PUBLIC; extern bool pdfioStreamClose(pdfio_stream_t *st) PDFIO_PUBLIC; extern bool pdfioStreamPrintf(pdfio_stream_t *st, const char *format, ...) PDFIO_PUBLIC PDFIO_FORMAT(2,3); @@ -153,6 +156,9 @@ extern bool pdfioStreamPuts(pdfio_stream_t *st, const char *s) PDFIO_PUBLIC; extern ssize_t pdfioStreamRead(pdfio_stream_t *st, void *buffer, size_t bytes) PDFIO_PUBLIC; extern bool pdfioStreamWrite(pdfio_stream_t *st, const void *buffer, size_t bytes) PDFIO_PUBLIC; +extern char *pdfioStringCreate(pdfio_file_t *pdf, const char *s) PDFIO_PUBLIC; +extern char *pdfioStringCreatef(pdfio_file_t *pdf, const char *format, ...) PDFIO_FORMAT(2,3) PDFIO_PUBLIC; + // // C++ magic...