Exemple #1
0
        AXmlObject ReadSingleObject(IEnumerator <AXmlObject> objStream)
        {
            AXmlObject obj = objStream.Current;

            objStream.MoveNext();
            return(obj);
        }
        void RemoveChildrenNotIn(IList <AXmlObject> srcList)
        {
            Dictionary <int, AXmlObject> srcChildren = srcList.ToDictionary(i => i.StartOffset);

            for (int i = 0; i < this.Children.Count;)
            {
                AXmlObject child = this.Children[i];
                AXmlObject srcChild;

                if (srcChildren.TryGetValue(child.StartOffset, out srcChild) && child.CanUpdateDataFrom(srcChild))
                {
                    // Keep only one item with given offset (we might have several due to deletion)
                    srcChildren.Remove(child.StartOffset);
                    // If contaner that needs updating
                    AXmlContainer childAsContainer = child as AXmlContainer;
                    if (childAsContainer != null && child.LastUpdatedFrom != srcChild)
                    {
                        childAsContainer.RemoveChildrenNotIn(((AXmlContainer)srcChild).Children);
                    }
                    i++;
                }
                else
                {
                    RemoveChild(i);
                }
            }
        }
Exemple #3
0
        AXmlObject ReadTextOrElement(IEnumerator <AXmlObject> objStream)
        {
            AXmlObject curr = objStream.Current;

            if (curr is AXmlText || curr is AXmlElement)
            {
                return(ReadSingleObject(objStream));
            }
            else
            {
                AXmlTag currTag = (AXmlTag)curr;
                if (currTag == StartTagPlaceholder)
                {
                    return(ReadElement(objStream));
                }
                else if (currTag.IsStartOrEmptyTag)
                {
                    return(ReadElement(objStream));
                }
                else
                {
                    return(ReadSingleObject(objStream));
                }
            }
        }
        void InsertAndUpdateChildrenFrom(IList <AXmlObject> srcList)
        {
            for (int i = 0; i < srcList.Count; i++)
            {
                // End of our list?
                if (i == this.Children.Count)
                {
                    InsertChild(i, srcList[i]);
                    continue;
                }
                AXmlObject child    = this.Children[i];
                AXmlObject srcChild = srcList[i];

                if (child.CanUpdateDataFrom(srcChild))                   // includes offset test
                // Does it need updating?
                {
                    if (child.LastUpdatedFrom != srcChild)
                    {
                        child.UpdateDataFrom(srcChild);
                        AXmlContainer childAsContainer = child as AXmlContainer;
                        if (childAsContainer != null)
                        {
                            childAsContainer.InsertAndUpdateChildrenFrom(((AXmlContainer)srcChild).Children);
                        }
                    }
                }
                else
                {
                    InsertChild(i, srcChild);
                }
            }
            Assert(this.Children.Count == srcList.Count, "List lengths differ after update");
        }
Exemple #5
0
 /// <summary> Is call to UpdateDataFrom is allowed? </summary>
 internal bool CanUpdateDataFrom(AXmlObject source)
 {
     return
         (this.GetType() == source.GetType() &&
          this.StartOffset == source.StartOffset &&
          (this.LastUpdatedFrom == source || !this.IsCached));
 }
Exemple #6
0
        /// <inheritdoc/>
        internal override bool UpdateDataFrom(AXmlObject source)
        {
            if (!base.UpdateDataFrom(source))
            {
                return(false);
            }
            AXmlElement src = (AXmlElement)source;

            // Clear the cache for this - quite expensive
            attributesAndElements = null;
            if (this.IsProperlyNested != src.IsProperlyNested ||
                this.HasStartOrEmptyTag != src.HasStartOrEmptyTag ||
                this.HasEndTag != src.HasEndTag)
            {
                OnChanging();
                this.IsProperlyNested   = src.IsProperlyNested;
                this.HasStartOrEmptyTag = src.HasStartOrEmptyTag;
                this.HasEndTag          = src.HasEndTag;
                OnChanged();
                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <summary> Add object to cache, optionally adding extra memory tracking </summary>
        public void AddParsedObject(AXmlObject obj, int?maxTouchedLocation)
        {
            if (!(obj.Length > 0 || obj is AXmlDocument))
            {
                AXmlParser.Assert(false, string.Format(CultureInfo.InvariantCulture, "Invalid object {0}.  It has zero length.", obj));
            }
//			// Expensive check
//			if (obj is AXmlContainer) {
//				int objStartOffset = obj.StartOffset;
//				int objEndOffset = obj.EndOffset;
//				foreach(AXmlObject child in ((AXmlContainer)obj).Children) {
//					AXmlParser.Assert(objStartOffset <= child.StartOffset && child.EndOffset <= objEndOffset, "Wrong nesting");
//				}
//			}
            segments.Add(obj);
            AddSyntaxErrorsOf(obj);
            obj.IsCached = true;
            if (maxTouchedLocation != null)
            {
                // location is assumed to be read so the range ends at (location + 1)
                // For example eg for "a_" it is (0-2)
                TouchedRange range = new TouchedRange()
                {
                    StartOffset     = obj.StartOffset,
                    EndOffset       = maxTouchedLocation.Value + 1,
                    TouchedByObject = obj
                };
                segments.Add(range);
                AXmlParser.Log("{0} touched range ({1}-{2})", obj, range.StartOffset, range.EndOffset);
            }
        }
 public void AddSyntaxErrorsOf(AXmlObject obj)
 {
     foreach (SyntaxError syntaxError in obj.MySyntaxErrors)
     {
         segments.Add(syntaxError);
     }
 }
 public void RemoveSyntaxErrorsOf(AXmlObject obj)
 {
     foreach (SyntaxError syntaxError in obj.MySyntaxErrors)
     {
         segments.Remove(syntaxError);
     }
 }
 internal void OnObjectRemoved(int index, AXmlObject obj)
 {
     if (ObjectRemoved != null)
     {
         ObjectRemoved(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new AXmlObject[] { obj }.ToList(), index));
     }
 }
        /// <summary> Verify that the subtree is consistent.  Only in debug build. </summary>
        /// <remarks> Parent pointers might be null or pointing somewhere else in parse tree </remarks>
        internal override void DebugCheckConsistency(bool checkParentPointers)
        {
            base.DebugCheckConsistency(checkParentPointers);
            AXmlObject prevChild     = null;
            int        myStartOffset = this.StartOffset;
            int        myEndOffset   = this.EndOffset;

            foreach (AXmlObject child in this.Children)
            {
                Assert(child.Length != 0, "Empty child");
                if (checkParentPointers)
                {
                    Assert(child.Parent != null, "Null parent reference");
                    Assert(child.Parent == this, "Inccorect parent reference");
                }
                if (this.Document != null)
                {
                    Assert(child.Document != null, "Child has null document");
                    Assert(child.Document == this.Document, "Child is in different document");
                }
                if (this.IsCached)
                {
                    Assert(child.IsCached, "Child not in cache");
                }
                Assert(myStartOffset <= child.StartOffset && child.EndOffset <= myEndOffset, "Child not within parent text range");
                if (prevChild != null)
                {
                    Assert(prevChild.EndOffset <= child.StartOffset, "Overlaping childs");
                }
                child.DebugCheckConsistency(checkParentPointers);
                prevChild = child;
            }
        }
        /// <inheritdoc/>
        internal override bool UpdateDataFrom(AXmlObject source)
        {
            if (!base.UpdateDataFrom(source))
            {
                return(false);
            }
            AXmlAttribute src = (AXmlAttribute)source;

            if (this.Name != src.Name ||
                this.EqualsSign != src.EqualsSign ||
                this.QuotedValue != src.QuotedValue ||
                this.Value != src.Value)
            {
                OnChanging();
                this.Name        = src.Name;
                this.EqualsSign  = src.EqualsSign;
                this.QuotedValue = src.QuotedValue;
                this.Value       = src.Value;
                OnChanged();
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #13
0
        int GetIndentLevel(AXmlObject obj)
        {
            int offset = obj.StartOffset - 1;
            int level  = 0;

            while (true)
            {
                if (offset < 0)
                {
                    break;
                }
                char c = input[offset];
                if (c == ' ')
                {
                    level++;
                }
                else if (c == '\t')
                {
                    level += 4;
                }
                else if (c == '\r' || c == '\n')
                {
                    break;
                }
                else
                {
                    return(-1);
                }
                offset--;
            }
            return(level);
        }
Exemple #14
0
        IEnumerable <AXmlObject> Split(AXmlElement elem)
        {
            int myIndention = GetIndentLevel(elem);

            // Has start tag and no end tag ?  (other then empty-element tag)
            if (elem.HasStartOrEmptyTag && elem.StartTag.IsStartTag && !elem.HasEndTag && myIndention != -1)
            {
                int lastAccepted = 0;                 // Accept start tag
                while (lastAccepted + 1 < elem.Children.Count)
                {
                    AXmlObject nextItem = elem.Children[lastAccepted + 1];
                    if (nextItem is AXmlText)
                    {
                        lastAccepted++; continue;                          // Accept
                    }
                    else
                    {
                        // Include all more indented items
                        if (GetIndentLevel(nextItem) > myIndention)
                        {
                            lastAccepted++; continue;                              // Accept
                        }
                        else
                        {
                            break;                              // Reject
                        }
                    }
                }
                // Accepted everything?
                if (lastAccepted + 1 == elem.Children.Count)
                {
                    yield return(elem);

                    yield break;
                }
                AXmlParser.Log("Splitting {0} - take {1} of {2} nested", elem, lastAccepted, elem.Children.Count - 1);
                AXmlElement topHalf = new AXmlElement();
                topHalf.HasStartOrEmptyTag = elem.HasStartOrEmptyTag;
                topHalf.HasEndTag          = elem.HasEndTag;
                topHalf.AddChildren(elem.Children.Take(1 + lastAccepted));                    // Start tag + nested
                topHalf.StartOffset = topHalf.FirstChild.StartOffset;
                topHalf.EndOffset   = topHalf.LastChild.EndOffset;
                TagReader.OnSyntaxError(topHalf, topHalf.LastChild.EndOffset, topHalf.LastChild.EndOffset,
                                        "Expected '</{0}>'", topHalf.StartTag.Name);

                AXmlParser.Log("Constructed {0}", topHalf);
                trackedSegments.AddParsedObject(topHalf, null);
                yield return(topHalf);

                for (int i = lastAccepted + 1; i < elem.Children.Count; i++)
                {
                    yield return(elem.Children[i]);
                }
            }
            else
            {
                yield return(elem);
            }
        }
        // Only these four methods should be used to modify the collection

        /// <summary> To be used exlucively by the parser </summary>
        internal void AddChild(AXmlObject item)
        {
            // Childs can be only added to newly parsed items
            Assert(this.Parent == null, "I have to be new");
            Assert(item.IsCached, "Added item must be in cache");
            // Do not set parent pointer
            this.Children.InsertItemAt(this.Children.Count, item);
        }
		internal SyntaxError Clone(AXmlObject newOwner)
		{
			return new SyntaxError {
				Object = newOwner,
				Message = Message,
				Tag = Tag,
				StartOffset = StartOffset,
				EndOffset = EndOffset,
			};
		}
 internal void OnObjectChanged(AXmlObject obj)
 {
     if (ObjectChanged != null)
     {
         ObjectChanged(this, new AXmlObjectEventArgs()
         {
             Object = obj
         });
     }
 }
Exemple #18
0
 internal SyntaxError Clone(AXmlObject newOwner)
 {
     return(new SyntaxError {
         Object = newOwner,
         Message = Message,
         Tag = Tag,
         StartOffset = StartOffset,
         EndOffset = EndOffset,
     });
 }
Exemple #19
0
        public IEnumerable <AXmlObject> GetAncestors()
        {
            AXmlObject curr = this.Parent;

            while (curr != null)
            {
                yield return(curr);

                curr = curr.Parent;
            }
        }
 /// <summary> Invalidates items, but keeps tracking them </summary>
 /// <remarks> Can be called redundantly (from range tacking) </remarks>
 void InvalidateCache(AXmlObject obj, bool includeParents)
 {
     if (includeParents)
     {
         foreach (AXmlObject parent in FindParents(obj))
         {
             parent.IsCached = false;
             AXmlParser.Log("Invalidating cached item {0} (it is parent)", parent);
         }
     }
     obj.IsCached = false;
     AXmlParser.Log("Invalidating cached item {0}", obj);
 }
        /// <summary>
        /// To be used exclusively by the children update algorithm.
        /// Insert child and keep links consistent.
        /// </summary>
        void InsertChild(int index, AXmlObject item)
        {
            AXmlParser.Log("Inserting {0} at index {1}", item, index);

            Assert(this.Document != null, "Can not insert to dangling object");
            Assert(item.Parent != this, "Can not own item twice");

            SetParentPointersInTree(item);

            this.Children.InsertItemAt(index, item);

            this.Document.OnObjectInserted(index, item);
        }
        IEnumerable <AXmlObject> FindParents(AXmlObject child)
        {
            int childStartOffset = child.StartOffset;
            int childEndOffset   = child.EndOffset;

            foreach (AXmlObject parent in segments.FindSegmentsContaining(child.StartOffset).OfType <AXmlObject>())
            {
                // Parent is anyone wholy containg the child
                if (parent.StartOffset <= childStartOffset && childEndOffset <= parent.EndOffset && parent != child)
                {
                    yield return(parent);
                }
            }
        }
 public static void OnSyntaxError(AXmlObject obj, int start, int end, string message, params object[] args)
 {
     if (end <= start)
     {
         end = start + 1;
     }
     AXmlParser.Log("Syntax error ({0}-{1}): {2}", start, end, string.Format(message, args));
     obj.AddSyntaxError(new SyntaxError()
     {
         Object      = obj,
         StartOffset = start,
         EndOffset   = end,
         Message     = string.Format(message, args),
     });
 }
		/// <inheritdoc/>
		internal override bool UpdateDataFrom(AXmlObject source)
		{
			if (!base.UpdateDataFrom(source)) return false;
			AXmlText src = (AXmlText)source;
			if (this.EscapedValue != src.EscapedValue ||
			    this.Value != src.Value)
			{
				OnChanging();
				this.EscapedValue = src.EscapedValue;
				this.Value = src.Value;
				OnChanged();
				return true;
			} else {
				return false;
			}
		}
Exemple #25
0
        public static void OnSyntaxError(AXmlObject obj, int start, int end, string message, params object[] args)
        {
            if (end <= start)
            {
                end = start + 1;
            }
            string formattedMessage = string.Format(CultureInfo.InvariantCulture, message, args);

            AXmlParser.Log("Syntax error ({0}-{1}): {2}", start, end, formattedMessage);
            obj.AddSyntaxError(new SyntaxError()
            {
                Object      = obj,
                StartOffset = start,
                EndOffset   = end,
                Message     = formattedMessage,
            });
        }
Exemple #26
0
        /// <summary> Copy all data from the 'source' to this object </summary>
        /// <remarks> Returns true if any updates were done </remarks>
        internal virtual bool UpdateDataFrom(AXmlObject source)
        {
            Assert(this.GetType() == source.GetType(), "Source has different type");
            DebugAssert(this.StartOffset == source.StartOffset, "Source has different StartOffset");

            if (this.LastUpdatedFrom == source)
            {
                DebugAssert(this.EndOffset == source.EndOffset, "Source has different EndOffset");
                return(false);
            }

            Assert(!this.IsCached, "Can not update cached item");
            Assert(source.IsCached, "Must update from cache");

            this.LastUpdatedFrom = source;
            this.StartOffset     = source.StartOffset;
            // In some cases we are just updating objects of that same
            // type and position and hoping to be luckily right
            this.EndOffset = source.EndOffset;

            // Do not bother comparing - assume changed if non-null
            if (this.syntaxErrors != null || source.syntaxErrors != null)
            {
                // May be called again in derived class - oh, well, does not matter
                OnChanging();
                this.Document.Parser.TrackedSegments.RemoveSyntaxErrorsOf(this);
                if (source.syntaxErrors == null)
                {
                    this.syntaxErrors = null;
                }
                else
                {
                    this.syntaxErrors = new List <SyntaxError>();
                    foreach (var error in source.MySyntaxErrors)
                    {
                        // The object differs, so create our own copy
                        // The source still might need it in the future and we do not want to break it
                        this.AddSyntaxError(error.Clone(this));
                    }
                }
                this.Document.Parser.TrackedSegments.AddSyntaxErrorsOf(this);
                OnChanged();
            }

            return(true);
        }
Exemple #27
0
		/// <inheritdoc/>
		internal override bool UpdateDataFrom(AXmlObject source)
		{
			if (!base.UpdateDataFrom(source)) return false;
			AXmlTag src = (AXmlTag)source;
			if (this.OpeningBracket != src.OpeningBracket ||
				this.Name != src.Name ||
				this.ClosingBracket != src.ClosingBracket)
			{
				OnChanging();
				this.OpeningBracket = src.OpeningBracket;
				this.Name = src.Name;
				this.ClosingBracket = src.ClosingBracket;
				OnChanged();
				return true;
			} else {
				return false;
			}
		}
        /// <summary> Removes object with all of its non-cached children </summary>
        public void RemoveParsedObject(AXmlObject obj)
        {
            // Cached objects may be used in the future - do not remove them
            if (obj.IsCached)
            {
                return;
            }
            segments.Remove(obj);
            RemoveSyntaxErrorsOf(obj);
            AXmlParser.Log("Stopped tracking {0}", obj);

            if (obj is AXmlContainer)
            {
                foreach (AXmlObject child in ((AXmlContainer)obj).Children)
                {
                    RemoveParsedObject(child);
                }
            }
        }
        /// <summary>
        /// To be used exclusively by the children update algorithm.
        /// Remove child, set parent to null and notify the document
        /// </summary>
        void RemoveChild(int index)
        {
            AXmlObject removed = this.Children[index];

            AXmlParser.Log("Removing {0} at index {1}", removed, index);

            // Stop tracking if the object can not be used again
            if (!removed.IsCached)
            {
                this.Document.Parser.TrackedSegments.RemoveParsedObject(removed);
            }

            // Null parent pointer
            Assert(removed.Parent == this, "Inconsistent child");
            removed.Parent = null;

            this.Children.RemoveItemAt(index);

            this.Document.OnObjectRemoved(index, removed);
        }
Exemple #30
0
		/// <inheritdoc/>
		internal override bool UpdateDataFrom(AXmlObject source)
		{
			if (!base.UpdateDataFrom(source)) return false;
			AXmlElement src = (AXmlElement)source;
			// Clear the cache for this - quite expensive
			attributesAndElements = null;
			if (this.IsProperlyNested != src.IsProperlyNested ||
				this.HasStartOrEmptyTag != src.HasStartOrEmptyTag ||
				this.HasEndTag != src.HasEndTag)
			{
				OnChanging();
				this.IsProperlyNested = src.IsProperlyNested;
				this.HasStartOrEmptyTag = src.HasStartOrEmptyTag;
				this.HasEndTag = src.HasEndTag;
				OnChanged();
				return true;
			} else {
				return false;
			}
		}
        /// <summary> Recursively fix all parent pointer in a tree </summary>
        /// <remarks>
        /// Cache constraint:
        ///    If cached item has parent set, then the whole subtree must be consistent and document set
        /// </remarks>
        void SetParentPointersInTree(AXmlObject item)
        {
            // All items come from the parser cache

            if (item.Parent == null)
            {
                // Dangling object - either a new parser object or removed tree (still cached)
                item.Parent   = this;
                item.Document = this.Document;
                AXmlContainer container = item as AXmlContainer;
                if (container != null)
                {
                    foreach (AXmlObject child in container.Children)
                    {
                        container.SetParentPointersInTree(child);
                    }
                }
            }
            else if (item.Parent == this)
            {
                // If node is attached and then deattached, it will have null parent pointer
                //   but valid subtree - so its children will alredy have correct parent pointer
                //   like in this case
                // item.DebugCheckConsistency(false);
                // Rest of the tree is consistent - do not recurse
            }
            else
            {
                // From cache & parent set => consitent subtree
                // item.DebugCheckConsistency(false);
                // The parent (or any futher parents) can not be part of parsed document
                //   becuase otherwise this item would be included twice => safe to change parents
                // Maintain cache constraint by setting parents to null
                foreach (AXmlObject ancest in item.GetAncestors().ToList())
                {
                    ancest.Parent = null;
                }
                item.Parent = this;
                // Rest of the tree is consistent - do not recurse
            }
        }
Exemple #32
0
        /// <inheritdoc/>
        internal override bool UpdateDataFrom(AXmlObject source)
        {
            if (!base.UpdateDataFrom(source))
            {
                return(false);
            }
            AXmlText src = (AXmlText)source;

            if (this.EscapedValue != src.EscapedValue ||
                this.Value != src.Value)
            {
                OnChanging();
                this.EscapedValue = src.EscapedValue;
                this.Value        = src.Value;
                OnChanged();
                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <inheritdoc/>
        internal override bool UpdateDataFrom(AXmlObject source)
        {
            if (!base.UpdateDataFrom(source))
            {
                return(false);
            }
            AXmlTag src = (AXmlTag)source;

            if (this.OpeningBracket != src.OpeningBracket ||
                this.Name != src.Name ||
                this.ClosingBracket != src.ClosingBracket)
            {
                OnChanging();
                this.OpeningBracket = src.OpeningBracket;
                this.Name           = src.Name;
                this.ClosingBracket = src.ClosingBracket;
                OnChanged();
                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemple #34
0
        string Dereference(AXmlObject owner, string text, int textLocation)
        {
            StringBuilder sb   = null;            // The dereferenced text so far (all up to 'curr')
            int           curr = 0;

            while (true)
            {
                // Reached end of input
                if (curr == text.Length)
                {
                    if (sb != null)
                    {
                        return(sb.ToString());
                    }
                    else
                    {
                        return(text);
                    }
                }

                // Try to find reference
                int start = text.IndexOf('&', curr);

                // No more references found
                if (start == -1)
                {
                    if (sb != null)
                    {
                        sb.Append(text, curr, text.Length - curr);                         // Add rest
                        return(sb.ToString());
                    }
                    else
                    {
                        return(text);
                    }
                }

                // Append text before the enitiy reference
                if (sb == null)
                {
                    sb = new StringBuilder(text.Length);
                }
                sb.Append(text, curr, start - curr);
                curr = start;

                // Process the entity
                int errorLoc = textLocation + sb.Length;

                // Find entity name
                int end = text.IndexOfAny(new char[] { '&', ';' }, start + 1, Math.Min(maxEntityLength, text.Length - (start + 1)));
                if (end == -1 || text[end] == '&')
                {
                    // Not found
                    OnSyntaxError(owner, errorLoc, errorLoc + 1, "Entity reference must be terminated with ';'");
                    // Keep '&'
                    sb.Append('&');
                    curr++;
                    continue;                      // Restart and next character location
                }
                string name = text.Substring(start + 1, end - (start + 1));

                // Resolve the name
                string replacement;
                if (name.Length == 0)
                {
                    replacement = null;
                    OnSyntaxError(owner, errorLoc + 1, errorLoc + 1, "Entity name expected");
                }
                else if (name == "amp")
                {
                    replacement = "&";
                }
                else if (name == "lt")
                {
                    replacement = "<";
                }
                else if (name == "gt")
                {
                    replacement = ">";
                }
                else if (name == "apos")
                {
                    replacement = "'";
                }
                else if (name == "quot")
                {
                    replacement = "\"";
                }
                else if (name.Length > 0 && name[0] == '#')
                {
                    int num;
                    if (name.Length > 1 && name[1] == 'x')
                    {
                        if (!int.TryParse(name.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture.NumberFormat, out num))
                        {
                            num = -1;
                            OnSyntaxError(owner, errorLoc + 3, errorLoc + 1 + name.Length, "Hexadecimal code of unicode character expected");
                        }
                    }
                    else
                    {
                        if (!int.TryParse(name.Substring(1), NumberStyles.None, CultureInfo.InvariantCulture.NumberFormat, out num))
                        {
                            num = -1;
                            OnSyntaxError(owner, errorLoc + 2, errorLoc + 1 + name.Length, "Numeric code of unicode character expected");
                        }
                    }
                    if (num != -1)
                    {
                        try {
                            replacement = char.ConvertFromUtf32(num);
                        } catch (ArgumentOutOfRangeException) {
                            replacement = null;
                            OnSyntaxError(owner, errorLoc + 2, errorLoc + 1 + name.Length, "Invalid unicode character U+{0:X} ({0})", num);
                        }
                    }
                    else
                    {
                        replacement = null;
                    }
                }
                else if (!IsValidName(name))
                {
                    replacement = null;
                    OnSyntaxError(owner, errorLoc + 1, errorLoc + 1, "Invalid entity name");
                }
                else
                {
                    replacement = null;
                    if (parser.UnknownEntityReferenceIsError)
                    {
                        OnSyntaxError(owner, errorLoc, errorLoc + 1 + name.Length + 1, "Unknown entity reference '{0}'", name);
                    }
                }

                // Append the replacement to output
                if (replacement != null)
                {
                    sb.Append(replacement);
                }
                else
                {
                    sb.Append('&');
                    sb.Append(name);
                    sb.Append(';');
                }
                curr = end + 1;
                continue;
            }
        }
Exemple #35
0
		/// <summary> Is call to UpdateDataFrom is allowed? </summary>
		internal bool CanUpdateDataFrom(AXmlObject source)
		{
			return
				this.GetType() == source.GetType() &&
				this.StartOffset == source.StartOffset &&
				(this.LastUpdatedFrom == source || !this.IsCached);
		}
		// Only these four methods should be used to modify the collection
		
		/// <summary> To be used exlucively by the parser </summary>
		internal void AddChild(AXmlObject item)
		{
			// Childs can be only added to newly parsed items
			Assert(this.Parent == null, "I have to be new");
			Assert(item.IsCached, "Added item must be in cache");
			// Do not set parent pointer
			this.Children.InsertItemAt(this.Children.Count, item);
		}
		/// <summary> Recursively fix all parent pointer in a tree </summary>
		/// <remarks>
		/// Cache constraint:
		///    If cached item has parent set, then the whole subtree must be consistent and document set
		/// </remarks>
		void SetParentPointersInTree(AXmlObject item)
		{
			// All items come from the parser cache
			
			if (item.Parent == null) {
				// Dangling object - either a new parser object or removed tree (still cached)
				item.Parent = this;
				item.Document = this.Document;
				if (item is AXmlContainer) {
					foreach(AXmlObject child in ((AXmlContainer)item).Children) {
						((AXmlContainer)item).SetParentPointersInTree(child);
					}
				}
			} else if (item.Parent == this) {
				// If node is attached and then deattached, it will have null parent pointer
				//   but valid subtree - so its children will alredy have correct parent pointer
				//   like in this case
				// item.DebugCheckConsistency(false);
				// Rest of the tree is consistent - do not recurse
			} else {
				// From cache & parent set => consitent subtree
				// item.DebugCheckConsistency(false);
				// The parent (or any futher parents) can not be part of parsed document
				//   becuase otherwise this item would be included twice => safe to change parents
				// Maintain cache constraint by setting parents to null
				foreach(AXmlObject ancest in item.GetAncestors().ToList()) {
					ancest.Parent = null; 
				}
				item.Parent = this;
				// Rest of the tree is consistent - do not recurse
			}
		}
		/// <summary>
		/// To be used exclusively by the children update algorithm.
		/// Insert child and keep links consistent.
		/// </summary>
		void InsertChild(int index, AXmlObject item)
		{
			AXmlParser.Log("Inserting {0} at index {1}", item, index);
			
			Assert(this.Document != null, "Can not insert to dangling object");
			Assert(item.Parent != this, "Can not own item twice");
			
			SetParentPointersInTree(item);
			
			this.Children.InsertItemAt(index, item);
			
			this.Document.OnObjectInserted(index, item);
		}
Exemple #39
0
		/// <summary> Copy all data from the 'source' to this object </summary>
		/// <remarks> Returns true if any updates were done </remarks>
		internal virtual bool UpdateDataFrom(AXmlObject source)
		{
			Assert(this.GetType() == source.GetType(), "Source has different type");
			DebugAssert(this.StartOffset == source.StartOffset, "Source has different StartOffset");
			
			if (this.LastUpdatedFrom == source) {
				DebugAssert(this.EndOffset == source.EndOffset, "Source has different EndOffset");
				return false;
			}
			
			Assert(!this.IsCached, "Can not update cached item");
			Assert(source.IsCached, "Must update from cache");
			
			this.LastUpdatedFrom = source;
			this.StartOffset = source.StartOffset;
			// In some cases we are just updating objects of that same
			// type and position and hoping to be luckily right
			this.EndOffset = source.EndOffset;
			
			// Do not bother comparing - assume changed if non-null
			if (this.syntaxErrors != null || source.syntaxErrors != null) {
				// May be called again in derived class - oh, well, does not matter
				OnChanging();
				this.Document.Parser.TrackedSegments.RemoveSyntaxErrorsOf(this);
				if (source.syntaxErrors == null) {
					this.syntaxErrors = null;
				} else {
					this.syntaxErrors = new List<SyntaxError>();
					foreach(var error in source.MySyntaxErrors) {
						// The object differs, so create our own copy
						// The source still might need it in the future and we do not want to break it
						this.AddSyntaxError(error.Clone(this));
					}
				}
				this.Document.Parser.TrackedSegments.AddSyntaxErrorsOf(this);
				OnChanged();
			}
			
			return true;
		}
		internal void OnObjectRemoved(int index, AXmlObject obj)
		{
			if (ObjectRemoved != null)
				ObjectRemoved(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new AXmlObject[] { obj }.ToList(), index));
		}
		/// <inheritdoc/>
		internal override bool UpdateDataFrom(AXmlObject source)
		{
			if (!base.UpdateDataFrom(source)) return false;
			AXmlAttribute src = (AXmlAttribute)source;
			if (this.Name != src.Name ||
				this.EqualsSign != src.EqualsSign ||
				this.QuotedValue != src.QuotedValue ||
				this.Value != src.Value)
			{
				OnChanging();
				this.Name = src.Name;
				this.EqualsSign = src.EqualsSign;
				this.QuotedValue = src.QuotedValue;
				this.Value = src.Value;
				OnChanged();
				return true;
			} else {
				return false;
			}
		}
		internal void OnObjectChanged(AXmlObject obj)
		{
			if (ObjectChanged != null)
				ObjectChanged(this, new AXmlObjectEventArgs() { Object = obj } );
		}