Files correlati : lurch.exe Ricompilazione Demo : [ ] Commento : Questo maggiordomo non solo e' in grado di ammazzare la servitu' oziosa... ma anche di risuscitarla quanto questa si suicida! git-svn-id: svn://10.65.10.50/trunk@19979 c028cbd2-c16b-5b4b-a496-9718f37d4682
		
			
				
	
	
		
			555 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			555 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| #include <wx/wx.h>
 | |
| 
 | |
| #include "wx/mstream.h"
 | |
| #include <wx/wfstream.h>
 | |
| 
 | |
| #include "xml.h"
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // Utilities
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| wxOutputStream& operator<<(wxOutputStream& outf, const wxChar* str)
 | |
| {
 | |
| 	if (str && *str)
 | |
|     outf.Write(str, wxStrlen(str));
 | |
| 	return outf;
 | |
| }
 | |
| 
 | |
| wxOutputStream& operator<<(wxOutputStream& outf, wxString str)
 | |
| {
 | |
| 	if (!str.IsEmpty())
 | |
|     outf.Write(str, str.Length());
 | |
| 	return outf;
 | |
| }
 | |
| 
 | |
| wxInputStream& operator>>(wxInputStream& inf, wxString& str)
 | |
| {
 | |
| 	const off_t nStart = inf.TellI();
 | |
| 	wxChar* buf = str.GetWriteBuf(1024); *buf = '\0';
 | |
| 	inf.Read(buf, 1024);
 | |
| 	str.UngetWriteBuf();
 | |
| 	const int nEol = str.Find('\n');
 | |
| 	if (nEol >= 0)
 | |
| 	{
 | |
|     if (str[(size_t)(nEol+1)] > '\0')
 | |
|       inf.SeekI(nStart+nEol+1, (wxSeekMode) 0);
 | |
| 		str.Truncate(nEol);
 | |
| 		str.Trim();
 | |
| 	}
 | |
| 	else
 | |
|   {
 | |
|     if (!str.IsEmpty())
 | |
| 		  inf.SeekI(nStart+str.Length(), (wxSeekMode) 0);
 | |
|   }
 | |
| 
 | |
| 	return inf;
 | |
| }
 | |
| 
 | |
| void Spaces(wxOutputStream& outf, int nSpaces)
 | |
| {
 | |
| 	outf << "\n";
 | |
| 	if (nSpaces > 0)
 | |
| 	{
 | |
| 		wxString str; 
 | |
| 		str.Append(' ', nSpaces);
 | |
| 		outf << str;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| int hex2int(const wxChar* str)
 | |
| {
 | |
| 	int n = 0;
 | |
| 	for (int i = 0; str[i]; i++)
 | |
| 	{
 | |
| 		if (str[i] >= '0' && str[i] <= '9')
 | |
| 		{
 | |
|   		n *= 16;
 | |
|       n += str[i]-'0';
 | |
| 		} else
 | |
| 		if (str[i] >= 'A' && str[i] <= 'F')
 | |
| 		{
 | |
|   		n *= 16;
 | |
| 		  n += str[i]-'A'+10;
 | |
| 		}
 | |
| 		else
 | |
| 			break;
 | |
| 	}
 | |
| 	return n;
 | |
| }
 | |
| 
 | |
| wxString EscapeSequence(char cStart, wxInputStream& inf)
 | |
| {
 | |
| 	wxString str;
 | |
| 
 | |
| 	if (cStart == '&')
 | |
| 	{
 | |
| 		for (wxChar c = inf.GetC(); c != ';'; c = inf.GetC())
 | |
| 			str += c;
 | |
|     unsigned n = 0;
 | |
|     sscanf(str, "#%X", &n);
 | |
|     str = char(n);
 | |
| 	}
 | |
|   else
 | |
|     str = cStart;
 | |
| 	
 | |
| 	return str;
 | |
| }
 | |
| 
 | |
| void WriteXmlString(wxOutputStream& outf, const wxChar* str)
 | |
| {
 | |
| 	for (int i = 0; str[i]; i++)
 | |
| 	{
 | |
| 		wxChar c = str[i];
 | |
| 		if (c < 0 || c > 'z' || strchr("<>/&", c) != NULL)
 | |
| 		{
 | |
| 			unsigned int n = (unsigned char)c;
 | |
| 			char str[8]; sprintf(str, "&#%02X;", n);
 | |
| 			outf << str;
 | |
| 		}
 | |
| 		else
 | |
| 			outf << c;
 | |
| 	}
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TXmlAttr
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| class TXmlAttr : public wxObject
 | |
| {
 | |
| public:
 | |
|   wxString m_str;
 | |
| 
 | |
| 	void Write(wxOutputStream& outf) const;
 | |
| 	
 | |
| 	TXmlAttr(const wxChar* str) : m_str(str) { }
 | |
| };
 | |
| 
 | |
| void TXmlAttr::Write(wxOutputStream& outf) const
 | |
| {
 | |
| 	if (m_str.IsEmpty())
 | |
| 	{
 | |
| 		outf << "\"\"";
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 		if (m_str.IsNumber())
 | |
| 			outf << m_str;
 | |
| 		else
 | |
| 			outf << "\"" << m_str << "\"";
 | |
| 	}
 | |
| }
 | |
| 
 | |
| ///////////////////////////////////////////////////////////
 | |
| // TXmlItem
 | |
| ///////////////////////////////////////////////////////////
 | |
| 
 | |
| IMPLEMENT_DYNAMIC_CLASS(TXmlItem, wxObject)
 | |
| 
 | |
| TXmlItem& TXmlItem::SetAttr(const wxChar* strAttr, const wxChar* strVal)
 | |
| {
 | |
| 	if (m_Attributes == NULL)
 | |
| 	{
 | |
| 		m_Attributes = new wxHashTable(wxKEY_STRING, 17);
 | |
|     m_Attributes->DeleteContents(true);
 | |
| 	}
 | |
|   else
 | |
|     m_Attributes->Delete(strAttr);
 | |
|   m_Attributes->Put(strAttr, new TXmlAttr(strVal));
 | |
| 	return *this;
 | |
| }
 | |
| 
 | |
| wxString TXmlItem::GetAttr(const wxChar* strAttr) const
 | |
| {
 | |
| 	wxString strResult;
 | |
| 	if (m_Attributes != NULL)
 | |
| 	{
 | |
| 	  const TXmlAttr* str = (const TXmlAttr*)m_Attributes->Get(strAttr);
 | |
| 		if (str != NULL)
 | |
| 			strResult = str->m_str;
 | |
| 	}
 | |
| 	return strResult;
 | |
| }
 | |
| 
 | |
| TXmlItem& TXmlItem::SetAttr(const wxChar* strAttr, long nVal)
 | |
| {
 | |
|   return SetAttr(strAttr, wxString::Format("%ld", nVal));
 | |
| }
 | |
| 
 | |
| int TXmlItem::GetChildren() const
 | |
| {
 | |
| 	int n = 0;
 | |
| 	if (m_Children != NULL)
 | |
| 		n = (int)m_Children->GetCount();
 | |
| 	return n;
 | |
| }
 | |
| 
 | |
| TXmlItem* TXmlItem::GetChild(size_t n) const
 | |
| {
 | |
| 	TXmlItem* i = NULL;
 | |
| 	if (m_Children != NULL && n < m_Children->GetCount())
 | |
| 	{
 | |
| 		wxNode* pNode = m_Children->Item(n);
 | |
| 		if (pNode != NULL)
 | |
| 		  i = (TXmlItem*)pNode->GetData();
 | |
| 	}
 | |
| 	return i;
 | |
| }
 | |
| 
 | |
| 
 | |
| wxString TXmlItem::GetWord(wxInputStream& inf) const
 | |
| {
 | |
| 	wxString str;
 | |
| 
 | |
| 	int cFirstChar = EOF;
 | |
| 	while (!inf.Eof())
 | |
| 	{
 | |
| 	  cFirstChar = inf.GetC();
 | |
| 	  if (cFirstChar <= 0 || cFirstChar > ' ')
 | |
| 			break;
 | |
| 	}
 | |
| 	if (cFirstChar == EOF)
 | |
| 		return str;
 | |
| 
 | |
| 	const bool bIsString = cFirstChar == '"' || cFirstChar == '\'';
 | |
| 	if (bIsString)
 | |
| 		str = "";
 | |
| 	else
 | |
| 	{
 | |
| 		str = char(cFirstChar);
 | |
| 		if (strchr("<=/>", cFirstChar))
 | |
| 			return str;            // Simboli terminali
 | |
| 	}
 | |
| 
 | |
| 	while (!inf.Eof())
 | |
| 	{
 | |
| 		int c = inf.GetC();
 | |
|     if (bIsString)
 | |
| 		{
 | |
| 			if (c == cFirstChar)
 | |
| 			  break;
 | |
| 			if (c >= '\0' && c <= ' ')
 | |
| 				c = ' ';
 | |
| 		  str += wxChar(c);
 | |
| 		}
 | |
| 		else
 | |
| 		{
 | |
| 			if (c >= '\0' && c <= ' ')
 | |
| 				break;
 | |
|       if (strchr("<=/>", c))
 | |
| 			{
 | |
| 				inf.Ungetch(char(c));
 | |
| 				break;
 | |
| 			}
 | |
|       if (c == '&')
 | |
|         str += EscapeSequence(c, inf);
 | |
|       else
 | |
| 			  str += wxChar(c);
 | |
| 		}
 | |
| 	}
 | |
|   return str;
 | |
| }
 | |
| 
 | |
| int TXmlItem::ReadTag(wxInputStream& inf)
 | |
| {
 | |
| 	wxString str = GetWord(inf);
 | |
|   if (str.IsEmpty())
 | |
| 		return -1;
 | |
| 
 | |
| 	if (str[0u] != '<')  // No tag = sequence of words
 | |
| 	{
 | |
| 		bool bFirstChar = true;
 | |
| 		while (!inf.Eof())
 | |
| 		{
 | |
| 		  wxChar c = inf.GetC();
 | |
| 			if (c == '<')
 | |
| 			{
 | |
| 				inf.Ungetch(c);
 | |
| 				break;
 | |
| 			}
 | |
| 			if (bFirstChar)
 | |
| 			{
 | |
|         if (c != ' ' && c != '=')
 | |
| 					str << ' ';
 | |
|         bFirstChar = false;
 | |
| 			}
 | |
|   		if (c == '&')
 | |
| 				str += EscapeSequence(c, inf);
 | |
| 			else
 | |
| 			  str << c;
 | |
| 		}
 | |
| 		SetTag("");
 | |
| 		SetText(str);  
 | |
| 		return 0;
 | |
| 	}
 | |
| 
 | |
| 	bool bChildrenFollow = true;
 | |
| 	
 | |
| 	m_strTag = GetWord(inf);
 | |
| 	if (m_strTag == "/")     // Sto leggendo un tag di chiusura del tipo </SOAP-ENV>
 | |
| 	{
 | |
| 		bChildrenFollow = false;
 | |
|     m_strTag += GetWord(inf);
 | |
| 	}
 | |
| 
 | |
| 	wxString name = GetWord(inf);
 | |
| 	while (!name.IsEmpty())
 | |
| 	{
 | |
|     if (name[ 0u] == '>')
 | |
| 			return bChildrenFollow ? +1 : 0;
 | |
| 
 | |
| 		if (name[0u] == '/')
 | |
| 		{
 | |
| 			bChildrenFollow = false;
 | |
| 			name = GetWord(inf);
 | |
| 			continue;
 | |
| 		}
 | |
| 
 | |
| 		// Ho letto un nome di attributo
 | |
| 		wxString str = GetWord(inf);
 | |
|     if (str.IsEmpty() || str[0u] != '=')
 | |
| 			break;
 | |
| 		// Leggo il valore dell'attributo
 | |
| 		str = GetWord(inf);
 | |
|     const size_t len = str.Len();
 | |
|     if (len >= 2 && (str[0] == '"' || str[0] == '\'') && str[len-1] == str[0])
 | |
|     {
 | |
| 			str = str.Mid(1, len - 2);
 | |
| 		}
 | |
|  		SetAttr(name, str);
 | |
| 
 | |
| 		name = GetWord(inf);
 | |
| 	}
 | |
| 	return -1;
 | |
| }
 | |
| 
 | |
| TXmlItem& TXmlItem::AddChild(TXmlItem* pItem)
 | |
| {
 | |
| 	if (m_Children == NULL)
 | |
| 	{
 | |
|     m_Children = new wxList;
 | |
| 		m_Children->DeleteContents(true);
 | |
| 	}
 | |
| 	if (pItem == NULL)
 | |
|     pItem = new TXmlItem;
 | |
| 	m_Children->Append(pItem);
 | |
| 	return *pItem;
 | |
| }
 | |
| 
 | |
| TXmlItem& TXmlItem::AddChild(const wxChar* strTagName)
 | |
| {
 | |
| 	TXmlItem& i = AddChild((TXmlItem*)NULL);
 | |
| 	i.SetTag(strTagName);
 | |
| 	return i;
 | |
| }
 | |
| 
 | |
| TXmlItem& TXmlItem::AddSoapString(const wxChar* name, const wxChar* value, bool typized)
 | |
| {
 | |
| 	TXmlItem& xmlVar = AddChild(name);
 | |
| 	if (typized)
 | |
| 	  xmlVar.SetAttr("xsi:type", "xsd:string");
 | |
|   xmlVar.AddChild("").SetText(value);
 | |
| 	return xmlVar;
 | |
| }
 | |
| 
 | |
| TXmlItem& TXmlItem::AddSoapInt(const wxChar* name, int value, bool typized)
 | |
| {
 | |
| 	TXmlItem& xmlVar = AddChild(name);
 | |
| 	if (typized)
 | |
|   	xmlVar.SetAttr("xsi:type", "xsd:int");
 | |
| 	wxString str; str += value;
 | |
|   xmlVar.AddChild("").SetText(str);
 | |
| 	return xmlVar;
 | |
| }
 | |
| 
 | |
| wxString TXmlItem::GetSoapString(const wxChar* tag, const wxChar* def) const
 | |
| {
 | |
|   const TXmlItem* i = FindFirst(tag);
 | |
|   return i != NULL ? i->GetEnclosedText().Trim() : def;
 | |
| }
 | |
|  
 | |
| long TXmlItem::GetSoapInt(const wxChar* tag, long def) const
 | |
| {
 | |
|   const wxString str = GetSoapString(tag);
 | |
|   long n; 
 | |
|   if (str.ToLong(&n))
 | |
|     def = n;
 | |
|   return def;
 | |
| }
 | |
| 
 | |
| void TXmlItem::RemoveLastChild()
 | |
| {
 | |
| 	if (m_Children != NULL)
 | |
| 	{
 | |
|     wxNode* n = m_Children->GetLast();
 | |
| 		if (n != NULL)
 | |
|       m_Children->DeleteNode(n);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| bool TXmlItem::Read(wxInputStream& inf)
 | |
| {
 | |
| 	int res = ReadTag(inf);
 | |
| 
 | |
| 	// Ignora la eventuale riga <?xml version="1.0" encoding="UTF-8" ?>
 | |
|   if (res == 0 && GetTag()[0] == '?') 
 | |
|     res = ReadTag(inf);
 | |
| 
 | |
| 	if (res > 0)  // There are children ahead
 | |
| 	{
 | |
| 		while (!inf.Eof())
 | |
| 		{
 | |
| 		  TXmlItem& item = AddChild("/");  // Add dummy child
 | |
| 		  if (item.Read(inf))
 | |
| 			{
 | |
| 				if (item.m_strTag[0u] == '/')
 | |
| 					break;
 | |
| 			}
 | |
| 			else
 | |
| 				break;
 | |
| 		}
 | |
| 		RemoveLastChild();                  // Remove dummy child
 | |
| 	}
 | |
| 	return res >= 0;
 | |
| }
 | |
| 
 | |
| TXmlItem* TXmlItem::ForEach(XmlItemCallback cb, void* jolly)
 | |
| {
 | |
| 	if (cb(*this, jolly))
 | |
| 		return this;
 | |
| 
 | |
| 	for (int n = 0; ; n++)
 | |
| 	{
 | |
| 		TXmlItem* c = GetChild(n);
 | |
| 		if (c == NULL)
 | |
| 			break;
 | |
| 		c = c->ForEach(cb, jolly);
 | |
|   	if (c)
 | |
| 	  	return c;
 | |
| 	}
 | |
| 
 | |
| 	return NULL;
 | |
| }
 | |
| 
 | |
| static bool GetEnclosedTextCallback(TXmlItem& item, void* jolly)
 | |
| {
 | |
|   wxString* strText = (wxString*)jolly;
 | |
| 	const wxString& str = item.GetText();
 | |
| 	if (!str.IsEmpty())
 | |
| 	{
 | |
| 		if (!strText->IsEmpty())
 | |
| 			*strText << " ";
 | |
| 	  *strText << str;
 | |
| 	}
 | |
| 	return false;
 | |
| }
 | |
| 
 | |
| wxString TXmlItem::GetEnclosedText() const
 | |
| {
 | |
| 	wxString text;
 | |
| 	((TXmlItem*)this)->ForEach(GetEnclosedTextCallback, &text);
 | |
| 	return text;
 | |
| }
 | |
| 
 | |
| TXmlItem& TXmlItem::AddEnclosedText(const wxChar* str)
 | |
| {
 | |
|   TXmlItem* item = FindFirst("");
 | |
| 	if (item == NULL)
 | |
| 		item = &AddChild("");
 | |
|   item->m_strText += str;
 | |
| 	return *item;
 | |
| }
 | |
| 
 | |
| TXmlItem& operator<<(TXmlItem& item, const wxChar* str)
 | |
| {
 | |
| 	item.AddEnclosedText(str);
 | |
| 	return item;
 | |
| }
 | |
| 
 | |
| void TXmlItem::Write(wxOutputStream& outf, int tab) const
 | |
| {
 | |
| 	if (!GetTag().IsEmpty())
 | |
| 	{
 | |
| 		Spaces(outf, tab);
 | |
| 	  outf << "<" << GetTag();
 | |
| 		if (m_Attributes != NULL)
 | |
| 		{
 | |
|       m_Attributes->BeginFind();
 | |
|       for (wxHashTable::Node* pNode = m_Attributes->Next(); pNode; pNode = m_Attributes->Next())
 | |
| 			{
 | |
| 				outf << " " << pNode->GetKeyString() << "=";
 | |
| 				const TXmlAttr* attr = (const TXmlAttr*)pNode->GetData();
 | |
| 				attr->Write(outf);
 | |
| 			}
 | |
| 		}
 | |
| 		if (GetChildren() > 0)
 | |
| 		{
 | |
| 			outf << ">";
 | |
| 			int n;
 | |
| 			
 | |
|       for (n = 0; ; n++)
 | |
| 			{
 | |
|         TXmlItem* c = GetChild(n);
 | |
| 				if (c == NULL)
 | |
| 					break;
 | |
| 				c->Write(outf, tab+1);
 | |
| 			}
 | |
| 			if (GetChild(n-1)->GetText().IsEmpty())
 | |
| 			  Spaces(outf, tab);
 | |
| 			outf << "</" << GetTag() << ">";
 | |
| 		}
 | |
| 		else
 | |
| 		  outf << " />";
 | |
| 	}
 | |
| 	else
 | |
| 		outf << GetText();
 | |
| }
 | |
| 
 | |
| wxString TXmlItem::AsString() const
 | |
| {
 | |
| 	wxString str;
 | |
| 	for (size_t nSize = 8192; ; nSize *= 2)
 | |
| 	{
 | |
| 	  wxChar* buf = str.GetWriteBuf(nSize); 
 | |
| 		memset(buf, 0, nSize);
 | |
| 		wxMemoryOutputStream outf(buf, nSize);
 | |
| 		Write(outf, 0);
 | |
| 		str.UngetWriteBuf();
 | |
| 		if (buf[nSize-1] == '\0')
 | |
| 			break;
 | |
| 	}
 | |
| 
 | |
| 	return str;
 | |
| }
 | |
| 
 | |
| void TXmlItem::Save(const wxChar* strFilename) const
 | |
| {
 | |
| 	wxFileOutputStream outf(strFilename);
 | |
| 	Write(outf, 0);
 | |
| }
 | |
| 
 | |
| static bool FindFirstCallback(TXmlItem& item, void* jolly)
 | |
| {
 | |
|   const wxChar* strTag = (const wxChar*)jolly;
 | |
| 	return item.GetTag() == strTag;
 | |
| }
 | |
| 
 | |
| TXmlItem* TXmlItem::FindFirst(const wxChar* strTag) const
 | |
| {
 | |
| 	return ((TXmlItem*)this)->ForEach(FindFirstCallback, (void*)strTag);
 | |
| }
 | |
| 
 | |
| TXmlItem::TXmlItem()
 | |
|         : m_Attributes(NULL), m_Children(NULL)
 | |
| { }
 | |
| 
 | |
| TXmlItem::~TXmlItem()
 | |
| { 
 | |
| 	if (m_Attributes)
 | |
| 		delete m_Attributes;
 | |
| 	if (m_Children)
 | |
| 		delete m_Children;
 | |
| } 
 | |
| 
 |