summaryrefslogtreecommitdiff
path: root/glcdskin/xml.c
diff options
context:
space:
mode:
Diffstat (limited to 'glcdskin/xml.c')
-rw-r--r--glcdskin/xml.c161
1 files changed, 126 insertions, 35 deletions
diff --git a/glcdskin/xml.c b/glcdskin/xml.c
index ed29d11..a3ad976 100644
--- a/glcdskin/xml.c
+++ b/glcdskin/xml.c
@@ -15,32 +15,15 @@
#include <iostream>
#include <fstream>
+#include <string.h>
+#include <stdlib.h>
+
#include "xml.h"
+#include "../glcdgraphics/common.h"
namespace GLCD
{
-std::string trim(const std::string & s)
-{
- std::string::size_type start, end;
-
- start = 0;
- while (start < s.length())
- {
- if (!isspace(s[start]))
- break;
- start++;
- }
- end = s.length() - 1;
- while (end >= 0)
- {
- if (!isspace(s[end]))
- break;
- end--;
- }
- return s.substr(start, end - start + 1);
-}
-
enum {
LOOK4START, // looking for first element start
LOOK4TAG, // looking for element tag
@@ -57,7 +40,7 @@ enum {
INCLOSETAG, // reading closing tag
};
-cXML::cXML(const std::string & file)
+cXML::cXML(const std::string & file, const std::string sysCharset)
: nodestartcb(NULL),
nodeendcb(NULL),
cdatacb(NULL),
@@ -66,6 +49,18 @@ cXML::cXML(const std::string & file)
{
char * buffer;
long size;
+ sysEncoding = sysCharset;
+ sysIsUTF8 = (sysEncoding == "UTF-8");
+ if (!sysIsUTF8) {
+ // convert from utf-8 to system encoding
+ iconv_cd = iconv_open(sysEncoding.c_str(), "UTF-8");
+ if (iconv_cd == (iconv_t) -1) {
+ syslog(LOG_ERR, "ERROR: system encoding %s is not supported\n", sysEncoding.c_str());
+ iconv_cd = NULL;
+ }
+ } else {
+ iconv_cd = NULL;
+ }
#if (__GNUC__ < 3)
std::ifstream f(file.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
@@ -75,20 +70,24 @@ cXML::cXML(const std::string & file)
if (!f.is_open())
{
syslog(LOG_ERR, "ERROR: skin file %s not found\n", file.c_str());
- }
- size = f.tellg();
+ validFile = false;
+ } else {
+ validFile = true;
+ size = f.tellg();
#if (__GNUC__ < 3)
- f.seekg(0, std::ios::beg);
+ f.seekg(0, std::ios::beg);
#else
- f.seekg(0, std::ios_base::beg);
+ f.seekg(0, std::ios_base::beg);
#endif
- buffer = new char[size];
- f.read(buffer, size);
- f.close();
- data.assign(buffer, size);
- delete[] buffer;
+ buffer = new char[size];
+ f.read(buffer, size);
+ f.close();
+ data.assign(buffer, size);
+ delete[] buffer;
+ }
}
+#if 0
cXML::cXML(const char * mem, unsigned int len)
: nodestartcb(NULL),
nodeendcb(NULL),
@@ -98,6 +97,13 @@ cXML::cXML(const char * mem, unsigned int len)
{
data.assign(mem, len);
}
+#endif
+
+cXML::~cXML()
+{
+ if (iconv_cd != NULL)
+ iconv_close(iconv_cd);
+}
void cXML::SetNodeStartCB(XML_NODE_START_CB(cb))
{
@@ -129,14 +135,29 @@ int cXML::Parse(void)
int percent = 0;
int last = 0;
std::string::size_type len;
+ uint32_t c, c_tmp;
+ unsigned int i_old;
+ int l, char_size;
+
+ if (!validFile)
+ return -1;
state = LOOK4START;
linenr = 1;
skipping = false;
len = data.length();
- for (std::string::size_type i = 0; i < len; i++)
+
+ unsigned int i = 0;
+ while (i < (unsigned int)len)
{
- if (ReadChar(data[i]) != 0)
+ i_old = i;
+ encodedCharAdjustCounter(true, data, c_tmp, i);
+ char_size = (i - i_old) + 1;
+ c = 0;
+ for (l = 0 ; l < char_size; l++)
+ c += ( (0xFF & data[i_old + l]) << ( l << 3) );
+
+ if (ReadChar(c /*data[i]*/, char_size) != 0)
return -1;
if (progresscb)
{
@@ -147,6 +168,7 @@ int cXML::Parse(void)
last = percent;
}
}
+ i++;
}
return 0;
}
@@ -156,8 +178,15 @@ bool cXML::IsTokenChar(bool start, int c)
return isalpha(c) || c == '_' || (!start && isdigit(c));
}
-int cXML::ReadChar(int c)
+int cXML::ReadChar(unsigned int c, int char_size)
{
+ // buffer for conversions (when conversion from utf8 to system encoding is required)
+ char convbufin[5];
+ char convbufout[5];
+ char* convbufinp = convbufin;
+ char* convbufoutp = convbufout;
+ size_t bufin_size, bufout_size, bufconverted;
+
// new line?
if (c == '\n')
linenr++;
@@ -179,6 +208,46 @@ int cXML::ReadChar(int c)
cdata.replace(pos, 4, ">");
else if (cdata.substr(pos, 5) == "&amp;")
cdata.replace(pos, 5, "&");
+ else if (cdata.substr(pos, 2) == "&#") {
+ bool ishex = ((cdata.substr(pos+2, 1) == "x") || (cdata.substr(pos+2, 1) == "X") );
+ size_t startpos = pos+2+((ishex)?1:0);
+ size_t endpos = cdata.find(';', startpos );
+ if (endpos != std::string::npos) {
+ char* tempptr;
+ std::string charid = cdata.substr(startpos, endpos-startpos);
+ long val = strtol(charid.c_str(), &tempptr, (ishex) ? 16 : 10);
+
+ if (tempptr != charid.c_str() && *tempptr == '\0') {
+ char encbuf[5]; size_t enclen = 0;
+
+ if ( val <= 0x1F ) {
+ enclen = 0; // ignore control chars
+ } else if ( val <= 0x007F ) {
+ enclen = 1;
+ encbuf[0] = (char)(val & 0x7F);
+ } else if ( val <= 0x07FF ) {
+ enclen = 2;
+ encbuf[1] = (char)(( val & 0x003F) | 0x80);
+ encbuf[0] = (char)(( (val & 0x07C0) >> 6) | 0xC0);
+ } else if ( val <= 0xFFFF ) {
+ enclen = 3;
+ encbuf[2] = (char)(( val & 0x003F) | 0x80);
+ encbuf[1] = (char)(( (val & 0x0FC0) >> 6) | 0x80);
+ encbuf[0] = (char)(( (val & 0xF000) >> 12) | 0xE0);
+ } else if ( val <= 0x10FFFF ) {
+ enclen = 4;
+ encbuf[3] = (char)(( val & 0x003F) | 0x80);
+ encbuf[2] = (char)(( (val & 0x0FC0) >> 6) | 0x80);
+ encbuf[1] = (char)(( (val & 0x03F000 ) >> 12) | 0x80);
+ encbuf[0] = (char)(( (val & 0x1C0000 ) >> 18) | 0xF0);
+ }
+ encbuf[enclen] = '\0';
+ if (enclen > 0) {
+ cdata.replace(pos, endpos-pos+1, encbuf);
+ }
+ }
+ }
+ }
pos++;
}
if (!cdatacb(trim(cdata)))
@@ -190,7 +259,29 @@ int cXML::ReadChar(int c)
state = LOOK4TAG;
}
else
- cdata += c;
+ {
+ int i;
+ //cdata += c;
+ // convert text-data on the fly if system encoding != UTF-8
+ if (iconv_cd != NULL && char_size > 1 /* ((c & 0x80) == 0x80)*/) {
+ for (i = 0; i < char_size; i++)
+ convbufin[i] = ( (char)((c >> ( i << 3) ) & 0xFF) );
+ convbufin[char_size] = '\0';
+ bufin_size = strlen(convbufin);
+ bufout_size = bufin_size;
+ bufconverted = iconv(iconv_cd, &convbufinp, &bufin_size, &convbufoutp, &bufout_size);
+
+ if (bufconverted != (size_t)-1 && strlen(convbufout) != 0) {
+ for (i = 0; i < (int)strlen(convbufout); i++)
+ cdata += convbufout[i];
+ } else {
+ cdata += "?";
+ }
+ } else {
+ for (i = 0; i < char_size; i++)
+ cdata += ( (unsigned char)((c >> ( i << 3) ) & 0xFF) );
+ }
+ }
// silently ignore until resync
break;