/// <summary> /// Sets an entry value in the table if it does not exist. /// </summary> /// <param name="name">The entry name</param> /// <param name="value">The value to set</param> /// <returns>False if the type does not match existing value</returns> public static bool SetDefaultEntryString(string name, string value) { #if CORE return(CoreMethods.SetDefaultEntryString(name, value)); #else return(Storage.Instance.SetDefaultEntryValue(name, Value.MakeString(value))); #endif }
/// <summary> /// Sets an entry value /// </summary> /// <remarks>If the type of the new value differs from the type currently /// stored and the force parameter is false (default), returns error and /// does not update value. If force is true, the value type in the /// table is changed</remarks> /// <param name="name">The entry name</param> /// <param name="value">The value to set</param> /// <param name="force">True to force an update even if types are different</param> /// <returns>True on success, otherwise false</returns> public static bool SetEntryString(string name, string value, bool force = false) { #if CORE return(CoreMethods.SetEntryString(name, value, force)); #else if (force) { Storage.Instance.SetEntryTypeValue(name, Value.MakeString(value)); return(true); } return(Storage.Instance.SetEntryValue(name, Value.MakeString(value))); #endif }
public async Task <bool> LoadPersistentAsync(Stream stream, Action <int, string> warn) { int lineNum = 1; List <StoragePair> entries = new List <StoragePair>(); List <bool> boolArray = new List <bool>(); List <double> doubleArray = new List <double>(); List <string> stringArray = new List <string>(); using (StreamReader reader = new StreamReader(stream)) { string lineStr; while ((lineStr = await reader.ReadLineAsync().ConfigureAwait(false)) != null) { string line = lineStr.Trim(); if (line != string.Empty && line[0] != ';' && line[0] != '#') { break; } } if (lineStr != "[NetworkTables Storage 3.0]") { warn?.Invoke(lineNum, "header line mismatch, ignoring rest of file"); return(false); } while ((lineStr = await reader.ReadLineAsync().ConfigureAwait(false)) != null) { string line = lineStr.Trim(); ++lineNum; if (line == string.Empty || line[0] == ';' || line[0] == '#') { continue; } string[] split = line.Split(new[] { ' ' }, 2); var typeTok = split[0]; line = split[1]; NtType type = NtType.Unassigned; if (typeTok == "boolean") { type = NtType.Boolean; } else if (typeTok == "double") { type = NtType.Double; } else if (typeTok == "string") { type = NtType.String; } else if (typeTok == "raw") { type = NtType.Raw; } else if (typeTok == "array") { split = line.Split(new[] { ' ' }, 2); var arrayTok = split[0]; line = split[1]; if (arrayTok == "boolean") { type = NtType.BooleanArray; } else if (arrayTok == "double") { type = NtType.DoubleArray; } else if (arrayTok == "string") { type = NtType.StringArray; } } if (type == NtType.Unassigned) { warn?.Invoke(lineNum, "unrecognized type"); continue; } string nameTok; ReadStringToken(out nameTok, out line, line); if (string.IsNullOrEmpty(nameTok)) { warn?.Invoke(lineNum, "unterminated name string"); continue; } string name; UnescapeString(nameTok, out name); line = line.TrimStart('\t'); if (string.IsNullOrEmpty(line) || line[0] != '=') { warn?.Invoke(lineNum, "expected = after name"); continue; } line = line.Substring(1).TrimStart(' ', '\t'); Value value = null; string str; switch (type) { case NtType.Boolean: if (line == "true") { value = Value.MakeBoolean(true); } else if (line == "false") { value = Value.MakeBoolean(false); } else { warn?.Invoke(lineNum, "unrecognized boolean value, not 'true' or 'false'"); continue; } break; case NtType.Double: str = line; double tmpDouble; var tmpBoolean = double.TryParse(str, out tmpDouble); if (!tmpBoolean) { warn?.Invoke(lineNum, "invalid double value"); continue; } value = Value.MakeDouble(tmpDouble); break; case NtType.String: string strTok; ReadStringToken(out strTok, out line, line); if (string.IsNullOrEmpty(strTok)) { warn?.Invoke(lineNum, "missing string value"); continue; } if (strTok[strTok.Length - 1] != '"') { warn?.Invoke(lineNum, "unterminated string value"); continue; } UnescapeString(strTok, out str); value = Value.MakeString(str); break; case NtType.Raw: value = Value.MakeRaw(Convert.FromBase64String(line)); break; case NtType.BooleanArray: value = ReadBooleanArray(line, lineNum, boolArray, warn); if (value == null) { continue; } break; case NtType.DoubleArray: value = ReadDoubleArray(line, lineNum, doubleArray, warn); if (value == null) { continue; } break; case NtType.StringArray: value = ReadStringArray(line, lineNum, stringArray, warn); if (value == null) { continue; } break; } if (name.Length != 0 && value != null) { entries.Add(new StoragePair(name, value)); } } List <Message> msgs = new List <Message>(); IDisposable monitor = null; try { monitor = await m_monitor.EnterAsync().ConfigureAwait(false); foreach (var i in entries) { Entry entry; if (!m_entries.TryGetValue(i.First, out entry)) { entry = new Entry(i.First); m_entries.Add(i.First, entry); } var oldValue = entry.Value; entry.Value = i.Second; bool wasPersist = entry.IsPersistent(); if (!wasPersist) { entry.Flags |= EntryFlags.Persistent; } if (m_server && entry.Id == 0xffff) { uint id = (uint)m_idMap.Count; entry.Id = id; m_idMap.Add(entry); } if (m_notifier.LocalNotifiers()) { if (oldValue != null) { m_notifier.NotifyEntry(i.First, i.Second, (NotifyFlags.NotifyNew | NotifyFlags.NotifyLocal)); } else if (oldValue != i.Second) { NotifyFlags notifyFlags = NotifyFlags.NotifyUpdate | NotifyFlags.NotifyLocal; if (!wasPersist) { notifyFlags |= NotifyFlags.NotifyFlagsChanged; } m_notifier.NotifyEntry(i.First, i.Second, notifyFlags); } } if (m_queueOutgoing == null) { continue; } ++entry.SeqNum; if (oldValue == null || oldValue.Type != i.Second.Type) { msgs.Add(Message.EntryAssign(i.First, entry.Id, entry.SeqNum.Value, i.Second, entry.Flags)); } else if (entry.Id != 0xffff) { if (oldValue != i.Second) { msgs.Add(Message.EntryUpdate(entry.Id, entry.SeqNum.Value, i.Second)); } if (!wasPersist) { msgs.Add(Message.FlagsUpdate(entry.Id, entry.Flags)); } } } if (m_queueOutgoing != null) { var queuOutgoing = m_queueOutgoing; IDisposable monitorToUnlock = Interlocked.Exchange(ref monitor, null); monitorToUnlock.Dispose(); foreach (var msg in msgs) { queuOutgoing(msg, null, null); } } } finally { monitor?.Dispose(); } } return(true); }