I've attached an updated version of the tokeniser documentation patch. I'll start restructuring the code to match that API too (except the token writer, since no such code has been written yet).
-- Michael
# Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: [email protected] # target_branch: file:///home/michael/src/%2Blocal/gnupdf/trunk/ # testament_sha1: 011b95bf4eeb5915cbc734ecb1ef3cff68f40abd # timestamp: 2009-05-19 14:08:23 -0400 # base_revision_id: jema...@termi-20090519150413-24yqb698xya3v1vh # # Begin patch === modified file 'AUTHORS' --- AUTHORS 2009-05-10 15:00:33 +0000 +++ AUTHORS 2009-05-19 18:03:37 +0000 @@ -262,7 +262,7 @@ torture/test-stm_openclose.c Michael Gold: changed src/Makefile.am utils/Makefile.am - torture/unit/Makefile.am + torture/unit/Makefile.am src/gnupdf.texi Yang Chang Hua: wrote src/base/pdf-stm-f-dct.h src/base/pdf-stm-f-dct.c === modified file 'ChangeLog' --- ChangeLog 2009-05-19 15:04:13 +0000 +++ ChangeLog 2009-05-19 18:07:04 +0000 @@ -1,3 +1,7 @@ +2009-05-19 Michael Gold <[email protected]> + + * doc/gnupdf.texi: Expanded the tokeniser API documentation. + 2009-05-19 Jose E. Marchesi <[email protected]> * src/base/pdf-stm.c: converted to Unix from DOS codification. === modified file 'doc/gnupdf.texi' --- doc/gnupdf.texi 2009-05-18 13:36:47 +0000 +++ doc/gnupdf.texi 2009-05-19 18:03:37 +0000 @@ -9866,7 +9866,8 @@ * Creation and destruction of tokenisers:: * Reading tokens:: * Writing tokens:: -* Manipulating PDF tokens:: +* Creating and destroying tokens:: +* Accessing token attributes:: @end menu @node Tokeniser data types @@ -9882,20 +9883,31 @@ Valid values are: @table @code -...@item PDF_TOKEN_BOOLEAN -A PDF boolean value. -...@item PDF_TOKEN_NUMBER -A PDF number value. -...@item PDF_TOKEN_NULL -The null PDF object. +...@item PDF_TOKEN_INTEGER +A PDF integer value. +...@item PDF_TOKEN_REAL +A PDF real value (a floating-point number). @item PDF_TOKEN_STRING -A PDF string value. +A PDF string. @item PDF_TOKEN_NAME -A PDF name value. -...@item PDF_TOKEN_INDIRECT -A PDF indirect reference. +A PDF name. @item PDF_TOKEN_COMMENT A PDF comment. +...@item PDF_TOKEN_KEYWORD +A keyword, i.e., any string of regular characters such as ``null'' +or ``R'' that is not matched as another type. +...@item PDF_TOKEN_DICT_START +The ``<<'' operator, which marks the beginning of a dictionary. +...@item PDF_TOKEN_DICT_END +The ``>>'' operator, which marks the end of a dictionary. +...@item PDF_TOKEN_ARRAY_START +The ``['' operator, which marks the beginning of an array. +...@item PDF_TOKEN_ARRAY_END +The ``]'' operator, which marks the end of an array. +...@item PDF_TOKEN_PROC_START +The `...@{'' operator, which marks the beginning of a procedure. +...@item PDF_TOKEN_PROC_END +The `...@}'' operator, which marks the end of a procedure. @end table @end deftp @@ -10034,7 +10046,7 @@ @end table @end deftypefun -...@deftypefun pdf_status_t pdf_tokeniser_reader_destroy (pdf_tokeniser_reader_t @var{reader}) +...@deftypefun pdf_status_t pdf_token_reader_destroy (pdf_token_reader_t @var{reader}) Destroy a token reader freeing any used resources. @@ -10062,9 +10074,9 @@ @end table @end deftypefun -...@deftypefun pdf_status_t pdf_tokeniser_writer_destroy (pdf_tokeniser_writer_t @var{writer}) +...@deftypefun pdf_status_t pdf_token_writer_destroy (pdf_token_writer_t @var{writer}) -Destroy a token writer freeing any used resources. +Destroy a token writer, freeing any used resources. @table @strong @item Parameters @@ -10093,7 +10105,7 @@ @node Reading tokens @subsection Reading tokens -...@deftypefun pdf_status_t pdf_token_read (pdf_token_reader_t @var{reader}, pdf_token_t *...@var{token}) +...@deftypefun pdf_status_t pdf_token_read (pdf_token_reader_t @var{reader}, pdf_u32_t @var{flags}, pdf_token_t *...@var{token}) Read a token from a token reader. @@ -10102,15 +10114,40 @@ @table @var @item reader A token reader. +...@item flags +A bitmask specifying a combination of these flags: +...@table @code +...@item PDF_TOKEN_NO_NAME_ESCAPES +Don't treat ``#'' as a special character when reading name tokens +(this flag should be used when reading PDF 1.1 files). +...@item PDF_TOKEN_RET_COMMENTS +Return comments as tokens (rather than ignoring them). +...@item PDF_TOKEN_END_AT_STREAM +Assume that a ``stream'' keyword token was just read, find the beginning +of the corresponding stream, and return PDF_EEOF when successful +(i.e., when the input stream is positioned after the first line feed). +...@end table @item token -A pointer to a token that will hold the read token. +A pointer to a pdf_token_t that will hold the read token. @end table @item Returns A PDF status value: @table @code @item PDF_OK +The operation succeeded. @item PDF_EAGAIN +It's not possible to read a full token now. +Since one may have been partially read, the operation should be repeated +with the same flags when data becomes available. +...@item PDF_EEOF +Reached the end of the input stream (at a valid position). +...@item PDF_EBADFILE +The stream violates the PDF specifications. +...@item PDF_EIMPLLIMIT +It's not possible to read the next token without exceeding an +implementation limit (e.g., the token is too long). @item PDF_ERROR +An unspecified error occurred. @end table @item Usage example @example @@ -10119,13 +10156,29 @@ @end table @end deftypefun -...@c pdf_token_reader_end_at_stream -...@c pdf_token_reader_reset_state +...@deftypefun pdf_status_t pdf_token_reader_reset (pdf_token_reader_t @var{reader}) + +Reset the state of the token reader. + +...@table @strong +...@item Parameters +...@table @var +...@item reader +A token reader. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@end table +...@end table +...@end deftypefun @node Writing tokens @subsection Writing tokens -...@deftypefun pdf_status_t pdf_token_write (pdf_token_writer_t @var{writer}, pdf_token_t *...@var{token}) +...@deftypefun pdf_status_t pdf_token_write (pdf_token_writer_t @var{writer}, pdf_u32_t @var{flags}, pdf_token_t @var{token}) Write a given token using a given token writer. @@ -10134,6 +10187,18 @@ @table @var @item writer A token writer. +...@item flags +A bitmask specifying a combination of these flags: +...@table @code +...@item PDF_TOKEN_NO_NAME_ESCAPES +Don't escape special characters using ``#'' when writing name tokens +(this flag should be used when writing PDF 1.1 files). +...@item PDF_TOKEN_HEX_STRINGS +Write strings in hexadecimal encoding. +...@item PDF_TOKEN_READABLE_STRINGS +Encode strings in a human-readable way +(i.e., in hexadecimal or with special characters escaped). +...@end table @item token A PDF token. @end table @@ -10141,8 +10206,16 @@ A PDF status value: @table @code @item PDF_OK +The operation succeeded. @item PDF_EAGAIN +It's not possible to write a full token now. +Since it may have been partially written, the operation must be repeated +with the same arguments when the stream becomes writable. +...@item PDF_EBADDATA +One of the arguments is invalid. This may be caused by an invalid token +(e.g., one that contains unrepresentable characters). @item PDF_ERROR +An unspecified error occurred. @end table @item Usage example @example @@ -10151,10 +10224,247 @@ @end table @end deftypefun -...@c pdf_token_write - -...@node Manipulating PDF tokens -...@subsection Manipulating PDF tokens +...@node Creating and destroying tokens +...@subsection Creating and destroying tokens + +...@deftypefun pdf_status_t pdf_token_integer_new (pdf_i32_t @var{value}, pdf_token_t *...@var{token}) + +Create an integer token. + +...@table @strong +...@item Parameters +...@table @var +...@item value +The numeric value for the token. +...@item token +A pointer to the newly created token. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@item PDF_ENOMEM +Not enough memory. +...@end table +...@end table + +...@end deftypefun + +...@deftypefun pdf_status_t pdf_token_real_new (pdf_real_t @var{value}, pdf_token_t *...@var{token}) + +Create a real (floating-point number) token. + +...@table @strong +...@item Parameters +...@table @var +...@item value +The numeric value for the token. +...@item token +A pointer to the newly created token. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@item PDF_EBADDATA +The given value is invalid. +...@item PDF_ENOMEM +Not enough memory. +...@end table +...@end table + +...@end deftypefun + +...@deftypefun pdf_status_t pdf_token_string_new (const pdf_char_t *...@var{value}, pdf_size_t @var{size}, pdf_token_t *...@var{token}) + +Create a string token containing a copy of the given data. + +...@table @strong +...@item Parameters +...@table @var +...@item value +A pointer to the binary data that will make up the string. +...@item size +The amount of data to copy, in octets. +...@item token +A pointer to the newly created token. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@item PDF_ENOMEM +Not enough memory. +...@end table +...@end table + +...@end deftypefun + +...@deftypefun pdf_status_t pdf_token_name_new (const pdf_char_t *...@var{value}, pdf_size_t @var{size}, pdf_token_t *...@var{token}) + +Create a name token containing a copy of the given data. + +...@table @strong +...@item Parameters +...@table @var +...@item value +A pointer to the binary data that will make up the name. +...@item size +The amount of data to copy, in octets. +...@item token +A pointer to the newly created token. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@item PDF_EBADDATA +The given value is invalid. +...@item PDF_ENOMEM +Not enough memory. +...@end table +...@end table + +...@end deftypefun + +...@deftypefun pdf_status_t pdf_token_keyword_new (const pdf_char_t *...@var{value}, pdf_size_t @var{size}, pdf_token_t *...@var{token}) + +Create a keyword token containing a copy of the given data. + +...@table @strong +...@item Parameters +...@table @var +...@item value +A pointer to the binary data that will make up the keyword. +...@item size +The amount of data to copy, in octets. +...@item token +A pointer to the newly created token. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@item PDF_EBADDATA +The given value is invalid. +...@item PDF_ENOMEM +Not enough memory. +...@end table +...@end table + +...@end deftypefun + +...@deftypefun pdf_status_t pdf_token_comment_new (const pdf_char_t *...@var{value}, pdf_size_t @var{size}, pdf_bool_t continuation, pdf_token_t *...@var{token}) + +Create a comment token containing a copy of the given data. + +...@table @strong +...@item Parameters +...@table @var +...@item value +A pointer to the binary data that will make up the keyword. +...@item size +The amount of data to copy, in octets. +...@item continuation +A boolean value indicating whether this is a continuation of a previous comment token (if false, it's a new comment). +...@item token +A pointer to the newly created token. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@item PDF_EBADDATA +The given value is invalid. +...@item PDF_ENOMEM +Not enough memory. +...@end table +...@end table + +...@end deftypefun + +...@deftypefun pdf_status_t pdf_token_valueless_new (enum pdf_token_type_e @var{type}, pdf_token_t *...@var{token}) + +Create a token of one of the valueless types (PDF_TOKEN_DICT_START, +PDF_TOKEN_DICT_END, PDF_TOKEN_ARRAY_START, PDF_TOKEN_ARRAY_END, +PDF_TOKEN_PROC_START, or PDF_TOKEN_PROC_END). + +...@table @strong +...@item Parameters +...@table @var +...@item type +The type of token to create. +...@item token +A pointer to the newly created token. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@item PDF_ENOMEM +Not enough memory. +...@item PDF_EBADDATA +The given type is not valid for this constructor. +...@end table +...@end table + +...@end deftypefun + +...@deftypefun pdf_status_t pdf_token_dup (const pdf_token_t @var{old}, pdf_token_t *...@var{new}) + +Create a copy of the given token. + +...@table @strong +...@item Parameters +...@table @var +...@item old +The token to copy. +...@item new +A pointer to the newly created token. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@item PDF_ENOMEM +Not enough memory. +...@end table +...@end table + +...@end deftypefun + +...@deftypefun pdf_status_t pdf_token_destroy (pdf_token_t @var{token}) + +Destroy the given token, freeing any memory it used. + +...@table @strong +...@item Parameters +...@table @var +...@item old +The token to copy. +...@item new +A pointer to the newly created token. +...@end table +...@item Returns +A PDF status value: +...@table @code +...@item PDF_OK +The operation succeeded. +...@end table +...@end table + +...@end deftypefun + +...@node Accessing token attributes +...@subsection Accessing token attributes @deftypefun {enum pdf_token_type_e} pdf_token_get_type (pdf_token_t @var{token}) @@ -10176,7 +10486,10 @@ /* ... */ /* Read a name */ -pdf_token_read (reader, &token); +if (pdf_token_read (reader, &token) != PDF_OK) +...@{ + /* Error */ +...@} if (pdf_token_get_type (token) != PDF_TOKEN_NAME) @{ /* We were expecting a name */ @@ -10185,39 +10498,197 @@ @end table @end deftypefun -...@deftypefun pdf_status_t pdf_token_set_attr (pdf_token_t @var{token}, pdf_token_attr_t @var{attr}) - -Set a given attribute @var{attr} in a given token. - -...@table @strong -...@item Parameters -...@table @var -...@item token -A token. -...@item attr -A token attribute. -...@end table -...@item Returns -A PDF status value: +...@c TODO: pdf_bool_t pdf_token_equal_p (pdf_token_t token1, pdf_token_t token2); +...@c -- if needed + +...@deftypefun pdf_i32_t pdf_token_get_integer_value (const pdf_token_t @var{token}) + +Returns the value associated with a given integer token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_INTEGER. +...@end table +...@item Returns +The token's value. +...@end table + +...@end deftypefun + +...@deftypefun pdf_real_t pdf_token_get_real_value (const pdf_token_t @var{token}) + +Returns the value associated with a given real token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_REAL. +...@end table +...@item Returns +The token's value. +...@end table + +...@end deftypefun + +...@deftypefun const pdf_char_t *pdf_token_get_string_data (const pdf_token_t @var{token}) + +Returns a pointer to the data associated with a given string token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_STRING. +...@end table +...@item Returns +A pointer to the data, which will be valid until the token is destroyed. +The data is @strong{not} null-terminated. +...@end table + +...@end deftypefun + +...@deftypefun pdf_size_t pdf_token_get_string_size (const pdf_token_t @var{token}) + +Returns the amount of data associated with a given string token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_STRING. +...@end table +...@item Returns +The string's size, in octets. +...@end table + +...@end deftypefun + +...@deftypefun const pdf_char_t *pdf_token_get_name_data (const pdf_token_t @var{token}) + +Returns a pointer to the data associated with a given name token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_NAME. +...@end table +...@item Returns +A pointer to the name data, which will be valid until the token is destroyed. +The data is null-terminated. +...@end table + +...@end deftypefun + +...@deftypefun pdf_size_t pdf_token_get_name_size (const pdf_token_t @var{token}) + +Returns the amount of data associated with a given name token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_NAME. +...@end table +...@item Returns +The name's size, in octets (excluding the terminating null byte). +...@end table + +...@end deftypefun + +...@deftypefun const pdf_char_t *pdf_token_get_keyword_data (const pdf_token_t @var{token}) + +Returns a pointer to the data associated with a given keyword token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_KEYWORD. +...@end table +...@item Returns +A pointer to the data, which will be valid until the token is destroyed. +The data is null-terminated. +...@end table + +...@end deftypefun + +...@deftypefun pdf_size_t pdf_token_get_keyword_size (const pdf_token_t @var{token}) + +Returns the amount of data associated with a given keyword token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_KEYWORD. +...@end table +...@item Returns +The keyword's size, in octets (excluding the terminating null byte). +...@end table + +...@end deftypefun + +...@deftypefun const pdf_char_t *pdf_token_get_comment_data (const pdf_token_t @var{token}) + +Returns a pointer to the data associated with a given comment token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_COMMENT. +...@end table +...@item Returns +A pointer to the data, which will be valid until the token is destroyed. +The data is @strong{not} null-terminated. +...@end table + +...@end deftypefun + +...@deftypefun pdf_size_t pdf_token_get_comment_size (const pdf_token_t @var{token}) + +Returns the amount of data associated with a given comment token. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_COMMENT. +...@end table +...@item Returns +The comment's size, in octets. +...@end table + +...@end deftypefun + +...@deftypefun pdf_bool_t pdf_token_get_comment_continued (const pdf_token_t @var{token}) + +Returns a boolean indicating whether the comment token is a continuation +of a previous token. If the token reader breaks a comment into multiple +tokens, each token except the last will be at least 32767 bytes long. + +...@table @strong +...@item Parameters +...@table @var +...@item token +A token of type PDF_TOKEN_COMMENT. +...@end table +...@item Returns +A boolean value: @table @code -...@item PDF_OK -...@item PDF_ERROR -...@end table -...@item Usage example -...@example -XXX -...@end example -...@end table +...@item PDF_TRUE +The given comment token is a continuation of another. +...@item PDF_FALSE +The token is a complete comment, or the beginning of a comment. +...@end table +...@end table + @end deftypefun -...@c pdf_token_get_string -...@c pdf_token_get_integer -...@c pdf_token_get_real - -...@c pdf_token_set_string -...@c pdf_token_set_integer -...@c pdf_token_set_real - @node Encryption @section Encryption @@ -13289,17 +13760,23 @@ @tab 10^10 bytes @tab Largest supported PDF file using a cross-reference table. @item integer -...@tab ??? +...@tab 2^32 - 1 @tab Largest integer value. +...@item integer +...@tab -2^32 +...@tab Smallest integer value. @item real -...@tab ??? +...@tab FLT_MAX @tab Largest real value. +...@item real +...@tab -FLT_MAX +...@tab Smallest real value. @item string in content stream @tab 32767 @tab Maximum length of a string contained in a content stream, in bytes. @item name -...@tab ??? +...@tab 32767 @tab Maximum length of a name, in bytes. @item indirect object @tab ?? # Begin bundle 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 REp/8XckU4UJD7OX2JA=
signature.asc
Description: Digital signature
