Commit 0b8c58ce authored by Tomáš Stefan's avatar Tomáš Stefan

Initial support for processing trailer

parent 585c1735
......@@ -24,12 +24,30 @@
typedef uint32_t free_indicator_t;
#endif /* FREE_INDICATOR_T */
#ifndef REREFENCE_T
#define REREFENCE_T
typedef struct {
size_t object_num;
size_t generation_num;
} reference_t;
#endif /* REREFENCE_T */
#ifndef DICT_KEY_T
#define DICT_KEY_T
typedef uint32_t dict_key_t;
#endif /* DICT_KEY_T */
#define KEYWORD_xref 0
#define KEYWORD_trailer 1
#define IN_USE_ENTRY 0
#define FREE_ENTRY 1
#define DICT_KEY_Size 0
#define DICT_KEY_Prev 1
#define DICT_KEY_Root 2
#define DICT_KEY_unknown 3
#define COLOR_RED "\x1b[31m"
#define COLOR_GREEN "\x1b[32m"
#define COLOR_RESET "\x1b[0m"
......@@ -44,10 +62,14 @@ int is_digit(const char_t c);
int is_whitespace(const char_t c);
sigil_err_t skip_leading_whitespaces(FILE *in);
sigil_err_t skip_dictionary(FILE *in);
sigil_err_t skip_dict_unknown_value(FILE *in);
sigil_err_t parse_number(FILE *in, size_t *number);
sigil_err_t parse_keyword(FILE *in, keyword_t *keyword);
sigil_err_t parse_free_indicator(FILE *in, free_indicator_t *result);
sigil_err_t parse_indirect_reference(FILE *in, reference_t *ref);
sigil_err_t parse_dict_key(FILE *in, dict_key_t *dict_key);
void print_module_name(const char *module_name, int verbosity);
void print_module_result(int result, int verbosity);
......
......@@ -23,22 +23,33 @@
typedef struct {
xref_entry_t **entry;
size_t capacity;
size_t size_from_trailer;
size_t prev_section;
} xref_t;
#endif /* XREF_T */
#ifndef REREFENCE_T
#define REREFENCE_T
typedef struct {
size_t object_num;
size_t generation_num;
} reference_t;
#endif /* REREFENCE_T */
#define XREF_TYPE_UNSET 0
#define XREF_TYPE_TABLE 1
#define XREF_TYPE_STREAM 2
typedef struct {
FILE *file;
short pdf_x, /* numbers from PDF header */
pdf_y; /* %PDF-<pdf_x>.<pdf_y> */
short xref_type;
xref_t *xref;
size_t file_size;
size_t pdf_start_offset; /* offset of %PDF-x.y */
size_t startxref;
FILE *file;
short pdf_x, /* numbers from PDF header */
pdf_y; /* %PDF-<pdf_x>.<pdf_y> */
short xref_type;
xref_t *xref;
reference_t ref_catalog_dict;
size_t file_size;
size_t pdf_start_offset; /* offset of %PDF-x.y */
size_t startxref;
} sigil_t;
sigil_err_t sigil_init(sigil_t **sgl);
......
......@@ -18,6 +18,8 @@
typedef struct {
xref_entry_t **entry;
size_t capacity;
size_t size_from_trailer;
size_t prev_section;
} xref_t;
#endif /* XREF_T */
......
......@@ -47,6 +47,60 @@ sigil_err_t skip_leading_whitespaces(FILE *in)
return (sigil_err_t)ERR_NO;
}
sigil_err_t skip_dictionary(FILE *in)
{
sigil_err_t err;
char c;
err = skip_leading_whitespaces(in);
if (err != ERR_NO)
return err;
while ((c = fgetc(in)) != EOF) {
switch (c) {
case '>':
if (fgetc(in) == '>')
return (sigil_err_t)ERR_NO;
break;
case '<':
if (fgetc(in) != '<')
break;
if ((err = skip_dictionary(in)) != ERR_NO)
return err;
return (sigil_err_t)ERR_NO;
default:
break;
}
}
return (sigil_err_t)ERR_PDF_CONT;
}
sigil_err_t skip_dict_unknown_value(FILE *in)
{
sigil_err_t err;
char c;
while ((c = fgetc(in)) != EOF) {
switch (c) {
case '/':
if (ungetc(c, in) != c)
return (sigil_err_t)ERR_IO;
return (sigil_err_t)ERR_NO;
case '<':
if (fgetc(in) != '<')
break;
if ((err = skip_dictionary(in)) != ERR_NO)
return err;
return (sigil_err_t)ERR_NO;
default:
break;
}
}
return (sigil_err_t)ERR_PDF_CONT;
}
sigil_err_t parse_number(FILE *in, size_t *number)
{
char_t c;
......@@ -141,6 +195,87 @@ sigil_err_t parse_free_indicator(FILE *in, free_indicator_t *result)
}
}
sigil_err_t parse_indirect_reference(FILE *in, reference_t *ref)
{
sigil_err_t err;
err = parse_number(in, &ref->object_num);
if (err != ERR_NO)
return err;
err = parse_number(in, &ref->generation_num);
if (err != ERR_NO)
return err;
err = skip_leading_whitespaces(in);
if (err != ERR_NO)
return err;
if (fgetc(in) != 'R')
return (sigil_err_t)ERR_PDF_CONT;
return (sigil_err_t)ERR_NO;
}
// parse the key of the couple key - value in the dictionary
sigil_err_t parse_dict_key(FILE *in, dict_key_t *dict_key)
{
sigil_err_t err;
const int dict_key_max = 10;
int count = 0;
char tmp[dict_key_max],
c;
sigil_zeroize(tmp, dict_key_max * sizeof(*tmp));
err = skip_leading_whitespaces(in);
if (err != ERR_NO)
return err;
if ((c = fgetc(in)) == EOF)
return 1;
switch (c) {
case '/':
break;
case '>':
if ((c = fgetc(in)) == '>')
return (sigil_err_t)ERR_PDF_CONT;
if (ungetc(c, in) != c)
return (sigil_err_t)ERR_IO;
return (sigil_err_t)ERR_PDF_CONT;
default:
return (sigil_err_t)ERR_PDF_CONT;
}
while ((c = fgetc(in)) != EOF) {
if (is_whitespace(c)) {
if (count <= 0)
return (sigil_err_t)ERR_PDF_CONT;
if (ungetc(c, in) != c)
return (sigil_err_t)ERR_IO;
if (strncmp(tmp, "Size", 4) == 0) {
*dict_key = DICT_KEY_Size;
return (sigil_err_t)ERR_NO;
}
if (strncmp(tmp, "Prev", 4) == 0) {
*dict_key = DICT_KEY_Prev;
return (sigil_err_t)ERR_NO;
}
if (strncmp(tmp, "Root", 4) == 0) {
*dict_key = DICT_KEY_Root;
return (sigil_err_t)ERR_NO;
}
*dict_key = DICT_KEY_unknown;
return (sigil_err_t)ERR_NO;
} else {
if (count >= dict_key_max - 1)
return (sigil_err_t)ERR_ALLOC;
tmp[count] = c;
count++;
}
}
return (sigil_err_t)ERR_PDF_CONT;
}
void print_module_name(const char *module_name, int verbosity)
{
if (verbosity < 1)
......
......@@ -21,14 +21,16 @@ sigil_err_t sigil_init(sigil_t **sgl)
return (sigil_err_t)ERR_ALLOC;
// set default values
(*sgl)->file = NULL;
(*sgl)->pdf_x = 0;
(*sgl)->pdf_y = 0;
(*sgl)->xref_type = XREF_TYPE_UNSET;
(*sgl)->xref = NULL;
(*sgl)->file_size = 0;
(*sgl)->pdf_start_offset = 0;
(*sgl)->startxref = 0;
(*sgl)->file = NULL;
(*sgl)->pdf_x = 0;
(*sgl)->pdf_y = 0;
(*sgl)->xref_type = XREF_TYPE_UNSET;
(*sgl)->xref = NULL;
(*sgl)->ref_catalog_dict.object_num = 0;
(*sgl)->ref_catalog_dict.generation_num = 0;
(*sgl)->file_size = 0;
(*sgl)->pdf_start_offset = 0;
(*sgl)->startxref = 0;
return (sigil_err_t)ERR_NO;
}
......
......@@ -2,12 +2,14 @@
#include "auxiliary.h"
#include "error.h"
#include "sigil.h"
#include "xref.h"
sigil_err_t process_trailer(sigil_t *sgl)
{
sigil_err_t err;
keyword_t keyword;
dict_key_t dict_key;
// function parameter checks
if (sgl == NULL || sgl->file == NULL)
......@@ -20,10 +22,44 @@ sigil_err_t process_trailer(sigil_t *sgl)
if (keyword != KEYWORD_trailer)
return (sigil_err_t)ERR_PDF_CONT;
err = skip_leading_whitespaces(sgl->file);
if (err != ERR_NO)
return err;
// if merged into one if statement with the '&&' operator in between, it's
// optimized out and position in the file is not changed
if (fgetc(sgl->file) != '<')
return 1;
if (fgetc(sgl->file) != '<')
return 1;
// TODO
while ((err = parse_dict_key(sgl->file, &dict_key)) == ERR_NO) {
switch (dict_key) {
case DICT_KEY_Size:
err = parse_number(sgl->file, &sgl->xref->size_from_trailer);
if (err != ERR_NO)
return err;
break;
case DICT_KEY_Prev:
err = parse_number(sgl->file, &sgl->xref->prev_section);
if (err != ERR_NO)
return err;
break;
case DICT_KEY_Root:
err = parse_indirect_reference(sgl->file, &sgl->ref_catalog_dict);
if (err != ERR_NO)
return err;
break;
case DICT_KEY_unknown:
err = skip_dict_unknown_value(sgl->file);
if (err != ERR_NO)
return err;
break;
default:
return (sigil_err_t)ERR_PDF_CONT;
}
}
return 0;
return err;
}
int sigil_trailer_self_test(int verbosity)
......
......@@ -81,8 +81,10 @@ xref_t *xref_init()
free(xref);
return NULL;
}
xref->capacity = XREF_PREALLOCATION;
sigil_zeroize(xref->entry, sizeof(xref_entry_t *) * xref->capacity);
xref->capacity = XREF_PREALLOCATION;
xref->size_from_trailer = 0;
xref->prev_section = 0;
return xref;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment