Skip to content

Instantly share code, notes, and snippets.

@rpgmaker
Created July 31, 2012 04:32
Show Gist options
  • Save rpgmaker/3213638 to your computer and use it in GitHub Desktop.
Save rpgmaker/3213638 to your computer and use it in GitHub Desktop.
XmlReaderEx (Working Draft)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
namespace PServiceBus.Serializer.Xml {
public unsafe class XmlReaderEx : IDisposable {
private char* _chrs;
private string _elementName, _attributeTypeValue;
private bool _disposed, _isEndElement;
private StringBuilder sb;
const int DefaultSBCapacity = 30;
const string TypeStr = "Type";
const char SpaceStr = ' ', GreaterStr = '>', LessStr = '<', BackSlash = '/', Null = '\0';
private static Regex _typeRegex = new Regex(@"type=""(?<Type>[^""]+)""", RegexOptions.Compiled);
public XmlReaderEx(string xml) {
_chrs = (char*)Marshal.StringToHGlobalUni(xml);
sb = new StringBuilder(DefaultSBCapacity);
}
public string ElementName { get { return _elementName; } }
public string TypeAttribute { get { return _attributeTypeValue; } }
public bool IsEndElement { get { return _isEndElement; } }
public string GetValue() {
if (_isEndElement) return string.Empty;
var current = *_chrs;
sb.Clear().Append(current);
do {
current = *(++_chrs);
if (current == LessStr || current == Null) break;
sb.Append(current);
} while (true);
return sb.ToString();
}
public bool Read(){
if (*_chrs == Null) return false;
_attributeTypeValue = null;
_isEndElement = false;
sb.Clear();
char current = Null;
bool hasValue = false, hasTypeAttribute = false;
string elementName = null;
do {
current = *(++_chrs);
if (current == GreaterStr || current == Null) {
if (current != Null) ++_chrs;
break;
}
if (current == SpaceStr && elementName == null) {
elementName = sb.ToString();
sb.Clear();
hasTypeAttribute = true;
hasValue = false;
continue;
}
if (current != LessStr) {
sb.Append(current);
hasValue = true;
}
} while (true);
if (hasValue) {
var text = sb.ToString();
if (hasTypeAttribute)
_attributeTypeValue = _typeRegex.Match(text).Groups[TypeStr].Value;
else if (elementName == null)
elementName = text;
if (elementName[0] == BackSlash) {
_isEndElement = true;
elementName = elementName.Substring(1);
}
}
_elementName = elementName;
return hasValue;
}
public void MoveToEndElement(string name) {
do {
if (_elementName == name && _isEndElement) break;
} while (Read());
}
protected void Dispose(bool disposing) {
if (_disposed) return;
if (disposing)
GC.SuppressFinalize(this);
_chrs = default(char*);
_disposed = true;
}
#region IDisposable Members
public void Dispose() {
Dispose(true);
}
#endregion
~XmlReaderEx() {
Dispose(false);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment