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