Unified the chapter and tag XML output code just like the parser code for both was unified a long time ago. Also output binary content of XML elements in hex format.

This commit is contained in:
Moritz Bunkus 2005-01-08 22:16:56 +00:00
parent 5d91d53bd9
commit 3bb0591e5c
5 changed files with 206 additions and 256 deletions

View File

@ -21,10 +21,10 @@
#include <matroska/KaxChapters.h> #include <matroska/KaxChapters.h>
#include "chapters.h"
#include "commonebml.h" #include "commonebml.h"
#include "mm_io.h" #include "mm_io.h"
#include "chapters.h" #include "xml_element_writer.h"
#include "xml_element_mapping.h"
using namespace std; using namespace std;
using namespace libmatroska; using namespace libmatroska;
@ -203,16 +203,8 @@ write_chapters_simple(int &chapter_num,
// {{{ XML chapter output // {{{ XML chapter output
typedef struct {
int level;
int parent_idx;
int elt_idx;
EbmlElement *e;
mm_io_c *out;
} chapter_writer_cb_t;
static void static void
pt(chapter_writer_cb_t *cb, pt(xml_writer_cb_t *cb,
const char *tag) { const char *tag) {
int i; int i;
@ -221,91 +213,6 @@ pt(chapter_writer_cb_t *cb,
cb->out->printf("%s", tag); cb->out->printf("%s", tag);
} }
static void
write_xml_element_rec(int level,
int parent_idx,
EbmlElement *e,
mm_io_c *out) {
EbmlMaster *m;
int elt_idx, i;
bool found;
string s;
elt_idx = parent_idx;
found = false;
while ((chapter_elements[elt_idx].name != NULL) &&
(chapter_elements[elt_idx].level >=
chapter_elements[parent_idx].level)) {
if (chapter_elements[elt_idx].id == e->Generic().GlobalId) {
found = true;
break;
}
elt_idx++;
}
for (i = 0; i < level; i++)
out->printf(" ");
if (!found) {
out->printf("<!-- Unknown element '%s' -->\n", e->Generic().DebugName);
return;
}
out->printf("<%s>", chapter_elements[elt_idx].name);
switch (chapter_elements[elt_idx].type) {
case EBMLT_MASTER:
out->printf("\n");
m = dynamic_cast<EbmlMaster *>(e);
assert(m != NULL);
for (i = 0; i < m->ListSize(); i++)
write_xml_element_rec(level + 1, elt_idx, (*m)[i], out);
if (chapter_elements[elt_idx].end_hook != NULL) {
chapter_writer_cb_t cb;
cb.level = level;
cb.parent_idx = parent_idx;
cb.elt_idx = elt_idx;
cb.e = e;
cb.out = out;
chapter_elements[elt_idx].end_hook(&cb);
}
for (i = 0; i < level; i++)
out->printf(" ");
out->printf("</%s>\n", chapter_elements[elt_idx].name);
break;
case EBMLT_UINT:
case EBMLT_BOOL:
out->printf("%llu</%s>\n", uint64(*dynamic_cast<EbmlUInteger *>(e)),
chapter_elements[elt_idx].name);
break;
case EBMLT_STRING:
s = escape_xml(string(*dynamic_cast<EbmlString *>(e)));
out->printf("%s</%s>\n", s.c_str(), chapter_elements[elt_idx].name);
break;
case EBMLT_USTRING:
s = UTFstring_to_cstrutf8(UTFstring(*static_cast
<EbmlUnicodeString *>(e)).c_str());
s = escape_xml(s);
out->printf("%s</%s>\n", s.c_str(), chapter_elements[elt_idx].name);
break;
case EBMLT_TIME:
out->printf(FMT_TIMECODEN "</%s>\n",
ARG_TIMECODEN(uint64(*dynamic_cast<EbmlUInteger *>(e))),
chapter_elements[elt_idx].name);
break;
default:
assert(false);
}
}
static int static int
cet_index(const char *name) { cet_index(const char *name) {
int i; int i;
@ -321,9 +228,9 @@ cet_index(const char *name) {
static void static void
end_write_chapter_atom(void *data) { end_write_chapter_atom(void *data) {
KaxChapterAtom *atom; KaxChapterAtom *atom;
chapter_writer_cb_t *cb; xml_writer_cb_t *cb;
cb = (chapter_writer_cb_t *)data; cb = (xml_writer_cb_t *)data;
atom = dynamic_cast<KaxChapterAtom *>(cb->e); atom = dynamic_cast<KaxChapterAtom *>(cb->e);
assert(atom != NULL); assert(atom != NULL);
if (FINDFIRST(atom, KaxChapterTimeStart) == NULL) if (FINDFIRST(atom, KaxChapterTimeStart) == NULL)
@ -333,9 +240,9 @@ end_write_chapter_atom(void *data) {
static void static void
end_write_chapter_display(void *data) { end_write_chapter_display(void *data) {
KaxChapterDisplay *display; KaxChapterDisplay *display;
chapter_writer_cb_t *cb; xml_writer_cb_t *cb;
cb = (chapter_writer_cb_t *)data; cb = (xml_writer_cb_t *)data;
display = dynamic_cast<KaxChapterDisplay *>(cb->e); display = dynamic_cast<KaxChapterDisplay *>(cb->e);
assert(display != NULL); assert(display != NULL);
if (FINDFIRST(display, KaxChapterString) == NULL) if (FINDFIRST(display, KaxChapterString) == NULL)
@ -359,7 +266,7 @@ write_chapters_xml(KaxChapters *chapters,
end_write_chapter_display; end_write_chapter_display;
for (i = 0; i < chapters->ListSize(); i++) for (i = 0; i < chapters->ListSize(); i++)
write_xml_element_rec(1, 0, (*chapters)[i], out); write_xml_element_rec(1, 0, (*chapters)[i], out, chapter_elements);
} }
// }}} // }}}

View File

@ -14,163 +14,13 @@
#include "os.h" #include "os.h"
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <matroska/KaxTag.h>
#include <matroska/KaxTags.h> #include <matroska/KaxTags.h>
#include <matroska/KaxTagMulti.h>
#include "xml_element_writer.h"
using namespace libmatroska; using namespace libmatroska;
using namespace std; using namespace std;
#include "base64.h"
#include "common.h"
#include "commonebml.h"
#include "matroska.h"
#include "mm_io.h"
#include "xml_element_mapping.h"
static void
print_binary(int level,
const char *name,
EbmlElement *e,
mm_io_c *out) {
EbmlBinary *b;
string s;
int i, idx, old_idx;
b = (EbmlBinary *)e;
s = base64_encode((const unsigned char *)b->GetBuffer(), b->GetSize(), true,
72 - level - 2);
if (s[s.length() - 1] == '\n')
s.erase(s.length() - 1);
if ((level * 2 + 2 * strlen(name) + 2 + 3 + s.length()) <= 78) {
out->printf("%s</%s>\n", s.c_str(), name);
return;
}
out->printf("\n");
for (i = 0; i < (level + 2); i++)
out->printf(" ");
old_idx = 0;
for (idx = 0; idx < s.length(); idx++)
if (s[idx] == '\n') {
out->printf("%s\n", s.substr(old_idx, idx - old_idx).c_str());
for (i = 0; i < (level + 2); i++)
out->printf(" ");
old_idx = idx + 1;
}
if (old_idx < s.length())
out->printf("%s", s.substr(old_idx).c_str());
out->printf("\n");
for (i = 0; i < level; i++)
out->printf(" ");
out->printf("</%s>\n", name);
}
typedef struct {
int level;
int parent_idx;
int elt_idx;
EbmlElement *e;
} tag_writer_cb_t;
static void
write_xml_element_rec(int level,
int parent_idx,
EbmlElement *e,
mm_io_c *out) {
EbmlMaster *m;
int elt_idx, i;
bool found;
string s;
elt_idx = parent_idx;
found = false;
while ((tag_elements[elt_idx].name != NULL) &&
(tag_elements[elt_idx].level >=
tag_elements[parent_idx].level)) {
if (tag_elements[elt_idx].id == e->Generic().GlobalId) {
found = true;
break;
}
elt_idx++;
}
for (i = 0; i < level; i++)
out->printf(" ");
if (!found) {
out->printf("<!-- Unknown element '%s' -->\n", e->Generic().DebugName);
return;
}
out->printf("<%s>", tag_elements[elt_idx].name);
switch (tag_elements[elt_idx].type) {
case EBMLT_MASTER:
out->printf("\n");
m = dynamic_cast<EbmlMaster *>(e);
assert(m != NULL);
for (i = 0; i < m->ListSize(); i++)
write_xml_element_rec(level + 1, elt_idx, (*m)[i], out);
if (tag_elements[elt_idx].end_hook != NULL) {
tag_writer_cb_t cb;
cb.level = level;
cb.parent_idx = parent_idx;
cb.elt_idx = elt_idx;
cb.e = e;
tag_elements[elt_idx].end_hook(&cb);
}
for (i = 0; i < level; i++)
out->printf(" ");
out->printf("</%s>\n", tag_elements[elt_idx].name);
break;
case EBMLT_UINT:
case EBMLT_BOOL:
out->printf("%llu</%s>\n", uint64(*dynamic_cast<EbmlUInteger *>(e)),
tag_elements[elt_idx].name);
break;
case EBMLT_STRING:
s = escape_xml(string(*dynamic_cast<EbmlString *>(e)));
out->printf("%s</%s>\n", s.c_str(), tag_elements[elt_idx].name);
break;
case EBMLT_USTRING:
s = UTFstring_to_cstrutf8(UTFstring(*static_cast
<EbmlUnicodeString *>(e)).c_str());
s = escape_xml(s);
out->printf("%s</%s>\n", s.c_str(), tag_elements[elt_idx].name);
break;
case EBMLT_TIME:
out->printf(FMT_TIMECODEN "</%s>\n",
ARG_TIMECODEN(uint64(*dynamic_cast<EbmlUInteger *>(e))),
tag_elements[elt_idx].name);
break;
case EBMLT_BINARY:
print_binary(level, tag_elements[elt_idx].name, e, out);
break;
default:
assert(false);
}
}
void void
write_tags_xml(KaxTags &tags, write_tags_xml(KaxTags &tags,
mm_io_c *out) { mm_io_c *out) {
@ -182,5 +32,5 @@ write_tags_xml(KaxTags &tags,
} }
for (i = 0; i < tags.ListSize(); i++) for (i = 0; i < tags.ListSize(); i++)
write_xml_element_rec(1, 0, tags[i], out); write_xml_element_rec(1, 0, tags[i], out, tag_elements);
} }

View File

@ -15,8 +15,6 @@
#ifndef __TAGWRITER_H #ifndef __TAGWRITER_H
#define __TAGWRITER_H #define __TAGWRITER_H
#include <stdio.h>
#include <matroska/KaxTags.h> #include <matroska/KaxTags.h>
#include <matroska/KaxTag.h> #include <matroska/KaxTag.h>

View File

@ -0,0 +1,153 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
Distributed under the GPL
see the file COPYING for details
or visit http://www.gnu.org/copyleft/gpl.html
$Id$
XML chapter writer functions
Written by Moritz Bunkus <moritz@bunkus.org>.
*/
#include <ebml/EbmlBinary.h>
#include <ebml/EbmlMaster.h>
#include <ebml/EbmlSInteger.h>
#include <ebml/EbmlString.h>
#include <ebml/EbmlUInteger.h>
#include <ebml/EbmlUnicodeString.h>
#include <ebml/EbmlDate.h>
#include "base64.h"
#include "common.h"
#include "commonebml.h"
#include "mm_io.h"
#include "xml_element_writer.h"
using namespace libebml;
static void
print_binary(int level,
const char *name,
EbmlElement *e,
mm_io_c *out) {
EbmlBinary *b;
const unsigned char *p;
string s;
int i, size;
b = (EbmlBinary *)e;
p = (const unsigned char *)b->GetBuffer();
size = b->GetSize();
for (i = 0; i < size; i++) {
if ((i % 16) != 0)
s += " ";
s += mxsprintf("%02x", *p);
++p;
if ((((i + 1) % 16) == 0) && ((i + 1) < size))
s += mxsprintf("\n%*s", (level + 1) * 2, "");
}
if ((level * 2 + 2 * strlen(name) + 2 + 3 + s.length()) <= 78)
out->printf("%s</%s>\n", s.c_str(), name);
else
out->printf("\n%*s%s\n%*s</%s>\n", (level + 1) * 2, "", s.c_str(),
level * 2, "", name);
}
void
write_xml_element_rec(int level,
int parent_idx,
EbmlElement *e,
mm_io_c *out,
const parser_element_t *element_map) {
EbmlMaster *m;
int elt_idx, i;
bool found;
string s;
elt_idx = parent_idx;
found = false;
while ((element_map[elt_idx].name != NULL) &&
(element_map[elt_idx].level >=
element_map[parent_idx].level)) {
if (element_map[elt_idx].id == e->Generic().GlobalId) {
found = true;
break;
}
elt_idx++;
}
for (i = 0; i < level; i++)
out->printf(" ");
if (!found) {
out->printf("<!-- Unknown element '%s' -->\n", e->Generic().DebugName);
return;
}
out->printf("<%s%s>", element_map[elt_idx].name,
element_map[elt_idx].type == EBMLT_BINARY ?
" format=\"hex\"" : "");
switch (element_map[elt_idx].type) {
case EBMLT_MASTER:
out->printf("\n");
m = dynamic_cast<EbmlMaster *>(e);
assert(m != NULL);
for (i = 0; i < m->ListSize(); i++)
write_xml_element_rec(level + 1, elt_idx, (*m)[i], out, element_map);
if (element_map[elt_idx].end_hook != NULL) {
xml_writer_cb_t cb;
cb.level = level;
cb.parent_idx = parent_idx;
cb.elt_idx = elt_idx;
cb.e = e;
cb.out = out;
element_map[elt_idx].end_hook(&cb);
}
for (i = 0; i < level; i++)
out->printf(" ");
out->printf("</%s>\n", element_map[elt_idx].name);
break;
case EBMLT_UINT:
case EBMLT_BOOL:
out->printf("%llu</%s>\n", uint64(*dynamic_cast<EbmlUInteger *>(e)),
element_map[elt_idx].name);
break;
case EBMLT_STRING:
s = escape_xml(string(*dynamic_cast<EbmlString *>(e)));
out->printf("%s</%s>\n", s.c_str(), element_map[elt_idx].name);
break;
case EBMLT_USTRING:
s = UTFstring_to_cstrutf8(UTFstring(*static_cast
<EbmlUnicodeString *>(e)).c_str());
s = escape_xml(s);
out->printf("%s</%s>\n", s.c_str(), element_map[elt_idx].name);
break;
case EBMLT_TIME:
out->printf(FMT_TIMECODEN "</%s>\n",
ARG_TIMECODEN(uint64(*dynamic_cast<EbmlUInteger *>(e))),
element_map[elt_idx].name);
break;
case EBMLT_BINARY:
print_binary(level, element_map[elt_idx].name, e, out);
break;
default:
assert(false);
}
}

View File

@ -0,0 +1,42 @@
/*
mkvmerge -- utility for splicing together matroska files
from component media subtypes
Distributed under the GPL
see the file COPYING for details
or visit http://www.gnu.org/copyleft/gpl.html
$Id$
XML chapter writer functions
Written by Moritz Bunkus <moritz@bunkus.org>.
*/
#ifndef __XML_ELEMENT_WRITER_H
#define __XML_ELEMENT_WRITER_H
#include "xml_element_parser.h"
namespace libebml {
class EbmlElement;
};
using namespace libebml;
class mm_io_c;
struct xml_writer_cb_t {
int level;
int parent_idx;
int elt_idx;
EbmlElement *e;
mm_io_c *out;
};
void MTX_DLL_API
write_xml_element_rec(int level, int parent_idx,
EbmlElement *e, mm_io_c *out,
const parser_element_t *element_map);
#endif // __XML_ELEMENT_WRITER_H