/// <summary> /// Advances a reading position by one character code /// and reads the next availbale character from a stream. /// This character becomes available as NextCharacter property. /// </summary> /// <remarks> /// Throws InvalidOperationException if attempted to be called on EndOfStream /// condition. /// </remarks> private void GetNextCharacter() { if (_nextCharacterCode == -1) { throw new InvalidOperationException("GetNextCharacter method called at the end of a stream"); } _previousCharacter = _nextCharacter; _nextCharacter = _lookAheadCharacter; _nextCharacterCode = _lookAheadCharacterCode; // next character not an entity as of now _isNextCharacterEntity = false; this.ReadLookAheadCharacter(); if (_nextCharacter == '&') { if (_lookAheadCharacter == '#') { // numeric entity - parse digits - &#DDDDD; int entityCode; entityCode = 0; this.ReadLookAheadCharacter(); // largest numeric entity is 7 characters for (int i = 0; i < 7 && Char.IsDigit(_lookAheadCharacter); i++) { entityCode = 10 * entityCode + (_lookAheadCharacterCode - (int)'0'); this.ReadLookAheadCharacter(); } if (_lookAheadCharacter == ';') { // correct format - advance this.ReadLookAheadCharacter(); _nextCharacterCode = entityCode; // if this is out of range it will set the character to '?' _nextCharacter = (char)_nextCharacterCode; // as far as we are concerned, this is an entity _isNextCharacterEntity = true; } else { // not an entity, set next character to the current lookahread character // we would have eaten up some digits _nextCharacter = _lookAheadCharacter; _nextCharacterCode = _lookAheadCharacterCode; this.ReadLookAheadCharacter(); _isNextCharacterEntity = false; } } else if (Char.IsLetter(_lookAheadCharacter)) { // entity is written as a string string entity = ""; // maximum length of string entities is 10 characters for (int i = 0; i < 10 && (Char.IsLetter(_lookAheadCharacter) || Char.IsDigit(_lookAheadCharacter)); i++) { entity += _lookAheadCharacter; this.ReadLookAheadCharacter(); } if (_lookAheadCharacter == ';') { // advance this.ReadLookAheadCharacter(); if (HtmlSchema.IsEntity(entity)) { _nextCharacter = HtmlSchema.EntityCharacterValue(entity); _nextCharacterCode = (int)_nextCharacter; _isNextCharacterEntity = true; } else { // just skip the whole thing - invalid entity // move on to the next character _nextCharacter = _lookAheadCharacter; _nextCharacterCode = _lookAheadCharacterCode; this.ReadLookAheadCharacter(); // not an entity _isNextCharacterEntity = false; } } else { // skip whatever we read after the ampersand // set next character and move on _nextCharacter = _lookAheadCharacter; this.ReadLookAheadCharacter(); _isNextCharacterEntity = false; } } } }