#define UNICODE
#define _UNICODE
#include <windows.h>
#include <windowsx.h> // Edit_SetModify
#include <malloc.h> // _alloca
#include <stdio.h> // _snprintf
#ifndef _DEBUG
# define NDEBUG
#endif
#include <assert.h>
struct Xml {
struct Node{
Xml*xml; // Zeiger hoch zum äDokumentô
enum type_t{ //scope sub name value
root, //0..len PI,Element,Comment 0 0
Element, //<tag..> Attr;Element,Text,Comm. tag 0
Attr, //tag="value" 0 tag value
Text, //text Entity 0 text
CDATASection, //<![CDATA[var]]> 0 0 var
EntityReference, //?
Entity, //&tag; 0 tag 0
ProcessingInstruction,//<?tag ?> Attr tag between tag and ?>
Comment, //<!-- --> 0 0 between <!-- and -->
Document, //HTML only
DocumentType, //<!DOCTYPE >
DocumentFragment, //HTML only
Notation //?
}type;
const char*name; // im Heap
const char*value; // im Heap
/* Knotenverkettung am Beispiel: 3 Knoten, der mittlere hat kein Kindelement
WΣhrend änextô am Ende 0 ist, zeigt äprevô auf das letzte Element.
Von einem beliebigen Knoten (au▀er root) ist äparent->sub->prevô das letzte Element.
^
+---<-------+---<-------+
+--------- | -->------ | -->------ | -+
| | | | |
| +------+ | +------+ | +------+ | |
| | Node | | | Node | | | Node | | |
| |parent|-+ |parent|-+ |parent|-+ |
| | next |--->| next |--->| next |>0 |
+-| prev |<---| prev |<---| prev |<---+
| sub |-+ | sub |>0 | sub |-+
+------+ | +------+ +------+ |
v v
*/
Node*next,*prev,*parent,*sub;
static void*operator new(size_t sz) {assert(false); return 0;}
static void operator delete(void*) {} // simply don't delete
Node(Xml*ml,type_t t=root):xml(ml),type(t) {prev=this;}
void add_child_back(Node*n) {
if (sub) sub->add_sibling_back(n);
else{sub=n;n->parent=this;}}
void add_sibling_back(Node*n) {
assert(isFirstChild());
n->parent=parent; prev->next=n; n->prev=prev; prev=n;}
void add_sibling_front(Node*n) {
assert(isFirstChild());
n->parent=parent; parent->sub=n; n->next=this; n->prev=prev; prev=n;}
bool isChild(Node*n) const {return n->parent==this;}
bool isLastChild() const {return !next;}
bool isFirstChild() const {return this==parent->sub;}
const Node*findElement(const char*tag=0) const {return findNode(Node::Element,tag);}
const Node*findNode(Node::type_t t,const char*tag=0) const;
bool enumNodes(Node::type_t t,const char*tag,bool(*)(const Node*,void*),void*) const;
const Node*findChildNode(Node::type_t t,const char*tag) const;
const Node*findChildNode(Node::type_t t,bool(*)(const Node*,void*),void*) const;
~Node(); // aushΣngen
// Node*addAttr(const char*tag,const char*val,Node*before=0);
// Node*addElement(const char*tag,Node*before=0);
// Node*setElement(Node*p,const char*tag,bool* =0); // Kind von p finden oder anhΣngen
// Node*addPI(const char*tag,Node*before=0); // always to root node
// Node*addText(const char*txt,Node*before=0);
};
Node*root;
unsigned ec,line,pos; // Stelle des Fehlers bei parse(), 0-basiert
HANDLE hStream;
bool parse(); // linearisierte Version
bool serialize() {return serialize(root);}
Xml(HANDLE h=0);
~Xml();
enum{BUFSIZE=1024*1024};
private:
HANDLE hHeap;
char*buf;
unsigned idx,len;
template<int MAX=256> struct Stringbuf{
unsigned slen;
char s[MAX];
Stringbuf():slen(0) {}
void clear() {slen=0;}
bool push(char c) {if (slen>=sizeof s) return false; s[slen++]=c; return true;}
bool operator==(const char*v) const {size_t lv=strlen(v); return slen==lv && !memcmp(s,v,lv);}
bool operator!=(const char*v) const {return !operator==(v);}
bool endsWith(const char*v) const {size_t lv=strlen(v); return slen>=lv && !memcmp(s+slen-lv,v,lv);}
};
int get() {
if (idx==len) readNext(); // Puffer ausgelesen? NΣchsten Block lesen!
if (idx==len) return -1; // Puffer immer noch ausgelesen? EOF liefern
int ret=(unsigned char)buf[idx++]; // Zeichen liefern
if (ret=='\n') {++line; pos=0;} else ++pos; // Zeilen und Spalten mitzΣhlen
return ret;
}
bool readNext();
int innerParse();
int parseAttr(Node*el,int c);
bool serialize(const Node*);
char*newString(); // Auf dem Heap
bool _cdecl out(const char*t,...);
Node*newNode(Node::type_t t=Node::root); // Auf dem Heap + Placement new
Stringbuf<4096>sb; // Nur fⁿr den Parser
};
Vorgefundene Kodierung: OEM (CP437) | 1
|
|