From 8fb2c88aedce9586959b2fe727766b461b4f9c27 Mon Sep 17 00:00:00 2001 From: "Fletcher T. Penney" Date: Wed, 12 Jul 2017 00:05:01 -0400 Subject: [PATCH] ADDED: Add functions to insert/replace metadata --- .../include/libMultiMarkdown.h | 12 ++ Sources/libMultiMarkdown/mmd.c | 105 ++++++++++++++++++ Sources/libMultiMarkdown/writer.c | 1 + Sources/libMultiMarkdown/writer.h | 1 + 4 files changed, 119 insertions(+) diff --git a/Sources/libMultiMarkdown/include/libMultiMarkdown.h b/Sources/libMultiMarkdown/include/libMultiMarkdown.h index 8f53910..540a89d 100644 --- a/Sources/libMultiMarkdown/include/libMultiMarkdown.h +++ b/Sources/libMultiMarkdown/include/libMultiMarkdown.h @@ -119,6 +119,10 @@ char * mmd_string_metadata_keys(char * source); char * mmd_string_metavalue_for_key(char * source, const char * key); +/// Insert/replace metadata in string, returning new string +char * mmd_string_update_metavalue_for_key(const char * source, const char * key, const char * value); + + /* @@ -155,6 +159,10 @@ char * mmd_d_string_metadata_keys(DString * source); char * mmd_d_string_metavalue_for_key(DString * source, const char * key); +/// Insert/replace metadata value in DString +void mmd_d_string_update_metavalue_for_key(DString * source, const char * key, const char * value); + + /* @@ -236,6 +244,10 @@ char * mmd_engine_metadata_keys(mmd_engine * e); char * mmd_engine_metavalue_for_key(mmd_engine * e, const char * key); +/// Insert/replace metadata value in mmd_engine +void mmd_engine_update_metavalue_for_key(mmd_engine * e, const char * key, const char * value); + + /* diff --git a/Sources/libMultiMarkdown/mmd.c b/Sources/libMultiMarkdown/mmd.c index 3229e0c..227b2e6 100644 --- a/Sources/libMultiMarkdown/mmd.c +++ b/Sources/libMultiMarkdown/mmd.c @@ -2143,6 +2143,111 @@ char * mmd_engine_metavalue_for_key(mmd_engine * e, const char * key) { } +/// Insert/replace metadata in string, returning new string +char * mmd_string_update_metavalue_for_key(const char * source, const char * key, const char * value) { + mmd_engine * e = mmd_engine_create_with_string(source, 0); + mmd_engine_update_metavalue_for_key(e, key, value); + + DString * d = e->dstr; + + mmd_engine_free(e, false); + + char * result = d->str; + d_string_free(d, false); + + return result; +} + + +/// Insert/replace metadata value in DString +void mmd_d_string_update_metavalue_for_key(DString * source, const char * key, const char * value) { + mmd_engine * e = mmd_engine_create_with_dstring(source, 0); + mmd_engine_update_metavalue_for_key(e, key, value); + + mmd_engine_free(e, false); +} + + +/// Insert/replace metadata value in mmd_engine +void mmd_engine_update_metavalue_for_key(mmd_engine * e, const char * key, const char * value) { + bool has_meta = true; + size_t meta_end = 0; + + // Check for metadata and character + if (!mmd_engine_has_metadata(e, &meta_end)) + has_meta = false; + + // Get clean metadata key for match + char * clean = label_from_string(key); + + // Determine range to excise and replace + size_t start = -1; + size_t end = -1; + size_t len = -1; + + meta * m; + + for (int i = 0; i < e->metadata_stack->size; ++i) + { + m = stack_peek_index(e->metadata_stack, i); + + if (strcmp(clean, m->key) == 0) { + // We have a match + start = m->start; + } else if (start != -1) { + // We have already found a match + if (end == -1) { + // This is the next metadata key, so determine length + end = m->start; + } + } + } + + DString * temp = d_string_new(key); + d_string_append(temp, ":\t"); + d_string_append(temp, value); + d_string_append_c(temp, '\n'); + + if (start != -1) { + // We're replacing existing metadata + + // Figure out where to start + char * begin = &(e->dstr->str[start]); + + while (*begin != ':') + begin++; + + begin++; + + while (char_is_whitespace(*begin)) + begin++; + + start = begin - e->dstr->str; + + if (end == -1) { + // Replace until the end of the metadata (last key) + len = meta_end - start; + } else { + len = end - start; + } + + d_string_erase(e->dstr, start, len); + d_string_insert(e->dstr, start, "\n"); + d_string_insert(e->dstr, start, value); + } else if (meta_end != 0) { + // We're appending metadata at the end + d_string_insert(e->dstr, meta_end, temp->str); + } else { + // There is no metadata, so prepend before document + d_string_append_c(temp, '\n'); + d_string_prepend(e->dstr, temp->str); + } + + d_string_free(temp, true); + free(clean); +} + + /// Convert MMD text to specified format, with specified extensions, and language /// Returned char * must be freed char * mmd_string_convert(const char * source, unsigned long extensions, short format, short language) { diff --git a/Sources/libMultiMarkdown/writer.c b/Sources/libMultiMarkdown/writer.c index def2acd..914bbe0 100644 --- a/Sources/libMultiMarkdown/writer.c +++ b/Sources/libMultiMarkdown/writer.c @@ -1082,6 +1082,7 @@ meta * meta_new(const char * source, size_t key_start, size_t len) { m->key = label_from_string(key); free(key); m->value = NULL; + m->start = key_start; } return m; diff --git a/Sources/libMultiMarkdown/writer.h b/Sources/libMultiMarkdown/writer.h index 7771cf1..7d6594d 100644 --- a/Sources/libMultiMarkdown/writer.h +++ b/Sources/libMultiMarkdown/writer.h @@ -171,6 +171,7 @@ typedef struct fn_holder fn_holder; struct meta { char * key; char * value; + size_t start; UT_hash_handle hh; }; -- 2.40.0