[prev in list] [next in list] [prev in thread] [next in thread]
List: mono-patches
Subject: [Mono-patches] [mono/mono] [3 commits] e07a7150: Reimplemented
From: "Atsushi Eno (atsushi () ximian ! com)" <mono-patches () lists ! ximian ! com>
Date: 2011-03-31 13:41:24
Message-ID: 20110331134124.B562222129 () mono ! ximian ! com
[Download RAW message or body]
Branch: refs/heads/master
Home: https://github.com/mono/mono
Commit: e07a7150a780b10a2fd1c46d2e4caca23dc340eb
Author: Atsushi Eno <atsushi@ximian.com>
Date: 03/31/2011 08:05:19
URL: https://github.com/mono/mono/commit/e07a7150a780b10a2fd1c46d2e4caca23dc340eb
Reimplemented XamlXmlReader to make it iterator based, much less stateful.
Also fixed bug #638290 (required lots of state management complication).
Changed paths:
M mcs/class/System.Xaml/System.Xaml/XamlXmlReader.cs
M mcs/class/System.Xaml/Test/System.Xaml/TestedTypes.cs
M mcs/class/System.Xaml/Test/System.Xaml/XamlReaderTestBase.cs
M mcs/class/System.Xaml/Test/System.Xaml/XamlXmlReaderTest.cs
Added paths:
A mcs/class/System.Xaml/Test/XmlFiles/ContentPropertyContainer.xml
Modified: mcs/class/System.Xaml/System.Xaml/XamlXmlReader.cs
===================================================================
--- a/mcs/class/System.Xaml/System.Xaml/XamlXmlReader.cs
+++ b/mcs/class/System.Xaml/System.Xaml/XamlXmlReader.cs
@@ -1,5 +1,5 @@
//
-// Copyright (C) 2010 Novell Inc. http://novell.com
+// Copyright (C) 2011 Novell Inc. http://novell.com
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
@@ -114,273 +114,176 @@ namespace System.Xaml
public XamlXmlReader (XmlReader xmlReader, XamlSchemaContext schemaContext, \
XamlXmlReaderSettings settings) {
- if (xmlReader == null)
- throw new ArgumentNullException ("xmlReader");
- if (schemaContext == null)
- throw new ArgumentNullException ("schemaContext");
-
- sctx = schemaContext;
- this.settings = settings ?? new XamlXmlReaderSettings ();
-
- // filter out some nodes.
- var xrs = new XmlReaderSettings () {
- CloseInput = this.settings.CloseInput,
- IgnoreComments = true,
- IgnoreProcessingInstructions = true,
- IgnoreWhitespace = true };
-
- r = XmlReader.Create (xmlReader, xrs);
- line_info = r as IXmlLineInfo;
- xaml_namespace_resolver = new NamespaceResolver (r as IXmlNamespaceResolver);
+ parser = new XamlXmlParser (xmlReader, schemaContext, settings);
}
#endregion
- XmlReader r;
- IXmlLineInfo line_info;
- XamlSchemaContext sctx;
- XamlXmlReaderSettings settings;
- bool is_eof;
- XamlNodeType node_type;
-
- object current;
- bool inside_object_not_member, is_xdata, is_empty_object, is_empty_member;
- Stack<XamlType> types = new Stack<XamlType> ();
- Stack<bool> get_flags = new Stack<bool> ();
- Stack<XamlMember> members = new Stack<XamlMember> ();
- XamlMember current_member;
-
- IEnumerator<Pair> stored_member_enumerator;
- IXamlNamespaceResolver xaml_namespace_resolver;
+ XamlXmlParser parser;
+ IEnumerator<XamlXmlNodeInfo> iter;
public bool HasLineInfo {
- get { return line_info != null && line_info.HasLineInfo (); }
+ get { return iter != null ? iter.Current.HasLineInfo : false; }
}
public override bool IsEof {
- get { return is_eof; }
+ get { return iter != null ? iter.Current.NodeType == XamlNodeType.None : false; }
}
public int LineNumber {
- get { return line_info != null ? line_info.LineNumber : 0; }
+ get { return iter != null ? iter.Current.LineNumber : 0; }
}
public int LinePosition {
- get { return line_info != null ? line_info.LinePosition : 0; }
+ get { return iter != null ? iter.Current.LinePosition : 0; }
}
public override XamlMember Member {
- get { return current as XamlMember; }
+ get { return iter != null && iter.Current.NodeType == XamlNodeType.StartMember ? \
(XamlMember) iter.Current.NodeValue : null; } }
+
public override NamespaceDeclaration Namespace {
- get { return current as NamespaceDeclaration; }
+ get { return iter != null && iter.Current.NodeType == \
XamlNodeType.NamespaceDeclaration ? (NamespaceDeclaration) iter.Current.NodeValue : \
null; } }
public override XamlNodeType NodeType {
- get { return node_type; }
+ get { return iter != null ? iter.Current.NodeType : XamlNodeType.None; }
}
public override XamlSchemaContext SchemaContext {
- get { return sctx; }
+ get { return parser.SchemaContext; }
}
public override XamlType Type {
- get { return current as XamlType; }
+ get { return iter != null && iter.Current.NodeType == XamlNodeType.StartObject ? \
(XamlType) iter.Current.NodeValue : null; } }
public override object Value {
- get { return NodeType == XamlNodeType.Value ? current : null; }
+ get { return iter != null && iter.Current.NodeType == XamlNodeType.Value ? \
iter.Current.NodeValue : null; } }
public override bool Read ()
{
if (IsDisposed)
throw new ObjectDisposedException ("reader");
- if (is_eof)
- return false;
-
- if (node_type == XamlNodeType.EndMember && members.Count > 0)
- current_member = members.Peek (); // set parent member _after_ EndMember.
-
- // check this before is_empty_* so that they aren't ignored.
- if (MoveToNextStoredMember ())
- return true;
-
- if (is_xdata) {
- is_xdata = false;
- ReadEndType (true);
- return true;
- }
- if (is_empty_object) {
- is_empty_object = false;
- ReadEndType (false);
- return true;
- }
- if (is_empty_member) {
- is_empty_member = false;
- ReadEndMember ();
- return true;
- }
-
- bool attrIterated = false;
- if (r.NodeType == XmlNodeType.Attribute) {
- attrIterated = true;
- if (r.MoveToNextAttribute ())
- if (CheckNextNamespace ())
- return true;
- }
-
- if (!r.EOF)
- r.MoveToContent ();
- if (r.EOF) {
- is_eof = true;
- return false;
+ if (iter == null)
+ iter = parser.Parse ().GetEnumerator ();
+ iter.MoveNext ();
+ return iter.Current.NodeType != XamlNodeType.None;
+ }
+ }
+
+ struct XamlXmlNodeInfo
+ {
+ public XamlXmlNodeInfo (XamlNodeType nodeType, object nodeValue, IXmlLineInfo \
lineInfo) + {
+ NodeType = nodeType;
+ NodeValue = nodeValue;
+ if (lineInfo != null && lineInfo.HasLineInfo ()) {
+ HasLineInfo = true;
+ LineNumber = lineInfo.LineNumber;
+ LinePosition = lineInfo.LinePosition;
+ } else {
+ HasLineInfo = false;
+ LineNumber = 0;
+ LinePosition = 0;
}
+ }
+
+ public bool HasLineInfo;
+ public int LineNumber;
+ public int LinePosition;
+ public XamlNodeType NodeType;
+ public object NodeValue;
+ }
+
+ class XamlXmlParser
+ {
+ public XamlXmlParser (XmlReader xmlReader, XamlSchemaContext schemaContext, \
XamlXmlReaderSettings settings) + {
+ if (xmlReader == null)
+ throw new ArgumentNullException ("xmlReader");
+ if (schemaContext == null)
+ throw new ArgumentNullException ("schemaContext");
- switch (r.NodeType) {
- case XmlNodeType.Element:
-
- // could be: StartObject, StartMember, optionally preceding \
NamespaceDeclarations
- if (!attrIterated && r.MoveToFirstAttribute ())
- if (CheckNextNamespace ())
- return true;
- r.MoveToElement ();
-
- if (inside_object_not_member) {
- if (r.LocalName.StartsWith (types.Peek ().Name + ".", \
StringComparison.Ordinal))
- ReadStartMember ();
- else if (!ReadExtraStartMember ())
- ReadStartMember ();
- } else {
- if (node_type == XamlNodeType.StartMember && current_member != null && \
!current_member.IsWritePublic) {
- if (current_member.Type.IsXData)
- ReadStartXData ();
- else if (current_member.Type.IsCollection)
- SetGetObject ();
- else
- throw new XamlParseException (String.Format ("Read-only member '{0}' showed \
up in the source XML, and the xml contains element content that cannot be read.", \
current_member.Name)) { LineNumber = this.LineNumber, LinePosition = \
this.LinePosition };
- }
- else
- ReadStartTypeOrContentGetObject ();
- }
- return true;
-
- case XmlNodeType.EndElement:
+ sctx = schemaContext;
+ this.settings = settings ?? new XamlXmlReaderSettings ();
- // could be: EndObject, EndMember
- if (inside_object_not_member) {
- var xm = members.Count > 0 ? members.Peek () : null;
- if (xm != null && !xm.IsWritePublic && xm.Type.IsCollection)
- ReadEndType (true);
- else
- ReadEndType (false);
- }
- else {
- if (r.LocalName.StartsWith (types.Peek ().Name + ".", \
StringComparison.Ordinal))
- ReadEndMember ();
- else if (!ReadExtraEndMember ())
- ReadEndMember ();
- }
- return true;
+ // filter out some nodes.
+ var xrs = new XmlReaderSettings () {
+ CloseInput = this.settings.CloseInput,
+ IgnoreComments = true,
+ IgnoreProcessingInstructions = true,
+ IgnoreWhitespace = true };
- default:
+ r = XmlReader.Create (xmlReader, xrs);
+ line_info = r as IXmlLineInfo;
+ xaml_namespace_resolver = new NamespaceResolver (r as IXmlNamespaceResolver);
+ }
+
+ XmlReader r;
+ IXmlLineInfo line_info;
+ XamlSchemaContext sctx;
+ XamlXmlReaderSettings settings;
+ IXamlNamespaceResolver xaml_namespace_resolver;
- // could be: normal property Value (Initialization and ContentProperty are \
handled at ReadStartTypeOrContentGetObject()).
- ReadValue ();
- return true;
- }
+ internal XmlReader Reader {
+ get { return r; }
}
- // returns an optional member without xml node.
- XamlMember GetExtraMember (XamlType xt)
- {
- if (xt.ContentProperty != null) // e.g. Array.Items
- return xt.ContentProperty;
- if (xt.IsCollection || xt.IsDictionary)
- return XamlLanguage.Items;
- return null;
+ public XamlSchemaContext SchemaContext {
+ get { return sctx; }
}
- bool ReadExtraStartMember ()
+ XamlXmlNodeInfo Node (XamlNodeType nodeType, object nodeValue)
{
- var xm = GetExtraMember (types.Peek ());
- if (xm != null && current != xm) {
- inside_object_not_member = false;
- current = current_member = xm;
- members.Push (xm);
- node_type = XamlNodeType.StartMember;
- return true;
- }
- return false;
- }
-
- bool ReadExtraEndMember ()
- {
- var xm = GetExtraMember (types.Peek ());
- // FIXME: unlike ReadExtraEndMember, I removed current
- // member check, as current_member might be kept since
- // ReadExtraStartMember(). And for PositionalParameters
- // I cannot "clean up" this field. I guess it is still
- // safe, but might cause some corner-case bugs.
- // I may have to simplify the entire implementation
- // like I did for (now push-based) XamlObjectReader.
- if (xm != null) {
- inside_object_not_member = true;
- current_member = members.Pop ();
- node_type = XamlNodeType.EndMember;
- return true;
- }
- return false;
+ return new XamlXmlNodeInfo (nodeType, nodeValue, line_info);
}
- bool CheckNextNamespace ()
+ public IEnumerable<XamlXmlNodeInfo> Parse ()
{
- do {
- if (r.NamespaceURI == XamlLanguage.Xmlns2000Namespace) {
- current = new NamespaceDeclaration (r.Value, r.Prefix == "xmlns" ? r.LocalName \
: String.Empty);
- node_type = XamlNodeType.NamespaceDeclaration;
- return true;
- }
- } while (r.MoveToNextAttribute ());
- return false;
+ r.MoveToContent ();
+ foreach (var xi in ReadObjectElement (null, null))
+ yield return xi;
+ yield return Node (XamlNodeType.None, null);
}
-
- void ReadStartTypeOrContentGetObject ()
+
+ // Note that it could return invalid (None) node to tell the caller that it is not \
really an object element. + IEnumerable<XamlXmlNodeInfo> ReadObjectElement (XamlType \
parentType, XamlMember currentMember) {
- string name = r.LocalName;
- string ns = r.NamespaceURI;
- string typeArgNames = null;
-
- var members = new List<Pair> ();
- var atts = ProcessAttributes (members);
+ if (r.NodeType != XmlNodeType.Element) {
+ //throw new XamlParseException (String.Format ("Element is expected, but got \
{0}", r.NodeType)); + yield return Node (XamlNodeType.Value, r.Value);
+ yield break;
+ }
- // check TypeArguments to resolve Type, and remove them from the list. They don't \
appear as a node.
- var l = new List<Pair> ();
- foreach (var p in members) {
- if (p.Key == XamlLanguage.TypeArguments) {
- typeArgNames = p.Value;
- l.Add (p);
- break;
- }
+ if (r.MoveToFirstAttribute ()) {
+ do {
+ if (r.NamespaceURI == XamlLanguage.Xmlns2000Namespace)
+ yield return Node (XamlNodeType.NamespaceDeclaration, new NamespaceDeclaration \
(r.Value, r.Prefix == "xmlns" ? r.LocalName : String.Empty)); + } while \
(r.MoveToNextAttribute ()); + r.MoveToElement ();
}
- foreach (var p in l)
- members.Remove (p);
- XamlType xt;
- IList<XamlTypeName> typeArgs = typeArgNames == null ? null : \
XamlTypeName.ParseList (typeArgNames, xaml_namespace_resolver);
- var xtn = new XamlTypeName (ns, name, typeArgs);
- xt = sctx.GetXamlType (xtn);
+ var sti = GetStartTagInfo ();
+
+ var xt = sctx.GetXamlType (sti.TypeName);
if (xt == null) {
+ // Current element could be for another member in the parent type (if exists)
+ if (parentType != null && (r.LocalName.IndexOf ('.') > 0 || parentType.GetMember \
(r.LocalName) != null)) { + // stop the iteration and signal the caller to not \
read current element as an object. (It resolves conflicts between "start object for \
current collection's item" and "start member for the next member in the parent \
object". + yield return Node (XamlNodeType.None, null);
+ yield break;
+ }
+
// creates name-only XamlType. Also, it does not seem that it does not store \
this XamlType to XamlSchemaContext (Try GetXamlType(xtn) after reading such xaml \
node, it will return null).
- xt = new XamlType (ns, name, typeArgs == null ? null : \
typeArgs.Select<XamlTypeName,XamlType> (xxtn => sctx.GetXamlType (xxtn)).ToArray (), \
sctx); + xt = new XamlType (sti.Namespace, sti.Name, sti.TypeName.TypeArguments == \
null ? null : sti.TypeName.TypeArguments.Select<XamlTypeName,XamlType> (xxtn => \
sctx.GetXamlType (xxtn)).ToArray (), sctx); }
-
- if (current_member != null && !xt.CanAssignTo (current_member.Type)) {
- var pxt = types.Count > 0 ? types.Peek () : null;
- if (pxt != null && pxt.ContentProperty == current_member) {
- SetGetObject ();
- return;
- }
+
+ bool isGetObject = false;
+ if (currentMember != null && !xt.CanAssignTo (currentMember.Type)) {
+ if (currentMember.DeclaringType != null && \
currentMember.DeclaringType.ContentProperty == currentMember) + isGetObject = \
true;
// It could still be GetObject if current_member
// is not a directive and current type is not
@@ -388,163 +291,125 @@ namespace System.Xaml
// (I'm not very sure about the condition;
// it could be more complex.)
// seealso: bug #682131
- if (!get_flags.Peek () &&
- !(current_member is XamlDirective) &&
- !xt.IsMarkupExtension) {
- SetGetObject ();
- return;
- }
+ else if (!(currentMember is XamlDirective) &&
+ !xt.IsMarkupExtension)
+ isGetObject = true;
}
- types.Push (xt);
- get_flags.Push (false);
- current = xt;
-
- if (!r.IsEmptyElement) {
- r.Read ();
- do {
- r.MoveToContent ();
- switch (r.NodeType) {
- case XmlNodeType.Element:
- // FIXME: parse type arguments etc.
- case XmlNodeType.EndElement:
- break;
- default:
- // this value is for Initialization, or Content property value
- if (xt.ContentProperty != null)
- members.Add (new Pair (xt.ContentProperty, r.Value));
+ if (isGetObject) {
+ yield return Node (XamlNodeType.GetObject, currentMember.Type);
+ foreach (var ni in ReadMembers (parentType, currentMember.Type))
+ yield return ni;
+ yield return Node (XamlNodeType.EndObject, currentMember.Type);
+ yield break;
+ }
+ // else
+
+ yield return Node (XamlNodeType.StartObject, xt);
+
+ // process attribute members (including MarkupExtensions)
+ ProcessAttributesToMember (sctx, sti, xt);
+
+ foreach (var pair in sti.Members) {
+ yield return Node (XamlNodeType.StartMember, pair.Key);
+
+ // Try markup extension
+ // FIXME: is this rule correct?
+ var v = pair.Value;
+ if (!String.IsNullOrEmpty (v) && v [0] == '{') {
+ var pai = ParsedMarkupExtensionInfo.Parse (v, xaml_namespace_resolver, sctx);
+ yield return Node (XamlNodeType.StartObject, pai.Type);
+ foreach (var xepair in pai.Arguments) {
+ yield return Node (XamlNodeType.StartMember, xepair.Key);
+ if (xepair.Value is List<string>)
+ foreach (var s in (List<string>) xepair.Value)
+ yield return Node (XamlNodeType.Value, s);
else
- members.Add (new Pair (XamlLanguage.Initialization, r.Value));
- r.Read ();
- continue;
+ yield return Node (XamlNodeType.Value, xepair.Value);
+ yield return Node (XamlNodeType.EndMember, xepair.Key);
}
- break;
- } while (true);
- }
- else
- is_empty_object = true;
-
- foreach (var p in atts) {
- int idx = p.Key.IndexOf (':');
- string prefix = idx > 0 ? p.Key.Substring (0, idx) : String.Empty;
- string aname = idx > 0 ? p.Key.Substring (idx + 1) : p.Key;
- idx = aname.IndexOf ('.');
- if (idx > 0) {
- string apns = prefix.Length > 0 ? r.LookupNamespace (prefix) : r.NamespaceURI;
- var apname = aname.Substring (0, idx);
- var axtn = new XamlTypeName (apns, apname, null);
- var at = sctx.GetXamlType (axtn);
- var am = at.GetAttachableMember (aname.Substring (idx + 1));
- if (am != null)
- members.Add (new Pair (am, p.Value));
- // ignore unknown attribute
+ yield return Node (XamlNodeType.EndObject, pai.Type);
}
- var xm = xt.GetMember (aname);
- if (xm != null)
- members.Add (new Pair (xm, p.Value));
- // ignore unknown attribute
+ else
+ yield return Node (XamlNodeType.Value, pair.Value);
+
+ yield return Node (XamlNodeType.EndMember, pair.Key);
}
- node_type = XamlNodeType.StartObject;
- inside_object_not_member = true;
+ // process content members
+ if (!r.IsEmptyElement) {
+ r.Read ();
+ foreach (var ni in ReadMembers (parentType, xt))
+ yield return ni;
+ r.ReadEndElement ();
+ }
+ else
+ r.Read (); // consume empty element.
- // The next Read() results are likely directives.
- stored_member_enumerator = members.GetEnumerator ();
+ yield return Node (XamlNodeType.EndObject, xt);
}
- void ReadStartXData ()
+ IEnumerable<XamlXmlNodeInfo> ReadMembers (XamlType parentType, XamlType xt)
{
- var xt = XamlLanguage.XData;
- string xdata = r.ReadInnerXml ();
- stored_member_enumerator = new List<Pair> (new Pair [] { new Pair (xt.GetMember \
("Text"), xdata) }).GetEnumerator ();
-
- types.Push (xt);
- get_flags.Push (false);
- current = xt;
- node_type = XamlNodeType.StartObject;
- inside_object_not_member = true;
- is_xdata = true;
- }
-
- void ReadStartMember ()
- {
- var xt = types.Peek ();
- var name = r.LocalName;
- int idx = name.IndexOf ('.');
- if (idx >= 0) {
- string tname = name.Substring (0, idx);
- var xtn = new XamlTypeName (r.NamespaceURI, tname, null);
- xt = SchemaContext.GetXamlType (xtn) ?? new XamlType (xtn.Namespace, xtn.Name, \
null, SchemaContext);
- name = name.Substring (idx + 1);
+ for (r.MoveToContent (); r.NodeType != XmlNodeType.EndElement; r.MoveToContent \
()) { + switch (r.NodeType) {
+ case XmlNodeType.Element:
+ // FIXME: parse type arguments etc.
+ foreach (var x in ReadMemberElement (parentType, xt)) {
+ if (x.NodeType == XamlNodeType.None)
+ yield break;
+ yield return x;
+ }
+ continue;
+ default:
+ foreach (var x in ReadMemberText (xt))
+ yield return x;
+ continue;
+ }
}
-
- var xm = (XamlMember) FindStandardDirective (name, \
AllowedMemberLocations.MemberElement) ?? xt.GetAttachableMember (name) ?? \
xt.GetMember (name);
- if (xm == null)
- // create unknown member.
- xm = new XamlMember (name, xt, false); // FIXME: not sure if isAttachable is \
always false.
- current = current_member = xm;
- members.Push (xm);
-
- node_type = XamlNodeType.StartMember;
- inside_object_not_member = false;
-
- r.Read ();
}
-
- void ReadEndType (bool skipRead)
- {
- var wasGet = get_flags.Pop ();
- if (!skipRead && !wasGet)
- r.Read ();
- types.Pop ();
- current = null;
- node_type = XamlNodeType.EndObject;
- inside_object_not_member = false;
- }
-
- void ReadEndMember ()
+ StartTagInfo GetStartTagInfo ()
{
- r.Read ();
-
- current_member = members.Pop ();
- current = null;
- node_type = XamlNodeType.EndMember;
- inside_object_not_member = true;
- }
+ string name = r.LocalName;
+ string ns = r.NamespaceURI;
+ string typeArgNames = null;
- void ReadValue ()
- {
- current = r.Value;
+ var members = new List<Pair> ();
+ var atts = ProcessAttributes (r, members);
- r.Read ();
+ // check TypeArguments to resolve Type, and remove them from the list. They don't \
appear as a node. + var l = new List<Pair> ();
+ foreach (var p in members) {
+ if (p.Key == XamlLanguage.TypeArguments) {
+ typeArgNames = p.Value;
+ l.Add (p);
+ break;
+ }
+ }
+ foreach (var p in l)
+ members.Remove (p);
- node_type = XamlNodeType.Value;
- }
-
- void SetGetObject ()
- {
- types.Push (current_member.Type);
- get_flags.Push (true);
- current = current_member = null;
- node_type = XamlNodeType.GetObject;
- inside_object_not_member = true;
+ XamlType xt;
+ IList<XamlTypeName> typeArgs = typeArgNames == null ? null : \
XamlTypeName.ParseList (typeArgNames, xaml_namespace_resolver); + var xtn = new \
XamlTypeName (ns, name, typeArgs); + return new StartTagInfo () { Name = name, \
Namespace = ns, TypeName = xtn, Members = members, Attributes = atts}; }
- XamlDirective FindStandardDirective (string name, AllowedMemberLocations loc)
- {
- return XamlLanguage.AllDirectives.FirstOrDefault (dd => (dd.AllowedLocation & \
loc) != 0 && dd.Name == name);
- }
+ bool xmlbase_done;
// returns remaining attributes to be processed
- Dictionary<string,string> ProcessAttributes (List<Pair> members)
+ Dictionary<string,string> ProcessAttributes (XmlReader r, List<Pair> members)
{
var l = members;
- // base
- string xmlbase = r.GetAttribute ("base", XamlLanguage.Xml1998Namespace) ?? \
r.BaseURI;
- if (types.Count == 0 && xmlbase != null) // top
- l.Add (new Pair (XamlLanguage.Base, xmlbase));
+ // base (top element)
+ if (!xmlbase_done) {
+ xmlbase_done = true;
+ string xmlbase = r.GetAttribute ("base", XamlLanguage.Xml1998Namespace) ?? \
r.BaseURI; + if (xmlbase != null)
+ l.Add (new Pair (XamlLanguage.Base, xmlbase));
+ }
var atts = new Dictionary<string,string> ();
@@ -586,105 +451,188 @@ namespace System.Xaml
}
return atts;
}
+
+
+ void ProcessAttributesToMember (XamlSchemaContext sctx, StartTagInfo sti, XamlType \
xt) + {
+ foreach (var p in sti.Attributes) {
+ int idx = p.Key.IndexOf (':');
+ string prefix = idx > 0 ? p.Key.Substring (0, idx) : String.Empty;
+ string aname = idx > 0 ? p.Key.Substring (idx + 1) : p.Key;
+ idx = aname.IndexOf ('.');
+ if (idx > 0) {
+ string apns = prefix.Length > 0 ? r.LookupNamespace (prefix) : r.NamespaceURI;
+ var apname = aname.Substring (0, idx);
+ var axtn = new XamlTypeName (apns, apname, null);
+ var at = sctx.GetXamlType (axtn);
+ var am = at.GetAttachableMember (aname.Substring (idx + 1));
+ if (am != null)
+ sti.Members.Add (new Pair (am, p.Value));
+ // ignore unknown attribute
+ }
+ var xm = xt.GetMember (aname);
+ if (xm != null)
+ sti.Members.Add (new Pair (xm, p.Value));
+ // ignore unknown attribute
+ }
+ }
+
+ // returns an optional member without xml node.
+ XamlMember GetExtraMember (XamlType xt)
+ {
+ if (xt.ContentProperty != null) // e.g. Array.Items
+ return xt.ContentProperty;
+ if (xt.IsCollection || xt.IsDictionary)
+ return XamlLanguage.Items;
+ return null;
+ }
+
+ static XamlDirective FindStandardDirective (string name, AllowedMemberLocations \
loc) + {
+ return XamlLanguage.AllDirectives.FirstOrDefault (dd => (dd.AllowedLocation & \
loc) != 0 && dd.Name == name); + }
+
+ IEnumerable<XamlXmlNodeInfo> ReadMemberText (XamlType xt)
+ {
+ // this value is for Initialization, or Content property value
+ XamlMember xm;
+ if (xt.ContentProperty != null)
+ xm = xt.ContentProperty;
+ else
+ xm = XamlLanguage.Initialization;
+ yield return Node (XamlNodeType.StartMember, xm);
+ yield return Node (XamlNodeType.Value, r.Value);
+ r.Read ();
+ yield return Node (XamlNodeType.EndMember, xm);
+ }
- IEnumerator<KeyValuePair<XamlMember,object>> markup_extension_attr_members;
- IEnumerator<string> markup_extension_attr_values;
-
- bool MoveToNextMarkupExtensionAttributeMember ()
- {
- if (markup_extension_attr_members != null) {
- switch (node_type) {
- case XamlNodeType.EndMember:
- members.Pop ();
- goto case XamlNodeType.StartObject;
- case XamlNodeType.StartObject:
- // -> next member or end object
- if (!markup_extension_attr_members.MoveNext ()) {
- node_type = XamlNodeType.EndObject;
- } else {
- current = current_member = markup_extension_attr_members.Current.Key;
- members.Push (current_member);
- node_type = XamlNodeType.StartMember;
- }
- return true;
- case XamlNodeType.EndObject:
- types.Pop ();
- get_flags.Pop ();
- markup_extension_attr_members = null;
- return false;
- case XamlNodeType.StartMember:
- node_type = XamlNodeType.Value;
- current = markup_extension_attr_members.Current.Value;
- if (current_member == XamlLanguage.PositionalParameters) {
- markup_extension_attr_values = ((List<string>) current).GetEnumerator ();
- goto case XamlNodeType.Value;
- }
- return true;
- case XamlNodeType.Value:
- if (markup_extension_attr_values != null) {
- if (markup_extension_attr_values.MoveNext ())
- current = markup_extension_attr_values.Current;
- else {
- node_type = XamlNodeType.EndMember;
- markup_extension_attr_values = null;
- }
+ // member element, implicit member, children via content property, or value
+ IEnumerable<XamlXmlNodeInfo> ReadMemberElement (XamlType parentType, XamlType xt)
+ {
+ XamlMember xm = null;
+ var name = r.LocalName;
+ int idx = name.IndexOf ('.');
+ // FIXME: it skips strict type name check, as it could result in MarkupExtension \
mismatch (could be still checked, though) + if (idx >= 0/* && name.Substring (0, \
idx) == xt.Name*/) { + name = name.Substring (idx + 1);
+ xm = xt.GetMember (name);
+ } else {
+ xm = (XamlMember) FindStandardDirective (name, \
AllowedMemberLocations.MemberElement) ?? + // not a standard directive? then try \
attachable + xt.GetAttachableMember (name) ??
+ // still not? then try ordinal member
+ xt.GetMember (name);
+ if (xm == null) {
+ // still not? could it be omitted as content property or items ?
+ if ((xm = GetExtraMember (xt)) != null) {
+ // Note that this does not involve r.Read()
+ foreach (var ni in ReadMember (xt, xm))
+ yield return ni;
+ yield break;
}
- else
- node_type = XamlNodeType.EndMember;
- return true;
}
}
- return false;
+ if (xm == null) {
+ // Current element could be for another member in the parent type (if exists)
+ if (parentType != null && parentType.GetMember (name) != null) {
+ // stop the iteration and signal the caller to not read current element as an \
object. (It resolves conflicts between "start object for current collection's item" \
and "start member for the next member in the parent object". + yield return Node \
(XamlNodeType.None, null); + yield break;
+ }
+
+ // ok, then create unknown member.
+ xm = new XamlMember (name, xt, false); // FIXME: not sure if isAttachable is \
always false. + }
+
+ if (!r.IsEmptyElement) {
+ r.Read ();
+ foreach (var ni in ReadMember (xt, xm))
+ yield return ni;
+ r.MoveToContent ();
+ r.ReadEndElement ();
+ }
+ else
+ r.Read ();
}
- bool MoveToNextStoredMember ()
+ IEnumerable<XamlXmlNodeInfo> ReadMember (XamlType parentType, XamlMember xm)
{
- if (MoveToNextMarkupExtensionAttributeMember ())
- return true;
+ yield return Node (XamlNodeType.StartMember, xm);
- if (stored_member_enumerator != null) {
- // FIXME: value might have to be deserialized.
- switch (node_type) {
- case XamlNodeType.StartObject:
- case XamlNodeType.EndMember:
- // -> StartMember
- if (stored_member_enumerator.MoveNext ()) {
- current = current_member = stored_member_enumerator.Current.Key;
- node_type = XamlNodeType.StartMember;
- return true;
- }
- break;
- case XamlNodeType.StartMember:
- // -> Value or StartObject (of MarkupExtension)
- var v = stored_member_enumerator.Current.Value;
- current = v;
- // Try markup extension
- // FIXME: is this rule correct?
- if (!String.IsNullOrEmpty (v) && v [0] == '{') {
- var pai = ParsedMarkupExtensionInfo.Parse (v, xaml_namespace_resolver, sctx);
- types.Push (pai.Type);
- get_flags.Push (false);
- current = pai.Type;
- node_type = XamlNodeType.StartObject;
- markup_extension_attr_members = pai.Arguments.GetEnumerator ();
+ if (xm.IsEvent) {
+ yield return Node (XamlNodeType.Value, r.Value);
+ r.Read ();
+ } else if (!xm.IsWritePublic) {
+ if (xm.Type.IsXData)
+ foreach (var ni in ReadXData ())
+ yield return ni;
+ else if (xm.Type.IsCollection) {
+ yield return Node (XamlNodeType.GetObject, xm.Type);
+ yield return Node (XamlNodeType.StartMember, XamlLanguage.Items);
+ foreach (var ni in ReadCollectionItems (parentType, XamlLanguage.Items))
+ yield return ni;
+ yield return Node (XamlNodeType.EndMember, XamlLanguage.Items);
+ yield return Node (XamlNodeType.EndObject, xm.Type);
+ }
+ else
+ throw new XamlParseException (String.Format ("Read-only member '{0}' showed up \
in the source XML, and the xml contains element content that cannot be read.", \
xm.Name)) { LineNumber = this.LineNumber, LinePosition = this.LinePosition }; + } \
else { + if (xm.Type.IsCollection || xm.Type.IsDictionary) {
+ foreach (var ni in ReadCollectionItems (parentType, xm))
+ yield return ni;
+ }
+ else
+ foreach (var ni in ReadObjectElement (parentType, xm)) {
+ if (ni.NodeType == XamlNodeType.None)
+ throw new Exception ("should not happen");
+ yield return ni;
}
- else
- node_type = XamlNodeType.Value;
- return true;
- case XamlNodeType.EndObject: // of MarkupExtension
- case XamlNodeType.Value:
- // -> EndMember
- current = null;
- node_type = XamlNodeType.EndMember;
- return true;
+ }
+
+ yield return Node (XamlNodeType.EndMember, xm);
+ }
+
+ IEnumerable<XamlXmlNodeInfo> ReadCollectionItems (XamlType parentType, XamlMember \
xm) + {
+ for (r.MoveToContent (); r.NodeType != XmlNodeType.EndElement; r.MoveToContent \
()) { +var obj = new object ();
+ foreach (var ni in ReadObjectElement (parentType, xm)) {
+ if (ni.NodeType == XamlNodeType.None)
+ yield break;
+ yield return ni;
}
}
+ }
+
+ IEnumerable<XamlXmlNodeInfo> ReadXData ()
+ {
+ var xt = XamlLanguage.XData;
+ var xm = xt.GetMember ("Text");
+ yield return Node (XamlNodeType.StartObject, xt);
+ yield return Node (XamlNodeType.StartMember, xm);
+ yield return Node (XamlNodeType.Value, r.ReadInnerXml ());
+ yield return Node (XamlNodeType.EndMember, xm);
+ yield return Node (XamlNodeType.EndObject, xt);
+ }
- stored_member_enumerator = null;
- return false;
+ public int LineNumber {
+ get { return line_info != null && line_info.HasLineInfo () ? line_info.LineNumber \
: 0; } + }
+
+ public int LinePosition {
+ get { return line_info != null && line_info.HasLineInfo () ? \
line_info.LinePosition : 0; } + }
+
+ internal class StartTagInfo
+ {
+ public string Name;
+ public string Namespace;
+ public XamlTypeName TypeName;
+ public List<Pair> Members;
+ public Dictionary<string,string> Attributes;
}
- class NamespaceResolver : IXamlNamespaceResolver
+ internal class NamespaceResolver : IXamlNamespaceResolver
{
IXmlNamespaceResolver source;
@@ -706,4 +654,3 @@ namespace System.Xaml
}
}
}
-
Modified: mcs/class/System.Xaml/Test/System.Xaml/TestedTypes.cs
===================================================================
--- a/mcs/class/System.Xaml/Test/System.Xaml/TestedTypes.cs
+++ b/mcs/class/System.Xaml/Test/System.Xaml/TestedTypes.cs
@@ -1044,6 +1044,28 @@ namespace SecondTest
{
public string TestProperty { get; set; }
}
+
+ #region bug #683290
+ [ContentProperty ("Items")]
+ public class SimpleType
+ {
+ public IList<SimpleType> Items { get; set; }
+
+ public IList<SimpleType> NonContentItems { get; set; }
+
+ public string TestProperty { get; set; }
+
+ public SimpleType ()
+ {
+ this.Items = new List<SimpleType> ();
+ this.NonContentItems=new List<SimpleType> ();
+ }
+ }
+
+ public class ContentPropertyContainer : Dictionary<object, object>
+ {
+ }
+ #endregion
}
Modified: mcs/class/System.Xaml/Test/System.Xaml/XamlReaderTestBase.cs
===================================================================
--- a/mcs/class/System.Xaml/Test/System.Xaml/XamlReaderTestBase.cs
+++ b/mcs/class/System.Xaml/Test/System.Xaml/XamlReaderTestBase.cs
@@ -3068,6 +3068,140 @@ namespace MonoTests.System.Xaml
Assert.IsFalse (r.Read (), "end");
}
+
+ protected void Read_ContentPropertyContainer (XamlReader r)
+ {
+ ReadNamespace (r, String.Empty, "http://www.domain.com/path", "ns#1");
+ ReadNamespace (r, "x", XamlLanguage.Xaml2006Namespace, "ns#2");
+
+ // 1:: t:ContentPropertyContainer
+ Assert.IsTrue (r.Read (), "so#1-1");
+ Assert.AreEqual (XamlNodeType.StartObject, r.NodeType, "so#1-2");
+ var xt = new XamlType (typeof (SecondTest.ContentPropertyContainer), \
r.SchemaContext); + Assert.AreEqual (xt, r.Type, "so#1-3");
+
+ if (r is XamlXmlReader)
+ ReadBase (r);
+
+ // 2:: m:Items
+ Assert.IsTrue (r.Read (), "sm1#1");
+ Assert.AreEqual (XamlNodeType.StartMember, r.NodeType, "sm1#2");
+ Assert.AreEqual (XamlLanguage.Items, r.Member, "sm1#3");
+
+ xt = r.SchemaContext.GetXamlType (typeof (SecondTest.SimpleType));
+ for (int i = 0; i < 2; i++) {
+ // 3:: t:SimpleType
+ Assert.IsTrue (r.Read (), "so#x-1" + "." + i);
+ Assert.AreEqual (XamlNodeType.StartObject, r.NodeType, "so#x-2" + "." + i);
+ Assert.AreEqual (xt, r.Type, "so#x-3" + "." + i);
+
+ // 4:: m:Key
+ Assert.IsTrue (r.Read (), "sm#y1" + "." + i);
+ Assert.AreEqual (XamlNodeType.StartMember, r.NodeType, "sm#y2" + "." + i);
+ Assert.AreEqual (XamlLanguage.Key, r.Member, "sm#y3" + "." + i);
+
+ // 4:: value
+ Assert.IsTrue (r.Read (), "v#y-1" + "." + i);
+ Assert.AreEqual (XamlNodeType.Value, r.NodeType, "v#y-2" + "." + i);
+ Assert.AreEqual (i == 0 ? "one" : "two", r.Value, "v#y-3" + "." + i);
+
+ // 4:: /m:Key
+ Assert.IsTrue (r.Read (), "em#y-1" + "." + i);
+ Assert.AreEqual (XamlNodeType.EndMember, r.NodeType, "em#y-2" + "." + i);
+
+if (i == 0) {
+
+ // 4-2:: m:Items(ContentProperty)
+ Assert.IsTrue (r.Read (), "sm#x1" + "." + i);
+ Assert.AreEqual (XamlNodeType.StartMember, r.NodeType, "sm#x2" + "." + i);
+ Assert.AreEqual (xt.GetMember ("Items"), r.Member, "sm#x3" + "." + i);
+
+ // 5:: GetObject
+ Assert.IsTrue (r.Read (), "go#z-1" + "." + i);
+ Assert.AreEqual (XamlNodeType.GetObject, r.NodeType, "go#z-2" + "." + i);
+
+ // 6:: m:Items(GetObject)
+ Assert.IsTrue (r.Read (), "smz#1" + "." + i);
+ Assert.AreEqual (XamlNodeType.StartMember, r.NodeType, "smz#2" + "." + i);
+ Assert.AreEqual (XamlLanguage.Items, r.Member, "smz#3" + "." + i);
+
+ for (int j = 0; j < 2; j++) {
+ // 7:: t:SimpleType
+ Assert.IsTrue (r.Read (), "soi#x-1" + "." + i + "-" + j);
+ Assert.AreEqual (XamlNodeType.StartObject, r.NodeType, "soi#x-2" + "." + i + \
"-" + j); + Assert.AreEqual (xt, r.Type, "soi#z-3" + "." + i + "-" + j);
+
+ // 7:: /t:SimpleType
+ Assert.IsTrue (r.Read (), "eoi#x-1" + "." + i + "-" + j);
+ Assert.AreEqual (XamlNodeType.EndObject, r.NodeType, "eoi#x-2" + "." + i + "-" \
+ j); + }
+
+ // 6:: /m:Items(GetObject)
+ Assert.IsTrue (r.Read (), "emz#x-1" + "." + i);
+ Assert.AreEqual (XamlNodeType.EndMember, r.NodeType, "emz#x-2" + "." + i);
+
+ // 5:: /GetObject
+ Assert.IsTrue (r.Read (), "eo#z-1" + "." + i);
+ Assert.AreEqual (XamlNodeType.EndObject, r.NodeType, "eo#z-2" + "." + i);
+
+ // 4:: /m:Items(ContentProperty)
+ Assert.IsTrue (r.Read (), "em#x1" + "." + i);
+ Assert.AreEqual (XamlNodeType.EndMember, r.NodeType, "em#x2" + "." + i);
+
+ // 4-2:: m:NonContentItems
+ Assert.IsTrue (r.Read (), "smv#1" + "." + i);
+ Assert.AreEqual (XamlNodeType.StartMember, r.NodeType, "smv#2" + "." + i);
+ Assert.AreEqual (xt.GetMember ("NonContentItems"), r.Member, "smv#3" + "." + i);
+
+ // 5-2:: GetObject
+ Assert.IsTrue (r.Read (), "go#z-1" + "." + i);
+ Assert.AreEqual (XamlNodeType.GetObject, r.NodeType, "go#v-2" + "." + i);
+
+ // 6-2:: m:Items
+ Assert.IsTrue (r.Read (), "smw#1" + "." + i);
+ Assert.AreEqual (XamlNodeType.StartMember, r.NodeType, "smw#2" + "." + i);
+ Assert.AreEqual (XamlLanguage.Items, r.Member, "smw#3" + "." + i);
+
+ for (int j = 0; j < 2; j++) {
+ // 7-2:: t:SimpleType
+ Assert.IsTrue (r.Read (), "soi2#x-1" + "." + i + "-" + j);
+ Assert.AreEqual (XamlNodeType.StartObject, r.NodeType, "soi2#x-2" + "." + i + \
"-" + j); + Assert.AreEqual (xt, r.Type, "soi2#z-3" + "." + i + "-" + j);
+
+ // 7-2:: /t:SimpleType
+ Assert.IsTrue (r.Read (), "eoi2#x-1" + "." + i + "-" + j);
+ Assert.AreEqual (XamlNodeType.EndObject, r.NodeType, "eoi2#x-2" + "." + i + "-" \
+ j); + }
+
+ // 6-2:: /m:Items
+ Assert.IsTrue (r.Read (), "emw#1" + "." + i);
+ Assert.AreEqual (XamlNodeType.EndMember, r.NodeType, "emw#2" + "." + i);
+
+ // 5-2:: /GetObject
+ Assert.IsTrue (r.Read (), "eo#v-1" + "." + i);
+ Assert.AreEqual (XamlNodeType.EndObject, r.NodeType, "eo#v-2" + "." + i);
+
+ // 4-2:: /m:NonContentItems
+ Assert.IsTrue (r.Read (), "emv#1" + "." + i);
+ Assert.AreEqual (XamlNodeType.EndMember, r.NodeType, "emv#2" + "." + i);
+
+}
+
+ // 3:: /t:SimpleType
+ Assert.IsTrue (r.Read (), "eo#x-1" + "." + i);
+ Assert.AreEqual (XamlNodeType.EndObject, r.NodeType, "eo#x-2" + "." + i);
+ }
+
+ // 2:: /m:Items
+ Assert.IsTrue (r.Read (), "em#1-1");
+ Assert.AreEqual (XamlNodeType.EndMember, r.NodeType, "em#1-2");
+
+ // 1:: /t:ContentPropertyContainer
+ Assert.IsTrue (r.Read (), "eo#1-1");
+ Assert.AreEqual (XamlNodeType.EndObject, r.NodeType, "eo#1-2");
+
+ Assert.IsFalse (r.Read (), "end");
+ }
protected void Read_AttachedProperty (XamlReader r)
{
Modified: mcs/class/System.Xaml/Test/System.Xaml/XamlXmlReaderTest.cs
===================================================================
--- a/mcs/class/System.Xaml/Test/System.Xaml/XamlXmlReaderTest.cs
+++ b/mcs/class/System.Xaml/Test/System.Xaml/XamlXmlReaderTest.cs
@@ -708,6 +708,13 @@ namespace MonoTests.System.Xaml
var r = GetReader ("DirectDictionaryContainer2.xml");
Read_DirectDictionaryContainer2 (r);
}
+
+ [Test]
+ public void Read_ContentPropertyContainer ()
+ {
+ var r = GetReader ("ContentPropertyContainer.xml");
+ Read_ContentPropertyContainer (r);
+ }
#region non-common tests
[Test]
Added: mcs/class/System.Xaml/Test/XmlFiles/ContentPropertyContainer.xml
===================================================================
Commit: 5da72e98ea1e4525192d504114227458ea1f5501
Author: Louis Salin <louis@lonestardevs.com>
Committer: Gonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Date: 03/31/2011 09:11:40
URL: https://github.com/mono/mono/commit/5da72e98ea1e4525192d504114227458ea1f5501
implement getter and setter for HostContext property
Changed paths:
M mcs/class/corlib/System.Runtime.Remoting.Messaging/CallContext.cs
Modified: mcs/class/corlib/System.Runtime.Remoting.Messaging/CallContext.cs
===================================================================
--- a/mcs/class/corlib/System.Runtime.Remoting.Messaging/CallContext.cs
+++ b/mcs/class/corlib/System.Runtime.Remoting.Messaging/CallContext.cs
@@ -47,14 +47,15 @@ namespace System.Runtime.Remoting.Messaging
{
[ThreadStatic] static Header [] Headers;
[ThreadStatic] static Hashtable datastore;
+ [ThreadStatic] static object hostContext;
private CallContext ()
{
}
public static object HostContext {
- get { throw new NotImplementedException (); }
- set { throw new NotImplementedException (); }
+ get { return hostContext; }
+ set { hostContext = value; }
}
// public methods
Commit: 16a5e1103766acb2adf91c1a0181edf0aef9b70e
Author: Louis Salin <louis@lonestardevs.com>
Committer: Gonzalo Paniagua Javier <gonzalo.mono@gmail.com>
Date: 03/31/2011 09:11:41
URL: https://github.com/mono/mono/commit/16a5e1103766acb2adf91c1a0181edf0aef9b70e
TraceData and TraceEvent methods must pass a new instance of TraceEventCache
Changed paths:
M mcs/class/System/System.Diagnostics/TraceSource.cs
Modified: mcs/class/System/System.Diagnostics/TraceSource.cs
===================================================================
--- a/mcs/class/System/System.Diagnostics/TraceSource.cs
+++ b/mcs/class/System/System.Diagnostics/TraceSource.cs
@@ -108,7 +108,7 @@ namespace System.Diagnostics
return;
lock (((ICollection) listeners).SyncRoot) {
foreach (TraceListener tl in listeners)
- tl.TraceData (null, Name, eventType, id, data);
+ tl.TraceData (new TraceEventCache(), Name, eventType, id, data);
}
}
@@ -120,7 +120,7 @@ namespace System.Diagnostics
return;
lock (((ICollection) listeners).SyncRoot) {
foreach (TraceListener tl in listeners)
- tl.TraceData (null, Name, eventType, id, data);
+ tl.TraceData (new TraceEventCache(), Name, eventType, id, data);
}
}
@@ -131,7 +131,7 @@ namespace System.Diagnostics
return;
lock (((ICollection) listeners).SyncRoot) {
foreach (TraceListener tl in listeners)
- tl.TraceEvent (null, Name, eventType, id);
+ tl.TraceEvent (new TraceEventCache(), Name, eventType, id);
}
}
@@ -143,7 +143,7 @@ namespace System.Diagnostics
return;
lock (((ICollection) listeners).SyncRoot) {
foreach (TraceListener tl in listeners)
- tl.TraceEvent (null, Name, eventType, id, message);
+ tl.TraceEvent (new TraceEventCache(), Name, eventType, id, message);
}
}
@@ -155,7 +155,7 @@ namespace System.Diagnostics
return;
lock (((ICollection) listeners).SyncRoot) {
foreach (TraceListener tl in listeners)
- tl.TraceEvent (null, Name, eventType, id, format, args);
+ tl.TraceEvent (new TraceEventCache(), Name, eventType, id, format, args);
}
}
@@ -179,7 +179,7 @@ namespace System.Diagnostics
return;
lock (((ICollection) listeners).SyncRoot) {
foreach (TraceListener tl in listeners)
- tl.TraceTransfer (null, Name, id, message, relatedActivityId);
+ tl.TraceTransfer (new TraceEventCache(), Name, id, message, relatedActivityId);
}
}
_______________________________________________
Mono-patches maillist - Mono-patches@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-patches
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic