/// <summary>
        /// Read a dictionary of tags.
        /// </summary>
        public HaystackDictionary ReadDictionary()
        {
            var  dictionary = new HaystackDictionary();
            bool braces     = _currentToken == HaystackToken.lbrace;

            if (braces)
            {
                Consume(HaystackToken.lbrace);
            }
            while (_currentToken == HaystackToken.id)
            {
                // tag name
                string id = ConsumeTagName();
                if (!char.IsLower(id[0]))
                {
                    throw GetException("Invalid dict tag name: " + id);
                }

                // tag value
                HaystackValue val = HaystackMarker.Instance;
                if (_currentToken == HaystackToken.colon)
                {
                    Consume(HaystackToken.colon);
                    val = ParseValue();
                }
                dictionary.Add(id, val);
            }
            if (braces)
            {
                Consume(HaystackToken.rbrace);
            }
            return(dictionary);
        }
Example #2
0
        void VerifyRowIterator(HaystackRow it, int iIndex, string name, HaystackValue val)
        {
            Assert.IsTrue(it.Count > iIndex);
            var strKeyValue = it.Keys.Skip(iIndex).First();

            Assert.AreEqual(name, strKeyValue);
            Assert.IsTrue(it[strKeyValue].Equals(val));
        }
 public static string ToHayson(HaystackValue val)
 {
     using (var stream = new MemoryStream())
         using (var streamWriter = new StreamWriter(stream))
             using (var writer = new HaysonWriter(streamWriter))
             {
                 writer.WriteValue(val);
                 streamWriter.Flush();
                 stream.Position = 0;
                 return(new StreamReader(stream).ReadToEnd());
             }
 }
        private HaystackList ParseList()
        {
            List <HaystackValue> arr = new List <HaystackValue>();

            Consume(HaystackToken.lbracket);
            while (_currentToken != HaystackToken.rbracket && _currentToken != HaystackToken.eof)
            {
                HaystackValue val = ParseValue();
                arr.Add(val);
                if (_currentToken != HaystackToken.comma)
                {
                    break;
                }
                Consume(HaystackToken.comma);
            }
            Consume(HaystackToken.rbracket);
            return(new HaystackList(arr));
        }
        /// <summary>
        /// Read a single value.
        /// </summary>
        public HaystackValue ReadValue()
        {
            HaystackValue val       = null;
            bool          bValisVer = false;

            if (_currentValue is string)
            {
                if (((string)_currentValue).CompareTo("ver") == 0)
                {
                    bValisVer = true;
                }
            }
            if (_currentToken == HaystackToken.id && bValisVer)
            {
                val = ReadGrid();
            }
            else
            {
                val = ParseValue();
            }
            // Depart from Java - 15.08.2018 after testing with Java Toolkit
            // It is possible there might be newlines or other non prihtables before eof
            // only verify it is not a token of interest
            bool bEnd = false;

            while (!bEnd)
            {
                if (TryVerify(HaystackToken.nl, false))
                {
                    Consume();
                }
                else
                {
                    // This will throw an exception if it is not eof
                    Verify(HaystackToken.eof);
                    bEnd = true;
                }
            }
            return(val);
        }
        private HaystackGrid ReadGrid()
        {
            bool nested = _currentToken == HaystackToken.lt2;

            if (nested)
            {
                Consume(HaystackToken.lt2);
                if (_currentToken == HaystackToken.nl)
                {
                    Consume(HaystackToken.nl);
                }
            }

            bool bValisVer = false;

            if (_currentValue is string)
            {
                if (((string)_currentValue).CompareTo("ver") == 0)
                {
                    bValisVer = true;
                }
            }
            // ver:"3.0"
            if (_currentToken != HaystackToken.id || !bValisVer)
            {
                throw GetException("Expecting grid 'ver' identifier, not " + curToStr());
            }
            Consume();
            Consume(HaystackToken.colon);
            _version = CheckVersion(ConsumeStr());

            // grid meta
            var grid = new HaystackGrid();

            if (_currentToken == HaystackToken.id)
            {
                var dict = ReadDictionary();
                foreach (var kv in dict)
                {
                    grid.AddMeta(kv.Key, kv.Value);
                }
            }
            Consume(HaystackToken.nl);

            // column definitions
            int numCols = 0;

            while (_currentToken == HaystackToken.id)
            {
                ++numCols;
                string name    = ConsumeTagName();
                var    colMeta = new HaystackDictionary();
                if (_currentToken == HaystackToken.id)
                {
                    colMeta = ReadDictionary();
                }
                grid.AddColumn(name, colMeta);
                if (_currentToken != HaystackToken.comma)
                {
                    break;
                }
                Consume(HaystackToken.comma);
            }
            if (numCols == 0)
            {
                throw GetException("No columns defined");
            }
            Consume(HaystackToken.nl);

            // grid rows
            while (true)
            {
                if (_currentToken == HaystackToken.nl)
                {
                    break;
                }
                if (_currentToken == HaystackToken.eof)
                {
                    break;
                }
                if (nested && _currentToken == HaystackToken.gt2)
                {
                    break;
                }

                // read cells
                HaystackValue[] cells = new HaystackValue[numCols];
                for (int i = 0; i < numCols; ++i)
                {
                    if (_currentToken == HaystackToken.comma || _currentToken == HaystackToken.nl || _currentToken == HaystackToken.eof)
                    {
                        cells[i] = null;
                    }
                    else
                    {
                        cells[i] = ParseValue();
                    }
                    if (i + 1 < numCols)
                    {
                        Consume(HaystackToken.comma);
                    }
                }
                grid.AddRow(cells);

                // newline or end
                if (nested && _currentToken == HaystackToken.gt2)
                {
                    break;
                }
                if (_currentToken == HaystackToken.eof)
                {
                    break;
                }
                Consume(HaystackToken.nl);
            }

            if (_currentToken == HaystackToken.nl)
            {
                Consume(HaystackToken.nl);
            }
            if (nested)
            {
                Consume(HaystackToken.gt2);
            }
            return(grid);
        }
 public void WriteValue(HaystackValue value)
 {
     if (value == null)
     {
         _haysonWriter.WriteNull();
         return;
     }
     if (value is HaystackString strValue)
     {
         _haysonWriter.WriteValue(strValue.Value);
         return;
     }
     if (value is HaystackNumber numValue)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("number");
         _haysonWriter.WritePropertyName("val");
         _haysonWriter.WriteValue(numValue.Value);
         _haysonWriter.WritePropertyName("unit");
         _haysonWriter.WriteValue(numValue.Unit);
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackBoolean boolValue)
     {
         _haysonWriter.WriteValue(boolValue.Value);
         return;
     }
     if (value is HaystackList listValue)
     {
         _haysonWriter.WriteStartArray();
         foreach (var val in listValue)
         {
             WriteValue(val);
         }
         _haysonWriter.WriteEndArray();
         return;
     }
     if (value is HaystackDictionary dictValue)
     {
         WriteEntity(dictValue);
         return;
     }
     if (value is HaystackGrid gridValue)
     {
         WriteGrid(gridValue);
         return;
     }
     if (value is HaystackMarker)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("marker");
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackRemove)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("remove");
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackNotAvailable)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("na");
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackReference refValue)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("ref");
         _haysonWriter.WritePropertyName("val");
         _haysonWriter.WriteValue(refValue.Value);
         _haysonWriter.WritePropertyName("dis");
         _haysonWriter.WriteValue(refValue.Display);
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackDate dateValue)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("date");
         _haysonWriter.WritePropertyName("val");
         _haysonWriter.WriteValue($"{dateValue.Value.Year:d4}-{dateValue.Value.Month:d2}-{dateValue.Value.Day:d2}");
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackTime timeValue)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("time");
         _haysonWriter.WritePropertyName("val");
         _haysonWriter.WriteValue($"{timeValue.Value.Hours:d2}-{timeValue.Value.Minutes:d2}-{timeValue.Value.Seconds:d2}");
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackDateTime dateTimeValue)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("dateTime");
         _haysonWriter.WritePropertyName("val");
         _haysonWriter.WriteValue(dateTimeValue.Value.ToString("o"));
         _haysonWriter.WritePropertyName("tz");
         _haysonWriter.WriteValue(dateTimeValue.TimeZone.Name);
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackUri uriValue)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("uri");
         _haysonWriter.WritePropertyName("val");
         _haysonWriter.WriteValue(uriValue.Value);
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackCoordinate coordValue)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("coord");
         _haysonWriter.WritePropertyName("lat");
         _haysonWriter.WriteValue(coordValue.Latitude);
         _haysonWriter.WritePropertyName("lng");
         _haysonWriter.WriteValue(coordValue.Longitude);
         _haysonWriter.WriteEndObject();
         return;
     }
     if (value is HaystackXString xStrValue)
     {
         _haysonWriter.WriteStartObject();
         _haysonWriter.WritePropertyName("_kind");
         _haysonWriter.WriteValue("xStr");
         _haysonWriter.WritePropertyName("type");
         _haysonWriter.WriteValue(xStrValue.Type);
         _haysonWriter.WritePropertyName("val");
         _haysonWriter.WriteValue(xStrValue.Value);
         _haysonWriter.WriteEndObject();
         return;
     }
 }
 protected void VerifyZinc(HaystackValue val, string s)
 {
     Assert.AreEqual(s, ZincWriter.ToZinc(val));
     Assert.IsTrue(ZincReader.ReadValue(s).Equals(val));
 }
        public ZincWriter WriteValue(HaystackValue value)
        {
            if (value == null)
            {
                WriteValue('N');
            }
            else if (value is HaystackBinary bin)
            {
                WriteValue("Bin(\"").WriteValue(bin.Mime).WriteValue("\")");
            }
            else if (value is HaystackBoolean boolean)
            {
                WriteValue(boolean.Value ? "T" : "F");
            }
            else if (value is HaystackCoordinate coordinate)
            {
                WriteValue($"C({coordinate.Latitude.ToString(_numberFormat)},{coordinate.Longitude.ToString(_numberFormat)})");
            }
            else if (value is HaystackDate date)
            {
                WriteValue(date.Value.ToString("yyyy-MM-dd"));
            }
            else if (value is HaystackDateTime dateTime)
            {
                var val = dateTime.Value.ToString("yyyy-MM-dd'T'HH:mm:ss.FFF");
                if (dateTime.TimeZone.Name == "UTC")
                {
                    val += "Z UTC";
                }
                else
                {
                    val += dateTime.Value.Offset.Hours >= 0 ? "+" : "-";
                    val += dateTime.Value.Offset.ToString(@"hh\:mm");
                    val += " ";
                    val += dateTime.TimeZone.Name;
                }
                WriteValue(val);
            }
            else if (value is HaystackDefinition definition)
            {
                WriteValue(definition.Value);
            }
            else if (value is HaystackDictionary dictionary)
            {
                WriteDictionary(dictionary, true);
            }
            else if (value is HaystackGrid)
            {
                HaystackGrid grid = (HaystackGrid)value;
                if (_isInGrid)
                {
                    WriteNestedGrid(grid);
                }
                else
                {
                    _isInGrid = true;
                    WriteGrid(grid);
                    _isInGrid = false;
                }
            }
            else if (value is HaystackHistoryItem historyItem)
            {
                throw new NotImplementedException("Cannot write history item");
            }
            else if (value is HaystackList list)
            {
                WriteList(list);
            }
            else if (value is HaystackMarker)
            {
                WriteValue("M");
            }
            else if (value is HaystackNotAvailable)
            {
                WriteValue("NA");
            }
            else if (value is HaystackNumber number)
            {
                if (number.Value == double.PositiveInfinity)
                {
                    WriteValue("INF");
                }
                else if (number.Value == double.NegativeInfinity)
                {
                    WriteValue("-INF");
                }
                else if (double.IsNaN(number.Value))
                {
                    WriteValue("NaN");
                }
                else
                {
                    double abs = Math.Abs(number.Value);
                    WriteValue(number.Value.ToString("#0.####", _numberFormat));
                    if (number.Unit != null)
                    {
                        WriteValue(number.Unit);
                    }
                }
            }
            else if (value is HaystackReference reference)
            {
                WriteValue($"@{reference.Value}");
                if (reference.Display != null)
                {
                    WriteValue(" ");
                    WriteValue(new HaystackString(reference.Display));
                }
            }
            else if (value is HaystackRemove)
            {
                WriteValue("R");
            }
            else if (value is HaystackString str)
            {
                if (str.Value == null)
                {
                    WriteValue(null);
                }
                else
                {
                    var escaped = str.Value
                                  .SelectMany(chr =>
                    {
                        switch (chr)
                        {
                        case ('\n'): return(@"\n".ToCharArray());

                        case ('\r'): return(@"\r".ToCharArray());

                        case ('\t'): return(@"\t".ToCharArray());

                        case ('"'): return(@"\""".ToCharArray());

                        case ('\\'): return(@"\\".ToCharArray());

                        default:
                            if (chr < ' ')
                            {
                                return((@"\u" + Convert.ToByte(chr).ToString("x4")).ToCharArray());
                            }
                            return(new[] { chr });
                        }
                    })
                                  .ToArray();
                    WriteValue($@"""{new string(escaped)}""");
                }
            }
            else if (value is HaystackTime time)
            {
                if (time.Value.Milliseconds == 0)
                {
                    WriteValue(time.Value.ToString("hh\\:mm\\:ss"));
                }
                else
                {
                    WriteValue(time.Value.ToString("hh\\:mm\\:ss\\.fff"));
                }
            }
            else if (value is HaystackUri uri)
            {
                var escaped = uri.Value
                              .SelectMany(chr =>
                {
                    if (chr == '`')
                    {
                        return(@"\`".ToCharArray());
                    }
                    if (chr < ' ')
                    {
                        throw new ArgumentException($"Invalid URI '{uri.Value}', char='{chr}'", "uri");
                    }
                    return(new[] { chr });
                })
                              .ToArray();
                WriteValue($@"`{new string(escaped)}`");
            }
            else if (value is HaystackXString xstr)
            {
                WriteValue(xstr.Type).WriteValue("(\"").WriteValue(xstr.Value).WriteValue("\")");
            }
            else
            {
                throw new InvalidOperationException($"Cannot write scalar value of type {value.GetType().Name}");
            }
            return(this);
        }
Example #10
0
        /// <summary>
        /// Write to a given level of a writable point, and return the current status
        /// of a writable point's priority array <see cref="pointWriteArray"/>.
        /// </summary>
        /// <param name="id">Reference of a writable point.</param>
        /// <param name="level">Number for level to write [1-17].</param>
        /// <param name="who">Username performing the write, defaults to user dis.</param>
        /// <param name="val">Value to write or null to auto the level.</param>
        /// <param name="dur">Number with duration unit if setting level 8.</param>
        /// <returns>Result grid.</returns>
        public Task <HaystackGrid> PointWriteAsync(HaystackReference id, int level, string who, HaystackValue val, HaystackNumber dur)
        {
            var req = new HaystackGrid()
                      .AddColumn("id")
                      .AddColumn("level")
                      .AddColumn("who")
                      .AddColumn("val")
                      .AddColumn("duration")
                      .AddRow(id, new HaystackNumber(level), new HaystackString(who), val, dur);

            return(CallAsync("pointWrite", req));
        }