Initial community commit
This commit is contained in:
parent
537bcbc862
commit
fc06254474
16440 changed files with 4239995 additions and 2 deletions
262
Src/Wasabi/api/xml/xmlwrite.cpp
Normal file
262
Src/Wasabi/api/xml/xmlwrite.cpp
Normal file
|
@ -0,0 +1,262 @@
|
|||
#include <precomp.h>
|
||||
|
||||
#include "xmlwrite.h"
|
||||
|
||||
#include <bfc/wasabi_std.h>
|
||||
#include <bfc/string/bfcstring.h>
|
||||
#include <bfc/parse/paramparser.h>
|
||||
|
||||
#if 0
|
||||
static unsigned char xmltypecheck[256] =
|
||||
{
|
||||
#define BT_COLON BT_NMSTRT
|
||||
#include "latin1tab.h"
|
||||
#undef BT_COLON
|
||||
#include "asciitab.h"
|
||||
};
|
||||
#endif
|
||||
|
||||
#define EFPRINTF (nohicharconversion ? eutf8fprintf : efprintf)
|
||||
|
||||
#include "../nu/AutoChar.h"
|
||||
XMLWrite::XMLWrite(const wchar_t *filename, const wchar_t *doctype, const wchar_t *dtddoctype, int no_hi_chars_conversion)
|
||||
{
|
||||
nohicharconversion = no_hi_chars_conversion;
|
||||
FILE *f = _wfopen(filename, WF_WRITE_BINARY);
|
||||
Init(f, doctype, dtddoctype);
|
||||
}
|
||||
|
||||
XMLWrite::XMLWrite(FILE *file, const wchar_t *doctype, const wchar_t *dtddoctype, int no_hi_chars_conversion)
|
||||
{
|
||||
nohicharconversion = no_hi_chars_conversion;
|
||||
Init(file, doctype, dtddoctype);
|
||||
}
|
||||
|
||||
void XMLWrite::Init(FILE *file, const wchar_t *doctype, const wchar_t *dtddoctype)
|
||||
{
|
||||
fp = file;
|
||||
ASSERT(fp != NULL); // sheet, need exceptions here
|
||||
indenter.setValue(L"");
|
||||
utf8fprintf(fp, L"<?xml version=\"1.0\" encoding='UTF-8' standalone=\"yes\"?>\n");
|
||||
if (dtddoctype != NULL)
|
||||
utf8fprintf(fp, L"<!DOCTYPE %s>\n", dtddoctype);
|
||||
pushCategory(doctype, 1, 0);
|
||||
}
|
||||
|
||||
XMLWrite::~XMLWrite()
|
||||
{
|
||||
popCategory(1, 0);
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
ASSERT(titles.peek() == 0);
|
||||
}
|
||||
|
||||
void XMLWrite::comment(const wchar_t *comment)
|
||||
{
|
||||
utf8fprintf(fp, L"<!-- %s -->\n", comment);
|
||||
}
|
||||
|
||||
void XMLWrite::pushCategory(const wchar_t *title, int wantcr, int wantindent)
|
||||
{
|
||||
if (wantindent)
|
||||
{
|
||||
utf8fprintf(fp, L"%s<%s>%s", indenter.getValue(), title, wantcr ? L"\n" : L"");
|
||||
}
|
||||
else
|
||||
utf8fprintf(fp, L"<%s>%s", title, wantcr ? L"\n" : L"");
|
||||
indenter+=L" ";
|
||||
ParamParser pp(title, L" ");
|
||||
titles.push(WCSDUP(pp.enumItem(0)));
|
||||
}
|
||||
|
||||
void XMLWrite::pushCategoryAttrib(const wchar_t *title, int nodata)
|
||||
{
|
||||
utf8fprintf(fp, L"%s<%s", indenter.getValue(), title);
|
||||
indenter+=L" ";
|
||||
titles.push(nodata ? NULL : WCSDUP(title));
|
||||
}
|
||||
|
||||
void XMLWrite::writeCategoryAttrib(const wchar_t *title, const int val)
|
||||
{
|
||||
utf8fprintf(fp, L" %s=\"%d\"", title, val);
|
||||
}
|
||||
|
||||
void XMLWrite::writeCategoryAttrib(const wchar_t *title, const wchar_t *str)
|
||||
{
|
||||
if (!str)
|
||||
str = L"";
|
||||
utf8fprintf(fp, L" %s=\"", title);
|
||||
EFPRINTF(fp, L"%s", str);
|
||||
utf8fprintf(fp, L"\"");
|
||||
}
|
||||
|
||||
void XMLWrite::closeCategoryAttrib(int wantcr)
|
||||
{
|
||||
if (titles.top() == NULL)
|
||||
utf8fprintf(fp, L" /");
|
||||
utf8fprintf(fp, L">%s", wantcr ? L"\n" : L"");
|
||||
}
|
||||
|
||||
void XMLWrite::writeAttribEmpty(const wchar_t *title, int wantcr, int wantindent)
|
||||
{
|
||||
if (wantindent)
|
||||
utf8fprintf(fp, L"%s<%s/>%s", indenter.getValue(), title, wantcr ? L"\n" : L"");
|
||||
else
|
||||
utf8fprintf(fp, L"<%s/>%s", title, wantcr ? L"\n" : L"");
|
||||
}
|
||||
|
||||
void XMLWrite::writeAttrib(const wchar_t *title, const wchar_t *text, int wantcr, int wantindent)
|
||||
{
|
||||
if (text && *text)
|
||||
{
|
||||
if (wantindent)
|
||||
utf8fprintf(fp, L"%s<%s>", indenter.getValue(), title);
|
||||
else
|
||||
utf8fprintf(fp, L"<%s>", title);
|
||||
EFPRINTF(fp, L"%s", text);
|
||||
utf8fprintf(fp, L"</%s>%s", title, wantcr ? L"\n" : L"");
|
||||
}
|
||||
else
|
||||
{
|
||||
writeAttribEmpty(title, wantcr, wantindent);
|
||||
}
|
||||
}
|
||||
|
||||
void XMLWrite::writeAttrib(const wchar_t *title, int val, int wantcr, int wantindent)
|
||||
{
|
||||
if (wantindent)
|
||||
utf8fprintf(fp, L"%s<%s>%d</%s>%s", indenter.getValue(), title, val, title, wantcr ? L"\n" : L"");
|
||||
else
|
||||
utf8fprintf(fp, L"<%s>%d</%s>%s", title, val, title, wantcr ? L"\n" : L"");
|
||||
}
|
||||
|
||||
int XMLWrite::popCategory(int wantcr, int wantindent)
|
||||
{
|
||||
indenter.trunc(-2);
|
||||
wchar_t *title;
|
||||
int r = titles.pop(&title);
|
||||
if (!r) return 0;
|
||||
if (title != NULL)
|
||||
{
|
||||
if (wantindent)
|
||||
utf8fprintf(fp, L"%s</%s>%s", indenter.getValue(), title, wantcr ? L"\n" : L"");
|
||||
else
|
||||
utf8fprintf(fp, L"</%s>%s", title, wantcr ? L"\n" : L"");
|
||||
FREE(title);
|
||||
}
|
||||
return titles.peek();
|
||||
}
|
||||
|
||||
int XMLWrite::utf8fprintf(FILE *fp, const wchar_t *format, ...)
|
||||
{
|
||||
va_list v;
|
||||
StringW outstr;
|
||||
va_start(v, format);
|
||||
outstr.va_sprintf(format, v);
|
||||
va_end(v);
|
||||
|
||||
#ifdef _WIN32
|
||||
AutoChar utf8(outstr, CP_UTF8);
|
||||
#else
|
||||
#warning port me
|
||||
AutoChar utf8(outstr);
|
||||
#endif
|
||||
const char *data = (const char *)utf8; // to make the next line less messay
|
||||
fwrite(data, STRLEN(data), 1, fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XMLWrite::eutf8fprintf(FILE *fp, const wchar_t *format, ...)
|
||||
{
|
||||
va_list v;
|
||||
StringW outstr;
|
||||
va_start(v, format);
|
||||
outstr.va_sprintf(format, v);
|
||||
va_end(v);
|
||||
|
||||
#ifdef _WIN32
|
||||
AutoChar utf8(outstr, CP_UTF8);
|
||||
#else
|
||||
#warning port me
|
||||
AutoChar utf8(outstr);
|
||||
#endif
|
||||
|
||||
const char *data = (const char *)utf8; // to make the next line less messay
|
||||
while (data && *data)
|
||||
{
|
||||
size_t cur_length=0;
|
||||
while (data[cur_length] && data[cur_length] != '<' && data[cur_length] != '>' && data[cur_length] != '&' && data[cur_length] != '\"' && data[cur_length] != '\'')
|
||||
{
|
||||
cur_length++;
|
||||
}
|
||||
fwrite(data, cur_length, 1, fp);
|
||||
data += cur_length;
|
||||
if (*data)
|
||||
{
|
||||
// if we get here, it was a special character
|
||||
switch(*data)
|
||||
{
|
||||
case '<': fwrite("<", 4, 1, fp); break;
|
||||
case '>': fwrite(">", 4, 1, fp); break;
|
||||
case '&': fwrite("&", 5, 1, fp); break;
|
||||
case '\"': fwrite(""", 6, 1, fp); break;
|
||||
case '\'': fwrite("'", 6, 1, fp); break;
|
||||
}
|
||||
data++;
|
||||
}
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int XMLWrite::efprintf(FILE *fp, const wchar_t *format, ...)
|
||||
{
|
||||
va_list v;
|
||||
// http://www.w3.org/TR/REC-xml#syntax
|
||||
int bcount = 0;
|
||||
StringW outstr;
|
||||
va_start(v, format);
|
||||
outstr.va_sprintf(format, v);
|
||||
va_end(v);
|
||||
size_t n = outstr.len();
|
||||
for (size_t i = 0; i != n; i++)
|
||||
{
|
||||
wchar_t c = outstr.getValue()[i];
|
||||
switch (c)
|
||||
{
|
||||
case '<': fwrite("<", 4, 1, fp); bcount += 4; break;
|
||||
case '>': fwrite(">", 4, 1, fp); bcount += 4; break;
|
||||
case '&': fwrite("&", 5, 1, fp); bcount += 5; break;
|
||||
case '\"': fwrite(""", 6, 1, fp); bcount += 6; break;
|
||||
case '\'': fwrite("'", 6, 1, fp); bcount += 6; break;
|
||||
default:
|
||||
// if (xmltypecheck[c] != 0)
|
||||
{
|
||||
// TODO: benski> optimize by scanning for the next character to be escaped (or NULL)
|
||||
size_t numChars=1;
|
||||
while (1)
|
||||
{
|
||||
wchar_t check = outstr.getValue()[i+numChars];
|
||||
if (check == 0
|
||||
|| check == '<'
|
||||
|| check == '>'
|
||||
|| check == '&'
|
||||
|| check == '\''
|
||||
|| check == '\"')
|
||||
break;
|
||||
numChars++;
|
||||
}
|
||||
const wchar_t *str = outstr.getValue() + i;
|
||||
int len = WideCharToMultiByte(CP_UTF8, 0, str, (int)numChars, 0, 0, 0, 0);
|
||||
char *utf8 = (char *)malloc(len);
|
||||
WideCharToMultiByte(CP_UTF8, 0, str, (int)numChars, utf8, len, 0, 0);
|
||||
fwrite(utf8, len, 1, fp);
|
||||
free(utf8);
|
||||
bcount+=(int)numChars;
|
||||
i+=(numChars-1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return bcount;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue