/// <summary> /// Loads next <see cref="LToken"/> from the specified <see cref="LuaTableTextReader"/>. /// </summary> /// <param name="reader">The reader from which to load the next <see cref="LToken"/>.</param> /// <exception cref="ArgumentNullException"><paramref name="reader"/> is <c>null</c>.</exception> /// <exception cref="LuaTableReaderException">There are unexpected input in the <paramref name="reader"/>.</exception> /// <returns>The loaded Lua token.</returns> public static LToken Load(LuaTableTextReader reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (reader.CurrentToken == LuaTableReaderToken.None) { reader.Read(); } SkipComments(reader); switch (reader.CurrentToken) { case LuaTableReaderToken.None: case LuaTableReaderToken.TableStart: return(LTable.Load(reader)); case LuaTableReaderToken.Key: return(LField.Load(reader)); case LuaTableReaderToken.Value: return(LValue.Load(reader)); default: throw MakeUnexpectedTokenException(reader); } }
public bool RemoveByName(LValue name) { if (name == null || name.TokenType == LTokenType.Nil) { return(false); } if (fieldsDict.Count == 0) { // Positional fields only // Fast route if (name.TokenType == LTokenType.Integer) { var intName = (int)name; if (intName <= 0 || intName > Items.Count) { return(false); } Items.RemoveAt(intName - 1); return(true); } } // Named field if (fieldsDict.TryGetValue(name, out var field)) { var success = Items.Remove(field); Debug.Assert(success); return(true); } // Positional field if (name.TokenType == LTokenType.Integer) { var intName = (int)name; // Sanity check if (intName <= 0 || intName > Items.Count) { return(false); } int positionalIndex = 0; for (int i = 0; i < Items.Count; i++) { if (Items[i].Name == null) { positionalIndex++; if (intName == positionalIndex) { Items.RemoveAt(i); return(true); } } } } return(false); }
/// <summary> /// Initializes a new Lua table field with the specified name and value. /// </summary> /// <param name="name">Name of the field. Use <c>null</c> for positional field.</param> /// <param name="value">Value of the field. Can be <c>null</c>, which means <see cref="LValue.Nil"/>.</param> /// <exception cref="ArgumentException"><paramref name="name"/>.<see cref="LValue.TokenType"/> is <see cref="LTokenType.Nil"/>.</exception> public LField(LValue name, LToken value) { if (name != null && name.TokenType == LTokenType.Nil) { throw new ArgumentException("Cannot use nil as field name."); } Name = name; _Value = value ?? LValue.Nil; }
public LField FieldFromName(LValue name, bool allowsCreation) { Debug.Assert(name != null && name.TokenType != LTokenType.Nil); if (name.TokenType == LTokenType.Integer) { return(FieldFromName((int)name, name, allowsCreation)); } // Named field if (fieldsDict.TryGetValue(name, out var field)) { return(field); } return(null); }
/// <summary> /// Inserts a field or value at the end of the table expression. /// </summary> /// <param name="content">The field or value of the field.</param> public void Add(object content) { if (content is LField field) { Add(field); } else if (content is LToken value) { Add(value); } else { var tv = new LValue(content); Add(tv); } }
public new static LField Load(LuaTableTextReader reader) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } if (reader.CurrentToken == LuaTableReaderToken.None) { reader.Read(); } SkipComments(reader); LValue key = null; if (reader.CurrentToken == LuaTableReaderToken.Key) { key = new LValue(reader.CurrentValue); reader.Read(); SkipComments(reader); } LToken value = LToken.Load(reader); return(new LField(key, value)); }
public LField FieldFromName(int name, LValue nameRef, bool allowsCreation) { if (nameRef != null && fieldsDict.TryGetValue(name, out var field)) { return(field); } if (fieldsDict.Count == 0) { // Positional fields only // Fast route if (name <= 0 || name > Items.Count) { if (!allowsCreation) { return(null); } var f = new LField(name == Items.Count ? null : new LValue(name), null); Items.Add(f); return(f); } return(Items[name - 1]); } // Positional field // Sanity check if (name <= 0 || name > Items.Count - fieldsDict.Count) { var nr = nameRef ?? new LValue(name); if (fieldsDict.TryGetValue(nr, out var f)) { return(f); } if (!allowsCreation) { return(null); } f = new LField(name > 0 && name - 1 == Items.Count - fieldsDict.Count ? null : nr, null); Items.Add(f); return(f); } // Get the positional field int positionalIndex = 0; foreach (var i in Items) { if (i.Name != null) { continue; } positionalIndex++; if (name == positionalIndex) { return(i); } } #if NETSTANDARD2_0 Debug.Fail("Should not execute to here."); #else Debug.Assert(false); #endif return(null); }
/// <summary> /// Inserts a field at the end of the table expression. /// </summary> /// <param name="name">The name of the new field to be appended.</param> /// <param name="value">The value of the new field to be appended. <c>null</c> will be treated the same as <see cref="LValue.Nil"/>.</param> public void Add(LValue name, LToken value) { store.Add(new LField(name, value)); }
/// <summary> /// Tries to get the field instance with the specified field name. /// </summary> /// <param name="name">The field name.</param> /// <returns>The field instance, or <c>null</c> if no matching field exists.</returns> public LField Field(LValue name) { return(store.FieldFromName(name, false)); }
/// <summary> /// Gets/sets the field value associated with the specified field key. /// </summary> /// <param name="name">The key of the field to set or get.</param> /// <returns>The value of the specified field, or <c>null</c> if the field does not exist.</returns> public override LToken this[LValue name] { get { return(store.FieldFromName(name, false)?.Value); } set { store.FieldFromName(name, true).Value = value; } }
/// <summary> /// Removes a field from table by its field name. /// </summary> /// <param name="name">Field name.</param> /// <returns>Whether a matching item has been removed.</returns> /// <remarks>To remvoe a positional field, pass a numeric value to the <paramref name="name"/> parameter.</remarks> public bool Remove(LValue name) { return(store.RemoveByName(name)); }