Fix output of special characters in name values (Issue #106)

Fix output of special characters in string values (Issue #107)
Fi output of large integers in dictionaries (Issue #108)

Bump version to 1.5.1.
This commit is contained in:
Michael R Sweet 2025-03-24 18:33:24 -04:00
parent 458f366d78
commit cfe91b4ea2
No known key found for this signature in database
GPG Key ID: BE67C75EC81F3244
13 changed files with 229 additions and 96 deletions

View File

@ -1,6 +1,14 @@
Changes in PDFio Changes in PDFio
================ ================
v1.5.1 - YYYY-MM-DD
-------------------
- Fixed output of special characters in name values (Issue #106)
- Fixed output of special characters in string values (Issue #107)
- Fixed output of large integers in dictionaries (Issue #108)
v1.5.0 - 2025-03-06 v1.5.0 - 2025-03-06
------------------- -------------------

24
configure vendored
View File

@ -1,6 +1,6 @@
#! /bin/sh #! /bin/sh
# Guess values for system-dependent variables and create Makefiles. # Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.71 for pdfio 1.5.0. # Generated by GNU Autoconf 2.71 for pdfio 1.5.1.
# #
# Report bugs to <https://github.com/michaelrsweet/pdfio/issues>. # Report bugs to <https://github.com/michaelrsweet/pdfio/issues>.
# #
@ -610,8 +610,8 @@ MAKEFLAGS=
# Identity of this package. # Identity of this package.
PACKAGE_NAME='pdfio' PACKAGE_NAME='pdfio'
PACKAGE_TARNAME='pdfio' PACKAGE_TARNAME='pdfio'
PACKAGE_VERSION='1.5.0' PACKAGE_VERSION='1.5.1'
PACKAGE_STRING='pdfio 1.5.0' PACKAGE_STRING='pdfio 1.5.1'
PACKAGE_BUGREPORT='https://github.com/michaelrsweet/pdfio/issues' PACKAGE_BUGREPORT='https://github.com/michaelrsweet/pdfio/issues'
PACKAGE_URL='https://www.msweet.org/pdfio' PACKAGE_URL='https://www.msweet.org/pdfio'
@ -1295,7 +1295,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing. # Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh. # This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF cat <<_ACEOF
\`configure' configures pdfio 1.5.0 to adapt to many kinds of systems. \`configure' configures pdfio 1.5.1 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]... Usage: $0 [OPTION]... [VAR=VALUE]...
@ -1361,7 +1361,7 @@ fi
if test -n "$ac_init_help"; then if test -n "$ac_init_help"; then
case $ac_init_help in case $ac_init_help in
short | recursive ) echo "Configuration of pdfio 1.5.0:";; short | recursive ) echo "Configuration of pdfio 1.5.1:";;
esac esac
cat <<\_ACEOF cat <<\_ACEOF
@ -1460,7 +1460,7 @@ fi
test -n "$ac_init_help" && exit $ac_status test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then if $ac_init_version; then
cat <<\_ACEOF cat <<\_ACEOF
pdfio configure 1.5.0 pdfio configure 1.5.1
generated by GNU Autoconf 2.71 generated by GNU Autoconf 2.71
Copyright (C) 2021 Free Software Foundation, Inc. Copyright (C) 2021 Free Software Foundation, Inc.
@ -1616,7 +1616,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake. running configure, to aid debugging if configure makes a mistake.
It was created by pdfio $as_me 1.5.0, which was It was created by pdfio $as_me 1.5.1, which was
generated by GNU Autoconf 2.71. Invocation command line was generated by GNU Autoconf 2.71. Invocation command line was
$ $0$ac_configure_args_raw $ $0$ac_configure_args_raw
@ -2372,9 +2372,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
PDFIO_VERSION="1.5.0" PDFIO_VERSION="1.5.1"
PDFIO_VERSION_MAJOR="`echo 1.5.0 | awk -F. '{print $1}'`" PDFIO_VERSION_MAJOR="`echo 1.5.1 | awk -F. '{print $1}'`"
PDFIO_VERSION_MINOR="`echo 1.5.0 | awk -F. '{printf("%d\n",$2);}'`" PDFIO_VERSION_MINOR="`echo 1.5.1 | awk -F. '{printf("%d\n",$2);}'`"
@ -4988,7 +4988,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their # report actual input values of CONFIG_FILES etc. instead of their
# values after options handling. # values after options handling.
ac_log=" ac_log="
This file was extended by pdfio $as_me 1.5.0, which was This file was extended by pdfio $as_me 1.5.1, which was
generated by GNU Autoconf 2.71. Invocation command line was generated by GNU Autoconf 2.71. Invocation command line was
CONFIG_FILES = $CONFIG_FILES CONFIG_FILES = $CONFIG_FILES
@ -5044,7 +5044,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config='$ac_cs_config_escaped' ac_cs_config='$ac_cs_config_escaped'
ac_cs_version="\\ ac_cs_version="\\
pdfio config.status 1.5.0 pdfio config.status 1.5.1
configured by $0, generated by GNU Autoconf 2.71, configured by $0, generated by GNU Autoconf 2.71,
with options \\"\$ac_cs_config\\" with options \\"\$ac_cs_config\\"

View File

@ -21,7 +21,7 @@ AC_PREREQ([2.70])
dnl Package name and version... dnl Package name and version...
AC_INIT([pdfio], [1.5.0], [https://github.com/michaelrsweet/pdfio/issues], [pdfio], [https://www.msweet.org/pdfio]) AC_INIT([pdfio], [1.5.1], [https://github.com/michaelrsweet/pdfio/issues], [pdfio], [https://www.msweet.org/pdfio])
PDFIO_VERSION="AC_PACKAGE_VERSION" PDFIO_VERSION="AC_PACKAGE_VERSION"
PDFIO_VERSION_MAJOR="`echo AC_PACKAGE_VERSION | awk -F. '{print $1}'`" PDFIO_VERSION_MAJOR="`echo AC_PACKAGE_VERSION | awk -F. '{print $1}'`"

View File

@ -476,7 +476,7 @@ pdfioContentDrawImage(
double width, // I - Width of image double width, // I - Width of image
double height) // I - Height of image double height) // I - Height of image
{ {
return (pdfioStreamPrintf(st, "q %.6f 0 0 %.6f %.6f %.6f cm/%s Do Q\n", width, height, x, y, name)); return (pdfioStreamPrintf(st, "q %.6f 0 0 %.6f %.6f %.6f cm%N Do Q\n", width, height, x, y, name));
} }
@ -811,7 +811,7 @@ pdfioContentSetFillColorSpace(
pdfio_stream_t *st, // I - Stream pdfio_stream_t *st, // I - Stream
const char *name) // I - Color space name const char *name) // I - Color space name
{ {
return (pdfioStreamPrintf(st, "/%s cs\n", name)); return (pdfioStreamPrintf(st, "%N cs\n", name));
} }
@ -961,7 +961,7 @@ pdfioContentSetStrokeColorSpace(
pdfio_stream_t *st, // I - Stream pdfio_stream_t *st, // I - Stream
const char *name) // I - Color space name const char *name) // I - Color space name
{ {
return (pdfioStreamPrintf(st, "/%s CS\n", name)); return (pdfioStreamPrintf(st, "%N CS\n", name));
} }
@ -988,7 +988,7 @@ pdfioContentSetTextFont(
const char *name, // I - Font name const char *name, // I - Font name
double size) // I - Font size double size) // I - Font size
{ {
return (pdfioStreamPrintf(st, "/%s %.6f Tf\n", name, size)); return (pdfioStreamPrintf(st, "%N %.6f Tf\n", name, size));
} }

View File

@ -120,10 +120,10 @@ extern bool pdfioContentTextMoveLine(pdfio_stream_t *st, double tx, double ty)
extern bool pdfioContentTextMoveTo(pdfio_stream_t *st, double tx, double ty) _PDFIO_PUBLIC; extern bool pdfioContentTextMoveTo(pdfio_stream_t *st, double tx, double ty) _PDFIO_PUBLIC;
extern bool pdfioContentTextNewLine(pdfio_stream_t *st) _PDFIO_PUBLIC; extern bool pdfioContentTextNewLine(pdfio_stream_t *st) _PDFIO_PUBLIC;
extern bool pdfioContentTextNewLineShow(pdfio_stream_t *st, double ws, double cs, bool unicode, const char *s) _PDFIO_PUBLIC; extern bool pdfioContentTextNewLineShow(pdfio_stream_t *st, double ws, double cs, bool unicode, const char *s) _PDFIO_PUBLIC;
extern bool pdfioContentTextNewLineShowf(pdfio_stream_t *st, double ws, double cs, bool unicode, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(5,6); extern bool pdfioContentTextNewLineShowf(pdfio_stream_t *st, double ws, double cs, bool unicode, const char *format, ...) _PDFIO_PUBLIC;
extern bool pdfioContentTextNextLine(pdfio_stream_t *st) _PDFIO_PUBLIC; extern bool pdfioContentTextNextLine(pdfio_stream_t *st) _PDFIO_PUBLIC;
extern bool pdfioContentTextShow(pdfio_stream_t *st, bool unicode, const char *s) _PDFIO_PUBLIC; extern bool pdfioContentTextShow(pdfio_stream_t *st, bool unicode, const char *s) _PDFIO_PUBLIC;
extern bool pdfioContentTextShowf(pdfio_stream_t *st, bool unicode, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(3,4); extern bool pdfioContentTextShowf(pdfio_stream_t *st, bool unicode, const char *format, ...) _PDFIO_PUBLIC;
extern bool pdfioContentTextShowJustified(pdfio_stream_t *st, bool unicode, size_t num_fragments, const double *offsets, const char * const *fragments) _PDFIO_PUBLIC; extern bool pdfioContentTextShowJustified(pdfio_stream_t *st, bool unicode, size_t num_fragments, const double *offsets, const char * const *fragments) _PDFIO_PUBLIC;
// Resource helpers... // Resource helpers...

View File

@ -1,7 +1,7 @@
// //
// PDF dictionary functions for PDFio. // PDF dictionary functions for PDFio.
// //
// Copyright © 2021-2024 by Michael R Sweet. // Copyright © 2021-2025 by Michael R Sweet.
// //
// Licensed under Apache License v2.0. See the file "LICENSE" for more // Licensed under Apache License v2.0. See the file "LICENSE" for more
// information. // information.
@ -1168,7 +1168,7 @@ _pdfioDictWrite(pdfio_dict_t *dict, // I - Dictionary
// Write all of the key/value pairs... // Write all of the key/value pairs...
for (i = dict->num_pairs, pair = dict->pairs; i > 0; i --, pair ++) for (i = dict->num_pairs, pair = dict->pairs; i > 0; i --, pair ++)
{ {
if (!_pdfioFilePrintf(pdf, "/%s", pair->key)) if (!_pdfioFilePrintf(pdf, "%N", pair->key))
return (false); return (false);
if (length && !strcmp(pair->key, "Length") && pair->value.type == PDFIO_VALTYPE_NUMBER && pair->value.value.number <= 0.0) if (length && !strcmp(pair->key, "Length") && pair->value.type == PDFIO_VALTYPE_NUMBER && pair->value.value.number <= 0.0)

View File

@ -327,6 +327,7 @@ struct _pdfio_stream_s // Stream
// Functions... // Functions...
// //
extern size_t _pdfio_strlcpy(char *dst, const char *src, size_t dstsize) _PDFIO_INTERNAL;
extern double _pdfio_strtod(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL; extern double _pdfio_strtod(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL;
extern ssize_t _pdfio_vsnprintf(pdfio_file_t *pdf, char *buffer, size_t bufsize, const char *format, va_list ap) _PDFIO_INTERNAL; extern ssize_t _pdfio_vsnprintf(pdfio_file_t *pdf, char *buffer, size_t bufsize, const char *format, va_list ap) _PDFIO_INTERNAL;
@ -367,13 +368,13 @@ extern bool _pdfioFileAddPage(pdfio_file_t *pdf, pdfio_obj_t *obj) _PDFIO_INTER
extern bool _pdfioFileConsume(pdfio_file_t *pdf, size_t bytes) _PDFIO_INTERNAL; extern bool _pdfioFileConsume(pdfio_file_t *pdf, size_t bytes) _PDFIO_INTERNAL;
extern pdfio_obj_t *_pdfioFileCreateObj(pdfio_file_t *pdf, pdfio_file_t *srcpdf, _pdfio_value_t *value) _PDFIO_INTERNAL; extern pdfio_obj_t *_pdfioFileCreateObj(pdfio_file_t *pdf, pdfio_file_t *srcpdf, _pdfio_value_t *value) _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 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_INTERNAL;
extern pdfio_obj_t *_pdfioFileFindMappedObj(pdfio_file_t *pdf, pdfio_file_t *src_pdf, size_t src_number) _PDFIO_INTERNAL; extern pdfio_obj_t *_pdfioFileFindMappedObj(pdfio_file_t *pdf, pdfio_file_t *src_pdf, size_t src_number) _PDFIO_INTERNAL;
extern bool _pdfioFileFlush(pdfio_file_t *pdf) _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 _pdfioFileGets(pdfio_file_t *pdf, char *buffer, size_t bufsize) _PDFIO_INTERNAL; extern bool _pdfioFileGets(pdfio_file_t *pdf, char *buffer, size_t bufsize) _PDFIO_INTERNAL;
extern ssize_t _pdfioFilePeek(pdfio_file_t *pdf, void *buffer, size_t bytes) _PDFIO_INTERNAL; extern ssize_t _pdfioFilePeek(pdfio_file_t *pdf, void *buffer, size_t bytes) _PDFIO_INTERNAL;
extern bool _pdfioFilePrintf(pdfio_file_t *pdf, const char *format, ...) _PDFIO_FORMAT(2,3) _PDFIO_INTERNAL; extern bool _pdfioFilePrintf(pdfio_file_t *pdf, const char *format, ...) _PDFIO_INTERNAL;
extern bool _pdfioFilePuts(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL; extern bool _pdfioFilePuts(pdfio_file_t *pdf, const char *s) _PDFIO_INTERNAL;
extern ssize_t _pdfioFileRead(pdfio_file_t *pdf, void *buffer, size_t bytes) _PDFIO_INTERNAL; extern ssize_t _pdfioFileRead(pdfio_file_t *pdf, void *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;

View File

@ -616,7 +616,7 @@ _pdfioStreamOpen(pdfio_obj_t *obj, // I - Object
else else
{ {
// Something else we don't support // Something else we don't support
_pdfioFileError(st->pdf, "Unsupported stream filter '/%s'.", filter); _pdfioFileError(st->pdf, "Unsupported stream filter '%N'.", filter);
goto error; goto error;
} }
} }
@ -689,6 +689,10 @@ pdfioStreamPeek(pdfio_stream_t *st, // I - Stream
// //
// 'pdfioStreamPrintf()' - Write a formatted string to a stream. // 'pdfioStreamPrintf()' - Write a formatted string to a stream.
// //
// This function writes a formatted string to a stream. In addition to the
// standard `printf` format characters, you can use "%N" to format a PDF name
// value ("/Name") and "%S" to format a PDF string ("(String)") value.
//
bool // O - `true` on success, `false` on failure bool // O - `true` on success, `false` on failure
pdfioStreamPrintf( pdfioStreamPrintf(

View File

@ -1,7 +1,7 @@
// //
// PDF string functions for PDFio. // PDF string functions for PDFio.
// //
// Copyright © 2021-2024 by Michael R Sweet. // Copyright © 2021-2025 by Michael R Sweet.
// //
// Licensed under Apache License v2.0. See the file "LICENSE" for more // Licensed under Apache License v2.0. See the file "LICENSE" for more
// information. // information.
@ -17,6 +17,83 @@
static size_t find_string(pdfio_file_t *pdf, const char *s, int *rdiff); static size_t find_string(pdfio_file_t *pdf, const char *s, int *rdiff);
//
// '_pdfio_strlcpy()' - Safe string copy.
//
size_t // O - Length of source string
_pdfio_strlcpy(char *dst, // I - Destination string buffer
const char *src, // I - Source string
size_t dstsize) // I - Size of destination
{
size_t srclen; // Length of source string
// Range check input...
if (!dst || !src || dstsize == 0)
{
if (dst)
*dst = '\0';
return (0);
}
// Figure out how much room is needed...
dstsize --;
srclen = strlen(src);
// Copy the appropriate amount...
if (srclen <= dstsize)
{
// Source string will fit...
memmove(dst, src, srclen);
dst[srclen] = '\0';
}
else
{
// Source string too big, copy what we can and clean up the end...
char *ptr = dst + dstsize - 1, // Pointer into string
*end = ptr + 1; // Pointer to end of string
memmove(dst, src, dstsize);
dst[dstsize] = '\0';
// Validate last character in destination buffer...
if (ptr > dst && *ptr & 0x80)
{
while ((*ptr & 0xc0) == 0x80 && ptr > dst)
ptr --;
if ((*ptr & 0xe0) == 0xc0)
{
// Verify 2-byte UTF-8 sequence...
if ((end - ptr) != 2)
*ptr = '\0';
}
else if ((*ptr & 0xf0) == 0xe0)
{
// Verify 3-byte UTF-8 sequence...
if ((end - ptr) != 3)
*ptr = '\0';
}
else if ((*ptr & 0xf8) == 0xf0)
{
// Verify 4-byte UTF-8 sequence...
if ((end - ptr) != 4)
*ptr = '\0';
}
else if (*ptr & 0x80)
{
// Invalid sequence at end...
*ptr = '\0';
}
}
}
return (srclen);
}
// //
// '_pdfio_strtod()' - Convert a string to a double value. // '_pdfio_strtod()' - Convert a string to a double value.
// //
@ -114,7 +191,6 @@ _pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
// Loop through the format string, formatting as needed... // Loop through the format string, formatting as needed...
bufptr = buffer; bufptr = buffer;
bufend = buffer + bufsize - 1; bufend = buffer + bufsize - 1;
*bufend = '\0';
bytes = 0; bytes = 0;
while (*format) while (*format)
@ -178,14 +254,12 @@ _pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
} }
else else
{ {
prec = 0;
while (isdigit(*format & 255)) while (isdigit(*format & 255))
{ {
if (tptr < (tformat + sizeof(tformat) - 1)) if (tptr < (tformat + sizeof(tformat) - 1))
*tptr++ = *format; *tptr++ = *format;
prec = prec * 10 + *format++ - '0'; format ++;
} }
} }
} }
@ -259,7 +333,7 @@ _pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
if (bufptr < bufend) if (bufptr < bufend)
{ {
strncpy(bufptr, temp, (size_t)(bufend - bufptr - 1)); _pdfio_strlcpy(bufptr, temp, (size_t)(bufend - bufptr + 1));
bufptr += strlen(bufptr); bufptr += strlen(bufptr);
} }
break; break;
@ -289,7 +363,7 @@ _pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
if (bufptr < bufend) if (bufptr < bufend)
{ {
strncpy(bufptr, temp, (size_t)(bufend - bufptr - 1)); _pdfio_strlcpy(bufptr, temp, (size_t)(bufend - bufptr + 1));
bufptr += strlen(bufptr); bufptr += strlen(bufptr);
} }
break; break;
@ -304,7 +378,7 @@ _pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
if (bufptr < bufend) if (bufptr < bufend)
{ {
strncpy(bufptr, temp, (size_t)(bufend - bufptr - 1)); _pdfio_strlcpy(bufptr, temp, (size_t)(bufend - bufptr + 1));
bufptr += strlen(bufptr); bufptr += strlen(bufptr);
} }
break; break;
@ -329,19 +403,111 @@ _pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
} }
break; break;
case 's' : // String case 'S' : // PDF string
if ((s = va_arg(ap, char *)) == NULL) if ((s = va_arg(ap, char *)) == NULL)
s = "(null)"; s = "(null)";
// PDF strings start with "("...
if (bufptr < bufend)
*bufptr++ = '(';
bytes ++;
// Loop through the literal string...
while (*s)
{
// Escape special characters
if (*s == '\\' || *s == '(' || *s == ')')
{
// Simple escape...
if (bufptr < bufend)
*bufptr++ = '\\';
if (bufptr < bufend)
*bufptr++ = *s;
bytes += 2;
}
else if (*s < ' ')
{
// Octal escape...
snprintf(bufptr, (size_t)(bufend - bufptr + 1), "\\%03o", *s & 255);
bufptr += strlen(bufptr);
bytes += 4;
}
else
{
// Literal character...
if (bufptr < bufend)
*bufptr++ = *s;
bytes ++;
}
s ++;
}
// PDF strings end with ")"...
if (bufptr < bufend)
*bufptr++ = ')';
bytes ++;
break;
case 's' : // Literal string
if ((s = va_arg(ap, char *)) == NULL)
s = "(null)";
if (width != 0)
{
// Format string to fit inside the specified width...
if ((size_t)(width + 1) > sizeof(temp))
break;
snprintf(temp, sizeof(temp), tformat, s);
s = temp;
}
bytes += strlen(s); bytes += strlen(s);
if (bufptr < bufend) if (bufptr < bufend)
{ {
strncpy(bufptr, s, (size_t)(bufend - bufptr - 1)); _pdfio_strlcpy(bufptr, s, (size_t)(bufend - bufptr + 1));
bufptr += strlen(bufptr); bufptr += strlen(bufptr);
} }
break; break;
case 'N' : // Output name string with proper escaping
if ((s = va_arg(ap, char *)) == NULL)
s = "(null)";
// PDF names start with "/"...
if (bufptr < bufend)
*bufptr++ = '/';
bytes ++;
// Loop through the name string...
while (*s)
{
if (*s < 0x21 || *s > 0x7e || *s == '#')
{
// Output #XX for character...
snprintf(bufptr, (size_t)(bufend - bufptr + 1), "#%02X", *s & 255);
bufptr += strlen(bufptr);
bytes += 3;
}
else
{
// Output literal character...
if (bufptr < bufend)
*bufptr++ = *s;
bytes ++;
}
s ++;
}
break;
case 'n' : // Output number of chars so far case 'n' : // Output number of chars so far
*(va_arg(ap, int *)) = (int)bytes; *(va_arg(ap, int *)) = (int)bytes;
break; break;
@ -358,11 +524,7 @@ _pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
} }
// Nul-terminate the string and return the number of characters needed. // Nul-terminate the string and return the number of characters needed.
if (bufptr < bufend)
{
// Everything fit in the buffer...
*bufptr = '\0'; *bufptr = '\0';
}
PDFIO_DEBUG("_pdfio_vsnprintf: Returning %ld \"%s\"\n", (long)bytes, buffer); PDFIO_DEBUG("_pdfio_vsnprintf: Returning %ld \"%s\"\n", (long)bytes, buffer);

View File

@ -1,7 +1,7 @@
// //
// PDF value functions for PDFio. // PDF value functions for PDFio.
// //
// Copyright © 2021-2024 by Michael R Sweet. // Copyright © 2021-2025 by Michael R Sweet.
// //
// Licensed under Apache License v2.0. See the file "LICENSE" for more // Licensed under Apache License v2.0. See the file "LICENSE" for more
// information. // information.
@ -637,7 +637,7 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
} }
else else
{ {
return (_pdfioFilePrintf(pdf, "(%s)", datestr)); return (_pdfioFilePrintf(pdf, "%S", datestr));
} }
} }
@ -648,13 +648,13 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
return (_pdfioFilePrintf(pdf, " %lu %u R", (unsigned long)v->value.indirect.number, v->value.indirect.generation)); return (_pdfioFilePrintf(pdf, " %lu %u R", (unsigned long)v->value.indirect.number, v->value.indirect.generation));
case PDFIO_VALTYPE_NAME : case PDFIO_VALTYPE_NAME :
return (_pdfioFilePrintf(pdf, "/%s", v->value.name)); return (_pdfioFilePrintf(pdf, "%N", v->value.name));
case PDFIO_VALTYPE_NULL : case PDFIO_VALTYPE_NULL :
return (_pdfioFilePuts(pdf, " null")); return (_pdfioFilePuts(pdf, " null"));
case PDFIO_VALTYPE_NUMBER : case PDFIO_VALTYPE_NUMBER :
return (_pdfioFilePrintf(pdf, " %g", v->value.number)); return (_pdfioFilePrintf(pdf, " %.6f", v->value.number));
case PDFIO_VALTYPE_STRING : case PDFIO_VALTYPE_STRING :
if (obj && pdf->encryption) if (obj && pdf->encryption)
@ -695,47 +695,7 @@ _pdfioValueWrite(pdfio_file_t *pdf, // I - PDF file
else else
{ {
// Write unencrypted string... // Write unencrypted string...
const char *start, // Start of fragment return (_pdfioFilePrintf(pdf, "%S", v->value.string));
*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, ")"));
} }
} }

10
pdfio.h
View File

@ -23,7 +23,7 @@ extern "C" {
// Version numbers... // Version numbers...
// //
# define PDFIO_VERSION "1.5.0" # define PDFIO_VERSION "1.5.1"
# define PDFIO_VERSION_MAJOR 1 # define PDFIO_VERSION_MAJOR 1
# define PDFIO_VERSION_MINOR 5 # define PDFIO_VERSION_MINOR 5
@ -34,11 +34,9 @@ extern "C" {
# if defined(__has_extension) || defined(__GNUC__) # if defined(__has_extension) || defined(__GNUC__)
# define _PDFIO_PUBLIC __attribute__ ((visibility("default"))) # define _PDFIO_PUBLIC __attribute__ ((visibility("default")))
# define _PDFIO_FORMAT(a,b) __attribute__ ((__format__(__printf__, a,b)))
# define _PDFIO_DEPRECATED __attribute__ ((deprecated)) _PDFIO_PUBLIC # define _PDFIO_DEPRECATED __attribute__ ((deprecated)) _PDFIO_PUBLIC
# else # else
# define _PDFIO_PUBLIC # define _PDFIO_PUBLIC
# define _PDFIO_FORMAT(a,b)
# define _PDFIO_DEPRECATED # define _PDFIO_DEPRECATED
# endif // __has_extension || __GNUC__ # endif // __has_extension || __GNUC__
@ -183,7 +181,7 @@ extern bool pdfioDictSetNumber(pdfio_dict_t *dict, const char *key, double valu
extern bool pdfioDictSetObj(pdfio_dict_t *dict, const char *key, pdfio_obj_t *value) _PDFIO_PUBLIC; extern bool pdfioDictSetObj(pdfio_dict_t *dict, const char *key, pdfio_obj_t *value) _PDFIO_PUBLIC;
extern bool pdfioDictSetRect(pdfio_dict_t *dict, const char *key, pdfio_rect_t *value) _PDFIO_PUBLIC; extern bool pdfioDictSetRect(pdfio_dict_t *dict, const char *key, pdfio_rect_t *value) _PDFIO_PUBLIC;
extern bool pdfioDictSetString(pdfio_dict_t *dict, const char *key, const char *value) _PDFIO_PUBLIC; extern bool pdfioDictSetString(pdfio_dict_t *dict, const char *key, const char *value) _PDFIO_PUBLIC;
extern bool pdfioDictSetStringf(pdfio_dict_t *dict, const char *key, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(3,4); extern bool pdfioDictSetStringf(pdfio_dict_t *dict, const char *key, const char *format, ...) _PDFIO_PUBLIC;
extern bool pdfioFileClose(pdfio_file_t *pdf) _PDFIO_PUBLIC; extern bool pdfioFileClose(pdfio_file_t *pdf) _PDFIO_PUBLIC;
extern pdfio_file_t *pdfioFileCreate(const char *filename, const char *version, pdfio_rect_t *media_box, pdfio_rect_t *crop_box, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC; extern pdfio_file_t *pdfioFileCreate(const char *filename, const char *version, pdfio_rect_t *media_box, pdfio_rect_t *crop_box, pdfio_error_cb_t error_cb, void *error_data) _PDFIO_PUBLIC;
@ -245,14 +243,14 @@ extern bool pdfioStreamClose(pdfio_stream_t *st) _PDFIO_PUBLIC;
extern bool pdfioStreamConsume(pdfio_stream_t *st, size_t bytes) _PDFIO_PUBLIC; extern bool pdfioStreamConsume(pdfio_stream_t *st, size_t bytes) _PDFIO_PUBLIC;
extern bool pdfioStreamGetToken(pdfio_stream_t *st, char *buffer, size_t bufsize) _PDFIO_PUBLIC; extern bool pdfioStreamGetToken(pdfio_stream_t *st, char *buffer, size_t bufsize) _PDFIO_PUBLIC;
extern ssize_t pdfioStreamPeek(pdfio_stream_t *st, void *buffer, size_t bytes) _PDFIO_PUBLIC; extern ssize_t pdfioStreamPeek(pdfio_stream_t *st, void *buffer, size_t bytes) _PDFIO_PUBLIC;
extern bool pdfioStreamPrintf(pdfio_stream_t *st, const char *format, ...) _PDFIO_PUBLIC _PDFIO_FORMAT(2,3); extern bool pdfioStreamPrintf(pdfio_stream_t *st, const char *format, ...) _PDFIO_PUBLIC;
extern bool pdfioStreamPutChar(pdfio_stream_t *st, int ch) _PDFIO_PUBLIC; extern bool pdfioStreamPutChar(pdfio_stream_t *st, int ch) _PDFIO_PUBLIC;
extern bool pdfioStreamPuts(pdfio_stream_t *st, const char *s) _PDFIO_PUBLIC; 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 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 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 *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; extern char *pdfioStringCreatef(pdfio_file_t *pdf, const char *format, ...) _PDFIO_PUBLIC;
# ifdef __cplusplus # ifdef __cplusplus

View File

@ -3,7 +3,7 @@
<metadata> <metadata>
<id>pdfio_native</id> <id>pdfio_native</id>
<title>PDFio Library for VS2019+</title> <title>PDFio Library for VS2019+</title>
<version>1.5.0</version> <version>1.5.1</version>
<authors>Michael R Sweet</authors> <authors>Michael R Sweet</authors>
<owners>michaelrsweet</owners> <owners>michaelrsweet</owners>
<projectUrl>https://github.com/michaelrsweet/pappl</projectUrl> <projectUrl>https://github.com/michaelrsweet/pappl</projectUrl>
@ -16,7 +16,7 @@
<copyright>Copyright © 2019-2025 by Michael R Sweet</copyright> <copyright>Copyright © 2019-2025 by Michael R Sweet</copyright>
<tags>pdf file native</tags> <tags>pdf file native</tags>
<dependencies> <dependencies>
<dependency id="pdfio_native.redist" version="1.5.0" /> <dependency id="pdfio_native.redist" version="1.5.1" />
<dependency id="libpng_native.redist" version="1.6.30" /> <dependency id="libpng_native.redist" version="1.6.30" />
<dependency id="zlib_native.redist" version="1.2.11" /> <dependency id="zlib_native.redist" version="1.2.11" />
</dependencies> </dependencies>

View File

@ -3,7 +3,7 @@
<metadata> <metadata>
<id>pdfio_native.redist</id> <id>pdfio_native.redist</id>
<title>PDFio Library for VS2019+</title> <title>PDFio Library for VS2019+</title>
<version>1.5.0</version> <version>1.5.1</version>
<authors>Michael R Sweet</authors> <authors>Michael R Sweet</authors>
<owners>michaelrsweet</owners> <owners>michaelrsweet</owners>
<projectUrl>https://github.com/michaelrsweet/pappl</projectUrl> <projectUrl>https://github.com/michaelrsweet/pappl</projectUrl>