ext/mmd/transclude.c in rmultimarkdown-6.2.2.1 vs ext/mmd/transclude.c in rmultimarkdown-6.4.0.1

- old
+ new

@@ -54,50 +54,15 @@ #include <stdio.h> #include <string.h> #include "d_string.h" +#include "file.h" #include "libMultiMarkdown.h" #include "transclude.h" -#if defined(__WIN32) - #include <windows.h> -#endif -#define kBUFFERSIZE 4096 // How many bytes to read at a time - - -/// strndup not available on all platforms -static char * my_strndup(const char * source, size_t n) { - if (source == NULL) { - return NULL; - } - - size_t len = 0; - char * result; - const char * test = source; - - // strlen is too slow if strlen(source) >> n - for (len = 0; len < n; ++len) { - if (test == '\0') { - break; - } - - test++; - } - - result = malloc(len + 1); - - if (result) { - memcpy(result, source, len); - result[len] = '\0'; - } - - return result; -} - - /// strdup() not available on all platforms static char * my_strdup(const char * source) { char * result = malloc(strlen(source) + 1); if (result) { @@ -106,195 +71,10 @@ return result; } -/// Windows can use either `\` or `/` as a separator -- thanks to t-beckmann on github -/// for suggesting a fix for this. -bool is_separator(char c) { - #if defined(__WIN32) - return c == '\\' || c == '/'; - #else - return c == '/'; - #endif -} - - -#ifdef TEST -void Test_is_separator(CuTest* tc) { - char * test = "a/\\"; - - #if defined(__WIN32) - CuAssertIntEquals(tc, false, is_separator(test[0])); - CuAssertIntEquals(tc, true, is_separator(test[1])); - CuAssertIntEquals(tc, true, is_separator(test[2])); - #else - CuAssertIntEquals(tc, false, is_separator(test[0])); - CuAssertIntEquals(tc, true, is_separator(test[1])); - CuAssertIntEquals(tc, false, is_separator(test[2])); - #endif -} -#endif - - -void add_trailing_sep(DString * path) { - #if defined(__WIN32) - char sep = '\\'; - #else - char sep = '/'; - #endif - - // Ensure that folder ends in separator - if (!is_separator(path->str[path->currentStringLength - 1])) { - d_string_append_c(path, sep); - } -} - -/// Combine directory and base filename to create a full path */ -char * path_from_dir_base(const char * dir, const char * base) { - if (!dir && !base) { - return NULL; - } - - - DString * path = NULL; - char * result = NULL; - - if ((base != NULL) && (is_separator(base[0]))) { - // We have an absolute path - path = d_string_new(base); - } else { - // We have a directory and relative path - path = d_string_new(dir); - - // Ensure that folder ends in separator - add_trailing_sep(path); - - // Append filename (if present) - if (base) { - d_string_append(path, base); - } - } - - result = path->str; - d_string_free(path, false); - - return result; -} - - -#ifdef TEST -void Test_path_from_dir_base(CuTest* tc) { - char dir[10] = "/foo"; - char base[10] = "bar"; - - char * path = path_from_dir_base(dir, base); - - #if defined(__WIN32) - CuAssertStrEquals(tc, "/foo\\bar", path); - #else - CuAssertStrEquals(tc, "/foo/bar", path); - #endif - - free(path); - strcpy(base, "/bar"); - - path = path_from_dir_base(dir, base); - - CuAssertStrEquals(tc, "/bar", path); - - free(path); - - path = path_from_dir_base(NULL, NULL); - CuAssertStrEquals(tc, NULL, path); -} -#endif - - -/// Separate filename and directory from a full path -/// -/// See http://stackoverflow.com/questions/1575278/function-to-split-a-filepath-into-path-and-file -void split_path_file(char ** dir, char ** file, const char * path) { - const char * slash = path, * next; - - #if defined(__WIN32) - const char sep[] = "\\/"; // Windows allows either variant - #else - const char sep[] = "/"; - #endif - - while ((next = strpbrk(slash + 1, sep))) { - slash = next; - } - - if (path != slash) { - slash++; - } - - *dir = my_strndup(path, slash - path); - *file = my_strdup(slash); -} - -#ifdef TEST -void Test_split_path_file(CuTest* tc) { - char * dir, * file; - - char * path = "/foo/bar.txt"; - split_path_file(&dir, &file, path); - - CuAssertStrEquals(tc, "/foo/", dir); - CuAssertStrEquals(tc, "bar.txt", file); - - path = "\\foo\\bar.txt"; - split_path_file(&dir, &file, path); - - #if defined(__WIN32) - CuAssertStrEquals(tc, "\\foo\\", dir); - CuAssertStrEquals(tc, "bar.txt", file); - #else - CuAssertStrEquals(tc, "", dir); - CuAssertStrEquals(tc, "\\foo\\bar.txt", file); - #endif -} -#endif - - -DString * scan_file(const char * fname) { - /* Read from a file and return a DString * - `buffer` will need to be freed elsewhere */ - - char chunk[kBUFFERSIZE]; - size_t bytes; - - FILE * file; - - #if defined(__WIN32) - int wchars_num = MultiByteToWideChar(CP_UTF8, 0, fname, -1, NULL, 0); - wchar_t wstr[wchars_num]; - MultiByteToWideChar(CP_UTF8, 0, fname, -1, wstr, wchars_num); - - if ((file = _wfopen(wstr, L"rb")) == NULL) { - #else - - if ((file = fopen(fname, "r")) == NULL ) { - #endif - - return NULL; - } - - DString * buffer = d_string_new(""); - - while ((bytes = fread(chunk, 1, kBUFFERSIZE, file)) > 0) { - d_string_append_c_array(buffer, chunk, bytes); - } - - fclose(file); - - return buffer; -} - - /// Recursively transclude source text, given a search directory. /// Track files to prevent infinite recursive loops void mmd_transclude_source(DString * source, const char * search_path, const char * source_path, short format, stack * parsed, stack * manifest) { DString * file_path; DString * buffer; @@ -465,14 +245,9 @@ // Strip metadata from buffer now that we have parsed it e = mmd_engine_create_with_dstring(buffer, EXT_TRANSCLUDE); if (mmd_engine_has_metadata(e, &offset)) { d_string_erase(buffer, 0, offset); - } else { - // Do we need to strip BOM? - if (strncmp(buffer->str, "\xef\xbb\xbf", 3) == 0) { - d_string_erase(buffer, 0, 3); - } } mmd_engine_free(e, false); // Insert file text -- this may cause d_string to reallocate the