Skip to content

Instantly share code, notes, and snippets.

@rpgmaker
Created July 30, 2012 05:56
Show Gist options
  • Save rpgmaker/3205192 to your computer and use it in GitHub Desktop.
Save rpgmaker/3205192 to your computer and use it in GitHub Desktop.
XmlReaderEx (Initial 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, _hasValue, _hasTypeAttribute;
private StringBuilder sb;
const int DefaultSBCapacity = 1024 << 1;
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;
sb.Clear().Append(*_chrs);
do {
++_chrs;
if (*_chrs == Null || *_chrs == LessStr) break;
sb.Append(*_chrs);
} while (true);
return sb.ToString();
}
public bool Read(){
if (*_chrs == Null) return false;
_elementName = _attributeTypeValue = null;
_hasTypeAttribute = _hasValue = _isEndElement = false;
sb.Clear();
do {
++_chrs;
if (*_chrs == GreaterStr || *_chrs == Null) {
if (*_chrs != Null) ++_chrs;
break;
}
if (*_chrs == SpaceStr && _elementName == null) {
_elementName = sb.ToString();
sb.Clear();
_hasTypeAttribute = true;
_hasValue = false;
continue;
}
if (*_chrs != LessStr) {
sb.Append(*_chrs);
_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);
}
}
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