Quelltext /~heha/hs/cdcat1plugin.zip/src/xml.h

#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: UTF-80