Here is a patch for new method pdf_fsys_build_path(). I tested it on GNU/Linux. Could anyone test it under win32 ?
## # Bazaar merge directive format 2 (Bazaar 0.90) # revision_id: [email protected] # target_branch: file:///home/gerel/PROJECTS/libgnupdf/trunk/ # testament_sha1: e9d9bb5584be247e80a81c85a2a68ccac71b6027 # timestamp: 2010-04-19 14:04:40 -0300 # base_revision_id: [email protected] # # Begin patch === modified file 'ChangeLog' --- ChangeLog 2010-04-18 11:13:22 +0000 +++ ChangeLog 2010-04-19 17:04:36 +0000 @@ -1,3 +1,24 @@ +2010-04-19 Gerardo E. Gidoni <[email protected]> + + Added pdf_fsys_build_path() method. + * doc/gnupdf.texi: updated documentation. + + * src/base/pdf-fsys-def.h: disk implementation. + + * src/base/pdf-fsys-disk.c: likewise. + + * src/base/pdf-fsys-disk.h: likewise. + + * src/base/pdf-fsys.c: fsys implementation. + + * src/base/pdf-fsys.h: likewise. + + * torture/unit/Makefile.am: method new test. + + * torture/unit/base/fsys/tsuite-fsys.c: likewise. + + * torture/unit/base/fsys/pdf-fsys-build-path.c: likewise. + 2010-04-15 Jose E. Marchesi <[email protected]> Remove spurious blank lines before EOF in the codebase. === modified file 'doc/gnupdf.texi' --- doc/gnupdf.texi 2010-04-13 20:50:45 +0000 +++ doc/gnupdf.texi 2010-04-19 17:04:36 +0000 @@ -8841,6 +8841,45 @@ @end table @end deftypefun + +...@deftypefun pdf_status_t pdf_fsys_build_path (pdf_fsys_t @var{filesystem}, pdf_text_t *...@var{output}, pdf_text_t @var{first_name}, ...) + +Build a file path by concatenating first_name with the following +variable-length list of @code{pdf_text_t} objects, store resulting path in @var{output}. + +...@table @strong +...@item Parameters +...@table @var +...@item filesystem +A filesystem. If @code{NULL} the default filesystem is used. +...@item output +A pdf_text_t pointer where the resulting path name will be stored. +...@item first_name +First text path component. +...@item ... +Variable-length pdf_text_t object list, last element must be NULL. +...@end table +...@item Returns +Returns PDF_OK if operation succeeded and @var{output} points to built path. +...@item Usage example +...@example +pdf_status_t st; +pdf_text_t full_path = NULL; +pdf_text_t filename = NULL; +pdf_text_t parent_path = get_current_dir_as_text (); /* example */ + +pdf_text_new_from_from_unicode ("filename.txt", strlen ("filename.txt"), + PDF_TEXT_UTF8, &filename); +st = pdf_fsys_build_path (NULL, &full_path, parent_dir, filename); +if (st != PDF_OK) +...@{ + /* ... */ +...@} +...@end example +...@end table +...@end deftypefun + + @node The File Interface @subsection The File Interface @@ -9793,6 +9832,21 @@ system interface function. @end deftp +typedef pdf_status_t (*pdf_fsys_build_path_fn_t) (void * data, + pdf_text_t * output, + pdf_text_t first_element, + pdf_list_t rest); + + +...@deftp {Data Type} {pdf_status_t (*pdf_fsys_build_path_fn_t) (void * @var{data}, pdf_text_t *...@var{output}, pdf_text_t @var{first_name}, pdf_list_t @var{rest})} + +Filesystem callback used to concatenate and build a file path. Where @var{rest} is a list of pdf_text_t objects. + +This callback is called by the @code{pdf_fsys_build_path} file +system interface function. +...@end deftp + + @node File Interface Implementation @subsubsection File Interface Implementation === modified file 'src/base/pdf-fsys-def.h' --- src/base/pdf-fsys-def.h 2010-02-20 16:02:07 +0000 +++ src/base/pdf-fsys-def.h 2010-04-19 17:04:36 +0000 @@ -51,6 +51,8 @@ pdf_fsys_disk_item_readable_p (NULL, (path_name)) #define pdf_fsys_def_item_writable_p(path_name) \ pdf_fsys_disk_item_writable_p (NULL, (path_name)) +#define pdf_fsys_def_build_path(output, first_element, rest) \ + pdf_fsys_disk_build_path (NULL, (output), (first_element), (rest)) #define pdf_fsys_def_file_open(path_name, mode, p_file) \ pdf_fsys_disk_file_open (NULL, (path_name), (mode), (p_file)) #define pdf_fsys_def_file_open_tmp(p_file) \ === modified file 'src/base/pdf-fsys-disk.c' --- src/base/pdf-fsys-disk.c 2010-04-15 15:07:50 +0000 +++ src/base/pdf-fsys-disk.c 2010-04-19 17:04:36 +0000 @@ -893,6 +893,72 @@ return result; } +pdf_status_t +pdf_fsys_disk_build_path (void *data, + pdf_text_t * output, + pdf_text_t first_element, + pdf_list_t rest) +{ + pdf_list_iterator_t itr; + pdf_text_t next, text_sep; + pdf_status_t st, st2; + + st = pdf_list_iterator (rest, &itr); + if (st != PDF_OK) + { + return st; + } + + *output = pdf_text_dup (first_element); + if (*output == NULL) + { + pdf_list_iterator_free (&itr); + return PDF_ENOMEM; + } + +#if FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR + st = pdf_text_new_from_unicode ((pdf_char_t*)"\\",1,PDF_TEXT_UTF8, &text_sep); +#else + st = pdf_text_new_from_unicode ((pdf_char_t*)"/",1,PDF_TEXT_UTF8, &text_sep); +#endif /* FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR */ + + if (st != PDF_OK) + { + pdf_list_iterator_free (&itr); + pdf_text_destroy(*output); + return st; + } + + /* Concatenate separator and next text object */ + st = pdf_list_iterator_next (&itr, (const void **) &next, NULL); + while (st == PDF_OK) + { + st2 = pdf_text_concat (*output, text_sep, PDF_TRUE); + if (st2 != PDF_OK) + { + pdf_list_iterator_free (&itr); + pdf_text_destroy(*output); + pdf_text_destroy (text_sep); + return st2; + } + + st2 = pdf_text_concat (*output, next, PDF_TRUE); + if (st2 != PDF_OK) + { + pdf_list_iterator_free (&itr); + pdf_text_destroy(*output); + pdf_text_destroy (text_sep); + return st2; + } + st = pdf_list_iterator_next (&itr, (const void **) &next, NULL); + } + + pdf_list_iterator_free (&itr); + pdf_text_destroy (text_sep); + return PDF_OK; +} + + /* * File Interface Implementation */ === modified file 'src/base/pdf-fsys-disk.h' --- src/base/pdf-fsys-disk.h 2010-02-20 16:02:07 +0000 +++ src/base/pdf-fsys-disk.h 2010-04-19 17:04:36 +0000 @@ -100,6 +100,11 @@ pdf_fsys_disk_item_writable_p (void *data, pdf_text_t path_name); +pdf_status_t +pdf_fsys_disk_build_path (void *data, + pdf_text_t * output, + pdf_text_t first_element, + pdf_list_t rest); /* --------------------- File interface ------------------------- */ === modified file 'src/base/pdf-fsys.c' --- src/base/pdf-fsys.c 2010-02-20 16:02:07 +0000 +++ src/base/pdf-fsys.c 2010-04-19 17:04:36 +0000 @@ -296,6 +296,55 @@ } } +pdf_status_t pdf_fsys_build_path (pdf_fsys_t filesystem, + pdf_text_t * output, + pdf_text_t first_element, ...) +{ + va_list args; + pdf_list_t rest; + pdf_status_t st; + pdf_text_t next; + + st = pdf_list_new (NULL,NULL,PDF_TRUE,&rest); + if (st != PDF_OK) + { + return st; + } + + /* Save the rest text objects */ + va_start (args, first_element); + next = va_arg (args, pdf_text_t); + while (next != NULL) + { + st = pdf_list_add_last (rest, next, NULL); + if (st != PDF_OK) + { + pdf_list_destroy (rest); + va_end (args); + return st; + } + + next = va_arg (args, pdf_text_t); + } + va_end (args); + + if (filesystem == NULL) + { + /* Use the default filesystem */ + st = pdf_fsys_def_build_path (output, first_element, rest); + } + else + { + st = filesystem->implementation->build_path_fn (filesystem->data, + output, first_element, + rest); + } + + pdf_list_destroy (rest); + return st; +} + + /* * File Interface Implementation */ === modified file 'src/base/pdf-fsys.h' --- src/base/pdf-fsys.h 2010-02-20 16:02:07 +0000 +++ src/base/pdf-fsys.h 2010-04-19 17:04:36 +0000 @@ -28,6 +28,7 @@ #include <config.h> +#include <stdarg.h> #include <pdf-types.h> #include <pdf-list.h> #include <pdf-hash.h> @@ -125,6 +126,10 @@ pdf_text_t path_name); typedef pdf_bool_t (*pdf_fsys_item_writable_p_fn_t) (void *data, pdf_text_t path_name); +typedef pdf_status_t (*pdf_fsys_build_path_fn_t) (void * data, + pdf_text_t * output, + pdf_text_t first_element, + pdf_list_t rest); typedef pdf_status_t (*pdf_fsys_file_read_fn_t) (pdf_fsys_file_t file, pdf_char_t *buf, @@ -183,6 +188,7 @@ pdf_fsys_item_readable_p_fn_t item_readable_p_fn; pdf_fsys_item_writable_p_fn_t item_writable_p_fn; pdf_fsys_file_get_url_fn_t file_get_url_fn; + pdf_fsys_build_path_fn_t build_path_fn; /* File interface callbacks */ pdf_fsys_file_open_fn_t file_open_fn; @@ -234,6 +240,9 @@ pdf_text_t path_name); pdf_bool_t pdf_fsys_item_writable_p (pdf_fsys_t filesystem, pdf_text_t path_name); +pdf_status_t pdf_fsys_build_path (pdf_fsys_t filesystem, + pdf_text_t * output, + pdf_text_t first_element, ...); /* File Interface */ pdf_status_t pdf_fsys_file_open (const pdf_fsys_t filesystem, === modified file 'torture/unit/Makefile.am' --- torture/unit/Makefile.am 2010-02-19 01:03:33 +0000 +++ torture/unit/Makefile.am 2010-04-19 17:04:36 +0000 @@ -230,7 +230,8 @@ TEST_SUITE_FSYS = base/fsys/pdf-fsys-get-free-space.c \ base/fsys/pdf-fsys-file-open.c \ base/fsys/pdf-fsys-file-open-tmp.c \ - base/fsys/pdf-fsys-file-close.c + base/fsys/pdf-fsys-file-close.c \ + base/fsys/pdf-fsys-build-path.c TEST_SUITE_TOKEN = base/token/pdf-token-read.c === added file 'torture/unit/base/fsys/pdf-fsys-build-path.c' --- torture/unit/base/fsys/pdf-fsys-build-path.c 1970-01-01 00:00:00 +0000 +++ torture/unit/base/fsys/pdf-fsys-build-path.c 2010-04-19 17:04:36 +0000 @@ -0,0 +1,88 @@ +/* -*- mode: C -*- + * + * File: pdf-fsys-build-path.c + * Date: Mon Apr 16 00:02:09 2010 + * + * GNU PDF Library - Unit tests for pdf_fsys_build_path + * + */ + +/* Copyright (C) 2010 Free Software Foundation, Inc. */ + +/* This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include <string.h> +#include <tortutils.h> +#include <check.h> + +#include <pdf.h> + +/* + * Test: pdf_fsys_build_path_001 + * Description: + * Build a path name from two text objects + * Success condition: + * The call to pdf_fsys_build_path should return PDF_OK + */ + +START_TEST(pdf_fsys_build_path_001) +{ + pdf_text_t text1,text2,text3,result; + pdf_char_t *first="want",*dir="some",*dirr="beer?", *output_data=NULL; + + /* Always INIT! Check runs each test in a different process */ + fail_if(pdf_init() != PDF_OK); + + fail_if(pdf_text_new_from_unicode(first, 4, PDF_TEXT_UTF8, &text1) != PDF_OK); + fail_if(pdf_text_new_from_unicode(dir, 4, PDF_TEXT_UTF8, &text2) != PDF_OK); + fail_if(pdf_text_new_from_unicode(dirr, 5, PDF_TEXT_UTF8, &text3) != PDF_OK); + + fail_if(pdf_fsys_build_path (NULL, &result, text1, text2, text3, NULL) + != PDF_OK); + + fail_if(pdf_text_get_pdfdocenc(&output_data, result) != PDF_OK); + +#if FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR + fail_unless(strcmp((char *)output_data, "want\\some\\beer?" ) == 0); + fail_unless(strlen((char *)output_data) == strlen("want\\some\\beer?")); +#else + fail_unless(strcmp((char *)output_data, "want/some/beer?" ) == 0); + fail_unless(strlen((char *)output_data) == strlen("want/some/beer?")); +#endif /* FILE_SYSTEM_BACKSLASH_IS_FILE_NAME_SEPARATOR */ + + + pdf_text_destroy (text1); + pdf_text_destroy (text2); + pdf_text_destroy (text3); + pdf_dealloc (output_data); +} +END_TEST + + +/* + * Test case creation function + */ +TCase * +test_pdf_fsys_build_path (void) +{ + TCase *tc = tcase_create("pdf_fsys_build_path"); + tcase_add_test(tc, pdf_fsys_build_path_001); + return tc; +} + + +/* End of pdf-fsys-build-path.c */ === modified file 'torture/unit/base/fsys/tsuite-fsys.c' --- torture/unit/base/fsys/tsuite-fsys.c 2010-02-20 16:02:07 +0000 +++ torture/unit/base/fsys/tsuite-fsys.c 2010-04-19 17:04:36 +0000 @@ -31,7 +31,7 @@ extern TCase *test_pdf_fsys_file_open (void); extern TCase *test_pdf_fsys_file_open_tmp (void); extern TCase *test_pdf_fsys_file_close (void); - +extern TCase *test_pdf_fsys_build_path (void); Suite * tsuite_fsys () @@ -44,6 +44,7 @@ suite_add_tcase (s, test_pdf_fsys_file_open ()); suite_add_tcase (s, test_pdf_fsys_file_open_tmp ()); suite_add_tcase (s, test_pdf_fsys_file_close ()); + suite_add_tcase (s, test_pdf_fsys_build_path ()); return s; } # Begin bundle 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 ### cheers, -gerel
