Skip to content

Instantly share code, notes, and snippets.

@rpgmaker
Created August 5, 2012 06:28
Show Gist options
  • Save rpgmaker/3262261 to your computer and use it in GitHub Desktop.
Save rpgmaker/3262261 to your computer and use it in GitHub Desktop.
XmlReaderEx (Improved Version 2)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Security;
namespace PServiceBus.Serializer.Xml {
public unsafe sealed class XmlReaderEx {
private int _index;
private string _elementName, _attributeTypeValue, _xml;
private bool _isEndElement;
const string TypeStr = "Type", Quote = "\"";
const char SpaceStr = ' ', GreaterStr = '>', LessStr = '<', BackSlash = '/', Null = '\0';
public XmlReaderEx(string xml) {
_xml = xml;
}
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 count = 1;
fixed (char* p = _xml) {
char* chrs = p + _index;
if (*chrs == Null) return string.Empty;
var current = Null;
do {
current = *(++chrs);
_index++;
if (current == LessStr) break;
count++;
} while (true);
var str = new string(Null, count);
fixed (char* cp = str)
memcpy(cp, chrs - count, count);
return str;
}
}
public bool Read(){
char current = Null;
bool hasValue = false, hasTypeAttribute = false;
string elementName = null;
int count = 0;
fixed (char* p = _xml) {
char* chrs = p + _index;
if (*chrs == Null) return false;
_attributeTypeValue = null;
_isEndElement = false;
do {
current = *(++chrs);
count++;
_index++;
if (current == GreaterStr) {
_index++;
++chrs;
break;
}
if (current == SpaceStr && elementName == null) {
var size = count - 1;
elementName = new string(Null, size);
fixed (char* cp = elementName)
memcpy(cp, chrs - size, size);
count = 0;
hasTypeAttribute = true;
continue;
}
} while (true);
if (hasValue = (count > 0 && *(chrs - count) != Null)) {
var text = GetString(chrs, count);
if (hasTypeAttribute) {
var index = text.IndexOf(Quote, StringComparison.Ordinal) + 1;
var endIndex = text.LastIndexOf(Quote, StringComparison.Ordinal);
_attributeTypeValue = text.Substring(index, endIndex - index);
} else if (elementName == null)
elementName = text;
if (elementName[0] == BackSlash) {
_isEndElement = true;
elementName = elementName.Substring(1);
}
}
}
_elementName = elementName;
return hasValue;
}
private unsafe static string GetString(char* chrs, int count) {
var size = count - 1;
var str = new string(Null, size);
fixed (char* cp = str)
memcpy(cp, chrs - count, size);
return str;
}
private static unsafe void memcpy(char* dmem, char* smem, int charCount) {
if ((((int)dmem) & 2) != 0) {
dmem[0] = smem[0];
dmem++;
smem++;
charCount--;
}
while (charCount >= 8) {
*((int*)dmem) = *((int*)smem);
*((int*)(dmem + 2)) = *((int*)(smem + 2));
*((int*)(dmem + 4)) = *((int*)(smem + 4));
*((int*)(dmem + 6)) = *((int*)(smem + 6));
dmem += 8;
smem += 8;
charCount -= 8;
}
if ((charCount & 4) != 0) {
*((int*)dmem) = *((int*)smem);
*((int*)(dmem + 2)) = *((int*)(smem + 2));
dmem += 4;
smem += 4;
}
if ((charCount & 2) != 0) {
*((int*)dmem) = *((int*)smem);
dmem += 2;
smem += 2;
}
if ((charCount & 1) != 0) {
dmem[0] = smem[0];
}
}
public void MoveToEndElement(string name) {
do {
if (_elementName == name && _isEndElement) return;
} while (Read());
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment