mirror of
https://github.com/michaelrsweet/pdfio.git
synced 2025-04-30 12:26:46 +02:00
Compare commits
4 Commits
cd1406e158
...
6c1db141a1
Author | SHA1 | Date | |
---|---|---|---|
|
6c1db141a1 | ||
|
b117959725 | ||
|
e882622233 | ||
|
c13b5a5e90 |
@ -2,6 +2,13 @@ Changes in PDFio
|
|||||||
================
|
================
|
||||||
|
|
||||||
|
|
||||||
|
v1.2.1 (Month DD, YYYY)
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
- Updated number support to avoid locale issues (Issue #61)
|
||||||
|
- Optimized string pool code.
|
||||||
|
|
||||||
|
|
||||||
v1.2.0 (January 24, 2024)
|
v1.2.0 (January 24, 2024)
|
||||||
-------------------------
|
-------------------------
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#
|
#
|
||||||
# Makefile for PDFio.
|
# Makefile for PDFio.
|
||||||
#
|
#
|
||||||
# Copyright © 2021-2023 by Michael R Sweet.
|
# Copyright © 2021-2024 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.
|
||||||
@ -163,7 +163,9 @@ install: $(TARGETS)
|
|||||||
# Test everything
|
# Test everything
|
||||||
test: testpdfio testttf
|
test: testpdfio testttf
|
||||||
./testttf 2>test.log
|
./testttf 2>test.log
|
||||||
./testpdfio 2>test.log
|
./testpdfio 2>>test.log
|
||||||
|
LANG=fr_FR.UTF-8 ./testpdfio 2>>test.log
|
||||||
|
|
||||||
|
|
||||||
valgrind: testpdfio
|
valgrind: testpdfio
|
||||||
valgrind --leak-check=full ./testpdfio
|
valgrind --leak-check=full ./testpdfio
|
||||||
|
27
configure
vendored
27
configure
vendored
@ -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.2.0.
|
# Generated by GNU Autoconf 2.71 for pdfio 1.2.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.2.0'
|
PACKAGE_VERSION='1.2.1'
|
||||||
PACKAGE_STRING='pdfio 1.2.0'
|
PACKAGE_STRING='pdfio 1.2.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'
|
||||||
|
|
||||||
@ -1293,7 +1293,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.2.0 to adapt to many kinds of systems.
|
\`configure' configures pdfio 1.2.1 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1359,7 +1359,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.2.0:";;
|
short | recursive ) echo "Configuration of pdfio 1.2.1:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1456,7 +1456,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.2.0
|
pdfio configure 1.2.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.
|
||||||
@ -1612,7 +1612,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.2.0, which was
|
It was created by pdfio $as_me 1.2.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
|
||||||
@ -2368,9 +2368,9 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
PDFIO_VERSION="1.2.0"
|
PDFIO_VERSION="1.2.1"
|
||||||
PDFIO_VERSION_MAJOR="`echo 1.2.0 | awk -F. '{print $1}'`"
|
PDFIO_VERSION_MAJOR="`echo 1.2.1 | awk -F. '{print $1}'`"
|
||||||
PDFIO_VERSION_MINOR="`echo 1.2.0 | awk -F. '{printf("%d\n",$2);}'`"
|
PDFIO_VERSION_MINOR="`echo 1.2.1 | awk -F. '{printf("%d\n",$2);}'`"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -4029,8 +4029,8 @@ then :
|
|||||||
|
|
||||||
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||||
printf "%s\n" "yes" >&6; }
|
printf "%s\n" "yes" >&6; }
|
||||||
LIBS="$($PKGCONFIG --libs zlib) $LIBS"
|
|
||||||
CPPFLAGS="$($PKGCONFIG --cflags zlib) $CPPFLAGS"
|
CPPFLAGS="$($PKGCONFIG --cflags zlib) $CPPFLAGS"
|
||||||
|
LIBS="$($PKGCONFIG --libs zlib) $LIBS"
|
||||||
|
|
||||||
else $as_nop
|
else $as_nop
|
||||||
|
|
||||||
@ -4093,6 +4093,7 @@ then :
|
|||||||
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
PKGCONFIG_REQUIRES=""
|
||||||
PKGCONFIG_LIBS_PRIVATE="-lz $PKGCONFIG_LIBS_PRIVATE"
|
PKGCONFIG_LIBS_PRIVATE="-lz $PKGCONFIG_LIBS_PRIVATE"
|
||||||
|
|
||||||
fi
|
fi
|
||||||
@ -4934,7 +4935,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.2.0, which was
|
This file was extended by pdfio $as_me 1.2.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
|
||||||
@ -4990,7 +4991,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.2.0
|
pdfio config.status 1.2.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\\"
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ AC_PREREQ([2.70])
|
|||||||
|
|
||||||
|
|
||||||
dnl Package name and version...
|
dnl Package name and version...
|
||||||
AC_INIT([pdfio], [1.2.0], [https://github.com/michaelrsweet/pdfio/issues], [pdfio], [https://www.msweet.org/pdfio])
|
AC_INIT([pdfio], [1.2.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}'`"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Common support functions for pdfio.
|
// Common support functions for pdfio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021-2023 by Michael R Sweet.
|
// Copyright © 2021-2024 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.
|
||||||
@ -261,7 +261,7 @@ _pdfioFilePrintf(pdfio_file_t *pdf, // I - PDF file
|
|||||||
|
|
||||||
// Format the string...
|
// Format the string...
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
_pdfio_vsnprintf(pdf, buffer, sizeof(buffer), format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
// Write it...
|
// Write it...
|
||||||
|
34
pdfio-file.c
34
pdfio-file.c
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// PDF file functions for PDFio.
|
// PDF file functions for PDFio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021-2023 by Michael R Sweet.
|
// Copyright © 2021-2024 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.
|
||||||
@ -20,6 +20,7 @@
|
|||||||
static pdfio_obj_t *add_obj(pdfio_file_t *pdf, size_t number, unsigned short generation, off_t offset);
|
static pdfio_obj_t *add_obj(pdfio_file_t *pdf, size_t number, unsigned short generation, off_t offset);
|
||||||
static int compare_objmaps(_pdfio_objmap_t *a, _pdfio_objmap_t *b);
|
static int compare_objmaps(_pdfio_objmap_t *a, _pdfio_objmap_t *b);
|
||||||
static const char *get_info_string(pdfio_file_t *pdf, const char *key);
|
static const char *get_info_string(pdfio_file_t *pdf, const char *key);
|
||||||
|
static struct lconv *get_lconv(void);
|
||||||
static bool load_obj_stream(pdfio_obj_t *obj);
|
static bool load_obj_stream(pdfio_obj_t *obj);
|
||||||
static bool load_pages(pdfio_file_t *pdf, pdfio_obj_t *obj, size_t depth);
|
static bool load_pages(pdfio_file_t *pdf, pdfio_obj_t *obj, size_t depth);
|
||||||
static bool load_xref(pdfio_file_t *pdf, off_t xref_offset, pdfio_password_cb_t password_cb, void *password_data);
|
static bool load_xref(pdfio_file_t *pdf, off_t xref_offset, pdfio_password_cb_t password_cb, void *password_data);
|
||||||
@ -217,6 +218,7 @@ pdfioFileCreate(
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pdf->loc = get_lconv();
|
||||||
pdf->filename = strdup(filename);
|
pdf->filename = strdup(filename);
|
||||||
pdf->version = strdup(version);
|
pdf->version = strdup(version);
|
||||||
pdf->mode = _PDFIO_MODE_WRITE;
|
pdf->mode = _PDFIO_MODE_WRITE;
|
||||||
@ -259,9 +261,12 @@ pdfioFileCreate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write a standard PDF header...
|
// Write a standard PDF header...
|
||||||
if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%\342\343\317\323\n", version))
|
if (!_pdfioFilePrintf(pdf, "%%PDF-%s\n%%PDF\303\254o\n", version))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
if (pdf->loc)
|
||||||
|
_pdfioFilePrintf(pdf, "%%decimal_point=\"%s\"\n", pdf->loc->decimal_point);
|
||||||
|
|
||||||
// Create the pages object...
|
// Create the pages object...
|
||||||
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
if ((dict = pdfioDictCreate(pdf)) == NULL)
|
||||||
goto error;
|
goto error;
|
||||||
@ -508,6 +513,7 @@ pdfioFileCreateOutput(
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pdf->loc = get_lconv();
|
||||||
pdf->filename = strdup("output.pdf");
|
pdf->filename = strdup("output.pdf");
|
||||||
pdf->version = strdup(version);
|
pdf->version = strdup(version);
|
||||||
pdf->mode = _PDFIO_MODE_WRITE;
|
pdf->mode = _PDFIO_MODE_WRITE;
|
||||||
@ -787,6 +793,7 @@ pdfioFileCreateTemporary(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pdf->loc = get_lconv();
|
||||||
pdf->filename = strdup(buffer);
|
pdf->filename = strdup(buffer);
|
||||||
|
|
||||||
if (i >= 1000)
|
if (i >= 1000)
|
||||||
@ -1218,6 +1225,7 @@ pdfioFileOpen(
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pdf->loc = get_lconv();
|
||||||
pdf->filename = strdup(filename);
|
pdf->filename = strdup(filename);
|
||||||
pdf->mode = _PDFIO_MODE_READ;
|
pdf->mode = _PDFIO_MODE_READ;
|
||||||
pdf->error_cb = error_cb;
|
pdf->error_cb = error_cb;
|
||||||
@ -1576,6 +1584,28 @@ get_info_string(pdfio_file_t *pdf, // I - PDF file
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'get_lconv()' - Get any locale-specific numeric information.
|
||||||
|
//
|
||||||
|
|
||||||
|
static struct lconv * // O - Locale information or `NULL`
|
||||||
|
get_lconv(void)
|
||||||
|
{
|
||||||
|
struct lconv *loc; // Locale information
|
||||||
|
|
||||||
|
|
||||||
|
if ((loc = localeconv()) != NULL)
|
||||||
|
{
|
||||||
|
PDFIO_DEBUG("get_lconv: loc=%p, loc->decimal_point=\"%s\"\n", loc, loc->decimal_point);
|
||||||
|
|
||||||
|
if (!loc->decimal_point || !strcmp(loc->decimal_point, "."))
|
||||||
|
loc = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (loc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// 'load_obj_stream()' - Load an object stream.
|
// 'load_obj_stream()' - Load an object stream.
|
||||||
//
|
//
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Private header file for PDFio.
|
// Private header file for PDFio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021-2023 by Michael R Sweet.
|
// Copyright © 2021-2024 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.
|
||||||
@ -20,6 +20,7 @@
|
|||||||
# include <errno.h>
|
# include <errno.h>
|
||||||
# include <inttypes.h>
|
# include <inttypes.h>
|
||||||
# include <fcntl.h>
|
# include <fcntl.h>
|
||||||
|
# include <locale.h>
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
# include <direct.h>
|
# include <direct.h>
|
||||||
@ -224,6 +225,7 @@ typedef struct _pdfio_objmap_s // PDF object map
|
|||||||
struct _pdfio_file_s // PDF file structure
|
struct _pdfio_file_s // PDF file structure
|
||||||
{
|
{
|
||||||
char *filename; // Filename
|
char *filename; // Filename
|
||||||
|
struct lconv *loc; // Locale data
|
||||||
char *version; // Version number
|
char *version; // Version number
|
||||||
pdfio_rect_t media_box, // Default MediaBox value
|
pdfio_rect_t media_box, // Default MediaBox value
|
||||||
crop_box; // Default CropBox value
|
crop_box; // Default CropBox value
|
||||||
@ -322,6 +324,9 @@ struct _pdfio_stream_s // Stream
|
|||||||
// Functions...
|
// Functions...
|
||||||
//
|
//
|
||||||
|
|
||||||
|
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 bool _pdfioArrayDecrypt(pdfio_file_t *pdf, pdfio_obj_t *obj, pdfio_array_t *a, size_t depth) _PDFIO_INTERNAL;
|
extern bool _pdfioArrayDecrypt(pdfio_file_t *pdf, pdfio_obj_t *obj, pdfio_array_t *a, size_t depth) _PDFIO_INTERNAL;
|
||||||
extern void _pdfioArrayDebug(pdfio_array_t *a, FILE *fp) _PDFIO_INTERNAL;
|
extern void _pdfioArrayDebug(pdfio_array_t *a, FILE *fp) _PDFIO_INTERNAL;
|
||||||
extern void _pdfioArrayDelete(pdfio_array_t *a) _PDFIO_INTERNAL;
|
extern void _pdfioArrayDelete(pdfio_array_t *a) _PDFIO_INTERNAL;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// PDF stream functions for PDFio.
|
// PDF stream functions for PDFio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021-2023 by Michael R Sweet.
|
// Copyright © 2021-2024 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.
|
||||||
@ -687,7 +687,7 @@ pdfioStreamPrintf(
|
|||||||
|
|
||||||
// Format the string...
|
// Format the string...
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
_pdfio_vsnprintf(st->pdf, buffer, sizeof(buffer), format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
// Write the string...
|
// Write the string...
|
||||||
|
453
pdfio-string.c
453
pdfio-string.c
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// PDF dictionary functions for PDFio.
|
// PDF string functions for PDFio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021 by Michael R Sweet.
|
// Copyright © 2021-2024 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.
|
||||||
@ -14,7 +14,360 @@
|
|||||||
// Local functions...
|
// Local functions...
|
||||||
//
|
//
|
||||||
|
|
||||||
static int compare_strings(char **a, char **b);
|
static size_t find_string(pdfio_file_t *pdf, const char *s, int *rdiff);
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// '_pdfio_strtod()' - Convert a string to a double value.
|
||||||
|
//
|
||||||
|
// This function wraps strtod() to avoid locale issues.
|
||||||
|
//
|
||||||
|
|
||||||
|
double // O - Double value
|
||||||
|
_pdfio_strtod(pdfio_file_t *pdf, // I - PDF file
|
||||||
|
const char *s) // I - String
|
||||||
|
{
|
||||||
|
char temp[64], // Temporary buffer
|
||||||
|
*tempptr; // Pointer into temporary buffer
|
||||||
|
|
||||||
|
|
||||||
|
// See if the locale has a special decimal point string...
|
||||||
|
if (!pdf->loc)
|
||||||
|
return (strtod(s, NULL));
|
||||||
|
|
||||||
|
// Copy leading sign, numbers, period, and then numbers...
|
||||||
|
tempptr = temp;
|
||||||
|
temp[sizeof(temp) - 1] = '\0';
|
||||||
|
|
||||||
|
while (*s && *s != '.')
|
||||||
|
{
|
||||||
|
if (tempptr < (temp + sizeof(temp) - 1))
|
||||||
|
*tempptr++ = *s++;
|
||||||
|
else
|
||||||
|
return (0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*s == '.')
|
||||||
|
{
|
||||||
|
// Convert decimal point to locale equivalent...
|
||||||
|
size_t declen = strlen(pdf->loc->decimal_point);
|
||||||
|
// Length of decimal point
|
||||||
|
s ++;
|
||||||
|
|
||||||
|
if (declen <= (sizeof(temp) - (size_t)(tempptr - temp)))
|
||||||
|
{
|
||||||
|
memcpy(tempptr, pdf->loc->decimal_point, declen);
|
||||||
|
tempptr += declen;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return (0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy any remaining characters...
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
if (tempptr < (temp + sizeof(temp) - 1))
|
||||||
|
*tempptr++ = *s++;
|
||||||
|
else
|
||||||
|
return (0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nul-terminate the temporary string and convert the string...
|
||||||
|
*tempptr = '\0';
|
||||||
|
|
||||||
|
return (strtod(temp, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// '_pdfio_vsnprintf()' - Format a string.
|
||||||
|
//
|
||||||
|
// This function emulates vsnprintf() to avoid locale issues.
|
||||||
|
//
|
||||||
|
|
||||||
|
ssize_t // O - Number of bytes
|
||||||
|
_pdfio_vsnprintf(pdfio_file_t *pdf, // I - PDF file
|
||||||
|
char *buffer, // I - Output buffer
|
||||||
|
size_t bufsize, // I - Size of output buffer
|
||||||
|
const char *format, // I - printf-style format string
|
||||||
|
va_list ap) // I - Pointer to additional arguments
|
||||||
|
{
|
||||||
|
char *bufptr, // Pointer to position in buffer
|
||||||
|
*bufend, // Pointer to end of buffer
|
||||||
|
size, // Size character (h, l, L)
|
||||||
|
type; // Format type character
|
||||||
|
int width, // Width of field
|
||||||
|
prec; // Number of characters of precision
|
||||||
|
char tformat[100], // Temporary format string for snprintf()
|
||||||
|
*tptr, // Pointer into temporary format
|
||||||
|
temp[1024], // Buffer for formatted numbers
|
||||||
|
*tempptr; // Pointer into buffer
|
||||||
|
char *s; // Pointer to string
|
||||||
|
ssize_t bytes; // Total number of bytes needed
|
||||||
|
const char *dec = pdf->loc ? pdf->loc->decimal_point : ".";
|
||||||
|
// Decimal point string
|
||||||
|
char *decptr; // Pointer to decimal point
|
||||||
|
|
||||||
|
|
||||||
|
// Loop through the format string, formatting as needed...
|
||||||
|
bufptr = buffer;
|
||||||
|
bufend = buffer + bufsize - 1;
|
||||||
|
*bufend = '\0';
|
||||||
|
bytes = 0;
|
||||||
|
|
||||||
|
while (*format)
|
||||||
|
{
|
||||||
|
if (*format == '%')
|
||||||
|
{
|
||||||
|
// Format character...
|
||||||
|
tptr = tformat;
|
||||||
|
*tptr++ = *format++;
|
||||||
|
|
||||||
|
if (*format == '%')
|
||||||
|
{
|
||||||
|
if (bufptr < bufend)
|
||||||
|
*bufptr++ = *format;
|
||||||
|
bytes ++;
|
||||||
|
format ++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (strchr(" -+#\'", *format))
|
||||||
|
{
|
||||||
|
*tptr++ = *format++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*format == '*')
|
||||||
|
{
|
||||||
|
// Get width from argument...
|
||||||
|
format ++;
|
||||||
|
width = va_arg(ap, int);
|
||||||
|
|
||||||
|
snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", width);
|
||||||
|
tptr += strlen(tptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
width = 0;
|
||||||
|
|
||||||
|
while (isdigit(*format & 255))
|
||||||
|
{
|
||||||
|
if (tptr < (tformat + sizeof(tformat) - 1))
|
||||||
|
*tptr++ = *format;
|
||||||
|
|
||||||
|
width = width * 10 + *format++ - '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*format == '.')
|
||||||
|
{
|
||||||
|
if (tptr < (tformat + sizeof(tformat) - 1))
|
||||||
|
*tptr++ = *format;
|
||||||
|
|
||||||
|
format ++;
|
||||||
|
|
||||||
|
if (*format == '*')
|
||||||
|
{
|
||||||
|
// Get precision from argument...
|
||||||
|
format ++;
|
||||||
|
prec = va_arg(ap, int);
|
||||||
|
|
||||||
|
snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", prec);
|
||||||
|
tptr += strlen(tptr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prec = 0;
|
||||||
|
|
||||||
|
while (isdigit(*format & 255))
|
||||||
|
{
|
||||||
|
if (tptr < (tformat + sizeof(tformat) - 1))
|
||||||
|
*tptr++ = *format;
|
||||||
|
|
||||||
|
prec = prec * 10 + *format++ - '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*format == 'l' && format[1] == 'l')
|
||||||
|
{
|
||||||
|
size = 'L';
|
||||||
|
|
||||||
|
if (tptr < (tformat + sizeof(tformat) - 2))
|
||||||
|
{
|
||||||
|
*tptr++ = 'l';
|
||||||
|
*tptr++ = 'l';
|
||||||
|
}
|
||||||
|
|
||||||
|
format += 2;
|
||||||
|
}
|
||||||
|
else if (*format == 'h' || *format == 'l' || *format == 'L')
|
||||||
|
{
|
||||||
|
if (tptr < (tformat + sizeof(tformat) - 1))
|
||||||
|
*tptr++ = *format;
|
||||||
|
|
||||||
|
size = *format++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!*format)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (tptr < (tformat + sizeof(tformat) - 1))
|
||||||
|
*tptr++ = *format;
|
||||||
|
|
||||||
|
type = *format++;
|
||||||
|
*tptr = '\0';
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case 'E' : // Floating point formats
|
||||||
|
case 'G' :
|
||||||
|
case 'e' :
|
||||||
|
case 'f' :
|
||||||
|
case 'g' :
|
||||||
|
if ((size_t)(width + 2) > sizeof(temp))
|
||||||
|
break;
|
||||||
|
|
||||||
|
snprintf(temp, sizeof(temp), tformat, va_arg(ap, double));
|
||||||
|
|
||||||
|
if ((decptr = strstr(temp, dec)) != NULL)
|
||||||
|
{
|
||||||
|
// Convert locale decimal point to "."
|
||||||
|
PDFIO_DEBUG("_pdfio_vsnprintf: Before \"%s\"\n", temp);
|
||||||
|
tempptr = decptr + strlen(dec);
|
||||||
|
if (tempptr > (decptr + 1))
|
||||||
|
memmove(decptr + 1, tempptr, strlen(tempptr) + 1);
|
||||||
|
*decptr = '.';
|
||||||
|
|
||||||
|
// Strip trailing 0's...
|
||||||
|
for (tempptr = temp + strlen(temp) - 1; tempptr > temp && *tempptr == '0'; tempptr --)
|
||||||
|
*tempptr = '\0';
|
||||||
|
|
||||||
|
if (*tempptr == '.')
|
||||||
|
*tempptr = '\0'; // Strip trailing decimal point
|
||||||
|
|
||||||
|
PDFIO_DEBUG("_pdfio_vsnprintf: After \"%s\"\n", temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy to the output buffer
|
||||||
|
bytes += (int)strlen(temp);
|
||||||
|
|
||||||
|
if (bufptr < bufend)
|
||||||
|
{
|
||||||
|
strncpy(bufptr, temp, (size_t)(bufend - bufptr - 1));
|
||||||
|
bufptr += strlen(bufptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B' : // Integer formats
|
||||||
|
case 'X' :
|
||||||
|
case 'b' :
|
||||||
|
case 'd' :
|
||||||
|
case 'i' :
|
||||||
|
case 'o' :
|
||||||
|
case 'u' :
|
||||||
|
case 'x' :
|
||||||
|
if ((size_t)(width + 2) > sizeof(temp))
|
||||||
|
break;
|
||||||
|
|
||||||
|
# ifdef HAVE_LONG_LONG
|
||||||
|
if (size == 'L')
|
||||||
|
snprintf(temp, sizeof(temp), tformat, va_arg(ap, long long));
|
||||||
|
else
|
||||||
|
# endif // HAVE_LONG_LONG
|
||||||
|
if (size == 'l')
|
||||||
|
snprintf(temp, sizeof(temp), tformat, va_arg(ap, long));
|
||||||
|
else
|
||||||
|
snprintf(temp, sizeof(temp), tformat, va_arg(ap, int));
|
||||||
|
|
||||||
|
bytes += (int)strlen(temp);
|
||||||
|
|
||||||
|
if (bufptr < bufend)
|
||||||
|
{
|
||||||
|
strncpy(bufptr, temp, (size_t)(bufend - bufptr - 1));
|
||||||
|
bufptr += strlen(bufptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'p' : // Pointer value
|
||||||
|
if ((size_t)(width + 2) > sizeof(temp))
|
||||||
|
break;
|
||||||
|
|
||||||
|
snprintf(temp, sizeof(temp), tformat, va_arg(ap, void *));
|
||||||
|
|
||||||
|
bytes += (int)strlen(temp);
|
||||||
|
|
||||||
|
if (bufptr < bufend)
|
||||||
|
{
|
||||||
|
strncpy(bufptr, temp, (size_t)(bufend - bufptr - 1));
|
||||||
|
bufptr += strlen(bufptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'c' : // Character or character array
|
||||||
|
bytes += width;
|
||||||
|
|
||||||
|
if (bufptr < bufend)
|
||||||
|
{
|
||||||
|
if (width <= 1)
|
||||||
|
{
|
||||||
|
*bufptr++ = (char)va_arg(ap, int);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((bufptr + width) > bufend)
|
||||||
|
width = (int)(bufend - bufptr);
|
||||||
|
|
||||||
|
memcpy(bufptr, va_arg(ap, char *), (size_t)width);
|
||||||
|
bufptr += width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's' : // String
|
||||||
|
if ((s = va_arg(ap, char *)) == NULL)
|
||||||
|
s = "(null)";
|
||||||
|
|
||||||
|
bytes += strlen(s);
|
||||||
|
|
||||||
|
if (bufptr < bufend)
|
||||||
|
{
|
||||||
|
strncpy(bufptr, s, (size_t)(bufend - bufptr - 1));
|
||||||
|
bufptr += strlen(bufptr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n' : // Output number of chars so far
|
||||||
|
*(va_arg(ap, int *)) = (int)bytes;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Literal character...
|
||||||
|
bytes ++;
|
||||||
|
|
||||||
|
if (bufptr < bufend)
|
||||||
|
*bufptr++ = *format++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nul-terminate the string and return the number of characters needed.
|
||||||
|
if (bufptr < bufend)
|
||||||
|
{
|
||||||
|
// Everything fit in the buffer...
|
||||||
|
*bufptr = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
PDFIO_DEBUG("_pdfio_vsnprintf: Returning %ld \"%s\"\n", (long)bytes, buffer);
|
||||||
|
|
||||||
|
return (bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -32,8 +385,9 @@ pdfioStringCreate(
|
|||||||
pdfio_file_t *pdf, // I - PDF file
|
pdfio_file_t *pdf, // I - PDF file
|
||||||
const char *s) // I - Nul-terminated string
|
const char *s) // I - Nul-terminated string
|
||||||
{
|
{
|
||||||
char *news; // New string
|
char *news; // New string
|
||||||
char **match; // Matching string
|
size_t idx; // Index into strings
|
||||||
|
int diff; // Different
|
||||||
|
|
||||||
|
|
||||||
PDFIO_DEBUG("pdfioStringCreate(pdf=%p, s=\"%s\")\n", pdf, s);
|
PDFIO_DEBUG("pdfioStringCreate(pdf=%p, s=\"%s\")\n", pdf, s);
|
||||||
@ -43,8 +397,17 @@ pdfioStringCreate(
|
|||||||
return (NULL);
|
return (NULL);
|
||||||
|
|
||||||
// See if the string has already been added...
|
// See if the string has already been added...
|
||||||
if (pdf->num_strings > 0 && (match = (char **)bsearch(&s, pdf->strings, pdf->num_strings, sizeof(char *), (int (*)(const void *, const void *))compare_strings)) != NULL)
|
if (pdf->num_strings > 0)
|
||||||
return (*match);
|
{
|
||||||
|
idx = find_string(pdf, s, &diff);
|
||||||
|
if (diff == 0)
|
||||||
|
return (pdf->strings[idx]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
idx = 0;
|
||||||
|
diff = -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Not already added, so add it...
|
// Not already added, so add it...
|
||||||
if ((news = strdup(s)) == NULL)
|
if ((news = strdup(s)) == NULL)
|
||||||
@ -65,11 +428,17 @@ pdfioStringCreate(
|
|||||||
pdf->alloc_strings += 128;
|
pdf->alloc_strings += 128;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Change to insertion sort as needed...
|
// Insert the string...
|
||||||
pdf->strings[pdf->num_strings ++] = news;
|
if (diff > 0)
|
||||||
|
idx ++;
|
||||||
|
|
||||||
if (pdf->num_strings > 1)
|
PDFIO_DEBUG("pdfioStringCreate: Inserting \"%s\" at %u\n", news, (unsigned)idx);
|
||||||
qsort(pdf->strings, pdf->num_strings, sizeof(char *), (int (*)(const void *, const void *))compare_strings);
|
|
||||||
|
if (idx < pdf->num_strings)
|
||||||
|
memmove(pdf->strings + idx + 1, pdf->strings + idx, (pdf->num_strings - idx) * sizeof(char *));
|
||||||
|
|
||||||
|
pdf->strings[idx] = news;
|
||||||
|
pdf->num_strings ++;
|
||||||
|
|
||||||
PDFIO_DEBUG("pdfioStringCreate: %lu strings\n", (unsigned long)pdf->num_strings);
|
PDFIO_DEBUG("pdfioStringCreate: %lu strings\n", (unsigned long)pdf->num_strings);
|
||||||
|
|
||||||
@ -120,17 +489,67 @@ _pdfioStringIsAllocated(
|
|||||||
pdfio_file_t *pdf, // I - PDF file
|
pdfio_file_t *pdf, // I - PDF file
|
||||||
const char *s) // I - String
|
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);
|
int diff; // Difference
|
||||||
|
|
||||||
|
|
||||||
|
if (pdf->num_strings == 0)
|
||||||
|
return (false);
|
||||||
|
|
||||||
|
find_string(pdf, s, &diff);
|
||||||
|
|
||||||
|
return (diff == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// 'compare_strings()' - Compare two strings.
|
// 'find_string()' - Find an element in the array.
|
||||||
//
|
//
|
||||||
|
|
||||||
static int // O - Result of comparison
|
static size_t // O - Index of match
|
||||||
compare_strings(char **a, // I - First string
|
find_string(pdfio_file_t *pdf, // I - PDF file
|
||||||
char **b) // I - Second string
|
const char *s, // I - String to find
|
||||||
|
int *rdiff) // O - Difference of match
|
||||||
{
|
{
|
||||||
return (strcmp(*a, *b));
|
size_t left, // Left side of search
|
||||||
|
right, // Right side of search
|
||||||
|
current; // Current element
|
||||||
|
int diff; // Comparison with current element
|
||||||
|
|
||||||
|
|
||||||
|
// Do a binary search for the string...
|
||||||
|
left = 0;
|
||||||
|
right = pdf->num_strings - 1;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
current = (left + right) / 2;
|
||||||
|
diff = strcmp(s, pdf->strings[current]);
|
||||||
|
|
||||||
|
if (diff == 0)
|
||||||
|
break;
|
||||||
|
else if (diff < 0)
|
||||||
|
right = current;
|
||||||
|
else
|
||||||
|
left = current;
|
||||||
|
}
|
||||||
|
while ((right - left) > 1);
|
||||||
|
|
||||||
|
if (diff != 0)
|
||||||
|
{
|
||||||
|
// Check the last 1 or 2 elements...
|
||||||
|
if ((diff = strcmp(s, pdf->strings[left])) <= 0)
|
||||||
|
{
|
||||||
|
current = left;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
diff = strcmp(s, pdf->strings[right]);
|
||||||
|
current = right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the closest string and the difference...
|
||||||
|
*rdiff = diff;
|
||||||
|
|
||||||
|
return (current);
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// PDF value functions for PDFio.
|
// PDF value functions for PDFio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021-2023 by Michael R Sweet.
|
// Copyright © 2021-2024 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.
|
||||||
@ -497,7 +497,7 @@ _pdfioValueRead(pdfio_file_t *pdf, // I - PDF file
|
|||||||
|
|
||||||
// If we get here, we have a number...
|
// If we get here, we have a number...
|
||||||
v->type = PDFIO_VALTYPE_NUMBER;
|
v->type = PDFIO_VALTYPE_NUMBER;
|
||||||
v->value.number = (double)strtod(token, NULL);
|
v->value.number = _pdfio_strtod(pdf, token);
|
||||||
}
|
}
|
||||||
else if (!strcmp(token, "true") || !strcmp(token, "false"))
|
else if (!strcmp(token, "true") || !strcmp(token, "false"))
|
||||||
{
|
{
|
||||||
|
4
pdfio.h
4
pdfio.h
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Public header file for PDFio.
|
// Public header file for PDFio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021-2023 by Michael R Sweet.
|
// Copyright © 2021-2024 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.
|
||||||
@ -23,7 +23,7 @@ extern "C" {
|
|||||||
// Version number...
|
// Version number...
|
||||||
//
|
//
|
||||||
|
|
||||||
# define PDFIO_VERSION "1.2.0"
|
# define PDFIO_VERSION "1.2.1"
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// Test program for PDFio.
|
// Test program for PDFio.
|
||||||
//
|
//
|
||||||
// Copyright © 2021-2023 by Michael R Sweet.
|
// Copyright © 2021-2024 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.
|
||||||
@ -16,6 +16,7 @@
|
|||||||
#include "pdfio-private.h"
|
#include "pdfio-private.h"
|
||||||
#include "pdfio-content.h"
|
#include "pdfio-content.h"
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include <locale.h>
|
||||||
#ifndef M_PI
|
#ifndef M_PI
|
||||||
# define M_PI 3.14159265358979323846264338327950288
|
# define M_PI 3.14159265358979323846264338327950288
|
||||||
#endif // M_PI
|
#endif // M_PI
|
||||||
@ -61,6 +62,8 @@ main(int argc, // I - Number of command-line arguments
|
|||||||
int ret = 0; // Return value
|
int ret = 0; // Return value
|
||||||
|
|
||||||
|
|
||||||
|
fprintf(stderr, "testpdfio: Test locale is \"%s\".\n", setlocale(LC_ALL, getenv("LANG")));
|
||||||
|
|
||||||
if (argc > 1)
|
if (argc > 1)
|
||||||
{
|
{
|
||||||
int i; // Looping var
|
int i; // Looping var
|
||||||
|
Loading…
x
Reference in New Issue
Block a user