/// <summary> /// Parse string into key. /// </summary> /// <param name="lineFormat"></param> /// <param name="str"></param> /// <param name="result">key result or null if contained no content</param> /// <param name="prevPart">(optional) previous part to append to</param> /// <param name="appender">(optional) line appender to append with. If null, uses appender from <paramref name="prevPart"/>. If null, uses default appender.</param> /// <returns>true if parse was successful (even through resulted key might be null)</returns> public static bool TryParse(this ILineFormat lineFormat, string str, out ILine result, ILine prevPart = default, ILineFactory appender = default) { if (lineFormat is ILineFormatAppendParser appendParser) { return(appendParser.TryParse(str, out result, prevPart, appender)); } // Try get appender if (appender == null && !prevPart.TryGetAppender(out appender)) { result = null; return(false); } // Try parse IEnumerable <ILineArgument> args; if (lineFormat is ILineFormatParser parser && parser.TryParseArgs(str, out args)) { // Append arguments foreach (ILineArgument arg in parser.ParseArgs(str)) { if (!appender.TryCreate(prevPart, arg, out prevPart)) { result = null; return(false); } } result = prevPart; return(true); }
/// <summary> /// Try get parameter infos. /// </summary> /// <param name="lineFormat"></param> /// <param name="parameterInfos"></param> /// <returns>true if returned infos</returns> public static bool TryGetParameterInfos(this ILineFormat lineFormat, out IParameterInfos parameterInfos) { ILineFactory lineFactory; if (lineFormat.TryGetLineFactory(out lineFactory) && lineFactory.TryGetParameterInfos(out parameterInfos)) return true; parameterInfos = default; return false; }
/// <summary> /// Get parameter infos. /// </summary> /// <param name="lineFormat"></param> /// <returns>infos or null</returns> public static IParameterInfos GetParameterInfos(this ILineFormat lineFormat) { ILineFactory lineFactory; IParameterInfos parameterInfos; if (lineFormat.TryGetLineFactory(out lineFactory) && lineFactory.TryGetParameterInfos(out parameterInfos)) return parameterInfos; return null; }
/// <summary> /// Json text into a tree. /// </summary> /// <param name="text"></param> /// <param name="lineFormat"></param> /// <returns></returns> public ILineTree ReadLineTree(TextReader text, ILineFormat lineFormat = default) { LineTree root = new LineTree(); using (var ini = new IniTokenizer(text.ReadToEnd())) ReadIniIntoTree(ini, root, lineFormat, null); return(root); }
/// <summary> /// Build name for key. /// </summary> /// <param name="key"></param> /// <param name="policy">(optional)</param> /// <returns>full name string or null</returns> public static string Print(this ILine key, ILineFormat policy) { if (policy == null) { policy = LineParameterPrinter.Default; } return(policy.Print(key)); }
/// <summary> /// Convenience constructor that adds one lines source <paramref name="reader"/>. /// /// <paramref name="reader"/> must implement one of: /// <list type="bullet"> /// <item>IEnumerable>KeyValuePair>ILine, IString<<</item> /// <item>IEnumerable>KeyValuePair>string, IString<<</item> /// <item>IEnumerable>KeyValuePair>ILine, string<<</item> /// <item>IEnumerable>KeyValuePair>string, string<<</item> /// <item>IEnumerable>ILineTree<</item> /// </list> /// </summary> /// <param name="reader">initial reader</param> /// <param name="lineFormat"></param> /// <param name="comparer">(optional) comparer to use</param> /// <param name="errorHandler">(optional) handler, if null or returns false, then exception is let to be thrown</param> public StringAsset(IEnumerable reader, ILineFormat lineFormat = default, IEqualityComparer <ILine> comparer = default, Func <Exception, bool> errorHandler = null) : base() { this.comparer = comparer ?? LineComparer.Default; this.errorHandler = errorHandler; this.LineFactory = LineAppender.Default; Add(reader ?? throw new ArgumentNullException(nameof(reader)), lineFormat); Load(); }
/// <summary> /// Try get parameter info. /// </summary> /// <param name="lineFormat"></param> /// <param name="parameterName"></param> /// <param name="parameterInfo"></param> /// <returns>true if returned info</returns> public static bool TryGetParameterInfo(this ILineFormat lineFormat, string parameterName, out IParameterInfo parameterInfo) { ILineFactory lineFactory; IParameterInfos parameterInfos; if (lineFormat.TryGetLineFactory(out lineFactory) && lineFactory.TryGetParameterInfos(out parameterInfos) && parameterInfos.TryGetValue(parameterName, out parameterInfo)) return true; parameterInfo = null; return false; }
/// <summary> /// Get parameter info. /// </summary> /// <param name="lineFormat"></param> /// <param name="parameterName"></param> /// <returns>info or null</returns> public static IParameterInfo GetParameterInfo(this ILineFormat lineFormat, string parameterName) { IParameterInfo info; ILineFactory lineFactory; IParameterInfos parameterInfos; if (lineFormat.TryGetLineFactory(out lineFactory) && lineFactory.TryGetParameterInfos(out parameterInfos) && parameterInfos.TryGetValue(parameterName, out info)) return info; return null; }
/// <summary> /// Build name for key. /// </summary> /// <param name="lineFormat"></param> /// <param name="key"></param> /// <returns>full name string or null</returns> public static string Print(this ILineFormat lineFormat, ILine key) { if (lineFormat is ILineFormatPrinter provider) { string name = provider.Print(key); if (name != null) return name; } return null; }
/// <summary> /// Read key tree from <paramref name="text"/>. /// </summary> /// <param name="text"></param> /// <param name="lineFormat">uses parameter info</param> /// <returns></returns> public ILineTree ReadLineTree(TextReader text, ILineFormat lineFormat = default) { ILineFactory _lineFactory; if (!lineFormat.TryGetLineFactory(out _lineFactory)) { _lineFactory = LineFactory; } return(ReadElement(Load(text).Root, new LineTree(), null, _lineFactory)); }
/// <summary> /// Read key tree from <paramref name="stream"/>. /// </summary> /// <param name="stream"></param> /// <param name="lineFormat">uses parameter info</param> /// <returns></returns> public ILineTree ReadLineTree(Stream stream, ILineFormat lineFormat = default) { ILineFactory _lineFactory; if (!lineFormat.TryGetLineFactory(out _lineFactory)) { _lineFactory = LineFactory; } return(ReadElement(Load(stream).Root, new LineTree(), null, _lineFactory)); }
/// <summary> /// Read key tree from <paramref name="element"/> /// </summary> /// <param name="element"></param> /// <param name="lineFormat">uses parameter info</param> /// <returns></returns> public ILineTree ReadLineTree(XElement element, ILineFormat lineFormat = default) { ILineFactory _lineFactory; if (!lineFormat.TryGetLineFactory(out _lineFactory)) { _lineFactory = LineFactory; } return(ReadElement(element, new LineTree(), null, _lineFactory)); }
/// <summary> /// Json text into a tree. /// </summary> /// <param name="text"></param> /// <param name="lineFormat">unused</param> /// <returns></returns> public ILineTree ReadLineTree(TextReader text, ILineFormat lineFormat = default) { LineTree root = new LineTree(); using (var json = new JsonTextReader(text)) { ReadJsonIntoTree(json, root, lineFormat, null); } return(root); }
/// <summary> /// Convert <paramref name="lines"/> to Key Tree of one level. /// </summary> /// <param name="lines"></param> /// <param name="lineFormat"></param> /// <returns></returns> public static ILineTree ToLineTree(this IEnumerable <ILine> lines, ILineFormat lineFormat) { LineTree tree = new LineTree(); if (lineFormat is ILinePattern pattern) { tree.AddRange(lines, pattern, lineFormat.GetParameterInfos()); } else { tree.AddRange(lines); } return(tree); }
/// <summary> /// Parse string into key. /// </summary> /// <param name="lineFormat"></param> /// <param name="str">key as string</param> /// <param name="prevPart">(optional) previous part to append to</param> /// <param name="appender">(optional) line appender to append with. If null, uses appender from <paramref name="prevPart"/>. If null, uses default appender.</param> /// <returns>key result or null if contained no content</returns> /// <exception cref="LineException">If parse failed</exception> /// <exception cref="LineException">If <paramref name="lineFormat"/> doesn't implement <see cref="ILineFormatParser"/>.</exception> /// <exception cref="LineException">Error if appender is not available</exception> public static ILine Parse(this ILineFormat lineFormat, string str, ILine prevPart = default, ILineFactory appender = default) { if (lineFormat is ILineFormatAppendParser appendParser) { return appendParser.Parse(str, prevPart, appender); } if (lineFormat is ILineFormatParser parser) { if (appender == null) appender = prevPart.GetAppender(); foreach (ILineArgument arg in parser.ParseArgs(str)) prevPart = appender.Create(prevPart, arg); return prevPart; } else throw new LineException(prevPart, $"Cannot parse strings to {nameof(ILine)} with {lineFormat.GetType().FullName}. {lineFormat} doesn't implement {nameof(ILineFormatParser)}."); }
/// <summary> /// Read lines from xml element, update <paramref name="correspondence"/>. /// </summary> /// <param name="element"></param> /// <param name="lineFormat">unused</param> /// <param name="correspondence"></param> /// <returns></returns> public List <KeyValuePair <string, IString> > ReadElement(XElement element, ILineFormat lineFormat, ResXCorrespondence correspondence) { List <KeyValuePair <string, IString> > result = new List <KeyValuePair <string, IString> >(); foreach (XElement dataNode in element.Elements("data")) { XAttribute name = dataNode.Attribute("name"); string key = name?.Value; if (key == null) { continue; } if (correspondence != null) { correspondence.Nodes.Put(key, dataNode); } foreach (XElement valueNode in dataNode.Elements("value")) { foreach (XNode textNode in valueNode.Nodes()) { if (textNode is XText text) { IString value = ValueParser.Parse(text?.Value); if (value != null) { result.Add(new KeyValuePair <string, IString>(key, value)); if (correspondence != null) { correspondence.Values[new KeyValuePair <string, IString>(key, value)] = dataNode; } } } } } } return(result); }
/// <summary> /// Add byte[] dictionary to builder. /// </summary> /// <param name="builder"></param> /// <param name="dictionary"></param> /// <param name="lineFormat">instructions how to convert key to byte[]</param> /// <returns></returns> public static IAssetBuilder AddResources(this IAssetBuilder builder, IReadOnlyDictionary <String, byte[]> dictionary, ILineFormat lineFormat) { builder.AddAsset(new ResourceStringDictionary(dictionary, lineFormat)); return(builder); }
/// <summary> /// Read json token stream into <paramref name="node"/> /// </summary> /// <param name="json"></param> /// <param name="node">parent node to under which add nodes</param> /// <param name="lineFormat">unused</param> /// <param name="correspondenceContext">(optional) place to update correspondence. If set <paramref name="json"/> must implement <see cref="JTokenReader"/>.</param> /// <returns></returns> public ILineTree ReadJsonIntoTree(JsonReader json, ILineTree node, ILineFormat lineFormat, JsonCorrespondence correspondenceContext) { ILineFactory tmp; ILineFormat _lineFormat = lineFormat.TryGetLineFactory(out tmp) && tmp != LineFactory ? new LineFormat(" :\\", false, " :\\", false, tmp, null) : this.lineFormat; ILineTree current = node; Stack <ILineTree> stack = new Stack <ILineTree>(); JTokenReader tokenReader = json as JTokenReader; bool updateCorrespondence = correspondenceContext != null && tokenReader != null; while (json.Read()) { switch (json.TokenType) { case JsonToken.StartObject: stack.Push(current); if (updateCorrespondence) { correspondenceContext.Nodes.Put(current, tokenReader.CurrentToken); } break; case JsonToken.EndObject: current = stack.Pop(); break; case JsonToken.PropertyName: ILine key = null; if (_lineFormat.TryParse(json.Value?.ToString(), out key)) { current = key == null?stack.Peek() : stack.Peek()?.Create(key); if (current != null && updateCorrespondence && !correspondenceContext.Nodes.ContainsLeft(current)) { correspondenceContext.Nodes.Put(current, tokenReader.CurrentToken); } } else { current = null; } break; case JsonToken.Raw: case JsonToken.Date: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Float: case JsonToken.Integer: if (current != null) { string value = json.Value?.ToString(); if (value != null) { int ix = current.Values.Count; IStringFormat stringFormat; if (current.TryGetStringFormat(resolver, out stringFormat)) { // Append FormatString IString valueString = stringFormat.Parse(value); ILineString lineValue = LineFactory.Create <ILineString, IString>(null, valueString); current.Values.Add(lineValue); if (updateCorrespondence) { correspondenceContext.Values[new LineTreeValue(current, lineValue, ix)] = (JValue)tokenReader.CurrentToken; } } else { // Append Hint ILineHint lineValue = LineFactory.Create <ILineHint, string, string>(null, "String", value); current.Values.Add(lineValue); if (updateCorrespondence) { correspondenceContext.Values[new LineTreeValue(current, lineValue, ix)] = (JValue)tokenReader.CurrentToken; } } } } break; case JsonToken.StartArray: if (updateCorrespondence) { correspondenceContext.Nodes.Put(current, tokenReader.CurrentToken); } break; case JsonToken.EndArray: break; } } return(node); }
public IEnumerable <ILine> ReadLines( TextReader text, ILineFormat lineFormat = null) { yield return(LineAppender.Default.Section("MyClass").Key("HelloWorld").Culture("en").Format("Hello World!")); }
/// <summary> /// Create abstract file source. /// </summary> /// <param name="fileFormat"></param> /// <param name="path"></param> /// <param name="filename"></param> /// <param name="lineFormat"></param> /// <param name="throwIfNotFound"></param> public LineFileSource(ILineFileFormat fileFormat, string path, string filename, ILineFormat lineFormat, bool throwIfNotFound) : base(path, filename, throwIfNotFound) { this.FileFormat = fileFormat ?? throw new ArgumentNullException(nameof(fileFormat)); this.LineFormat = lineFormat; }
/// <summary> /// Create localization file source that reads as string lines. /// </summary> /// <param name="fileFormat"></param> /// <param name="path">(optional) root folder</param> /// <param name="filename">non-rooted relative path, or rooted full path</param> /// <param name="lineFormat"></param> /// <param name="throwIfNotFound"></param> public StringLineFileSource(ILineFileFormat fileFormat, string path, string filename, ILineFormat lineFormat, bool throwIfNotFound) : base(fileFormat, path, filename, lineFormat, throwIfNotFound) { }
/// <summary> /// Create abstract file source. /// </summary> /// <param name="fileFormat"></param> /// <param name="path"></param> /// <param name="filePattern"></param> /// <param name="lineFormat"></param> public LineFilePatternSource(ILineFileFormat fileFormat, string path, ILinePattern filePattern, ILineFormat lineFormat) : base(path, filePattern) { this.FileFormat = fileFormat ?? throw new ArgumentNullException(nameof(fileFormat)); this.LineFormat = lineFormat; }
/// <summary> /// Create source to localization file in a <paramref name="fileProvider"/>. /// </summary> /// <param name="fileFormat"></param> /// <param name="fileProvider"></param> /// <param name="filepath"></param> /// <param name="lineFormat"></param> /// <param name="throwIfNotFound"></param> public StringLineFileProviderSource(ILineFileFormat fileFormat, IFileProvider fileProvider, string filepath, ILineFormat lineFormat, bool throwIfNotFound) : base(fileFormat, fileProvider, filepath, lineFormat, throwIfNotFound) { }
/// <summary> /// Create (abstract) source to localization file in a file provider. /// </summary> /// <param name="fileFormat"></param> /// <param name="fileProvider"></param> /// <param name="filepath"></param> /// <param name="lineFormat"></param> /// <param name="throwIfNotFound"></param> public LineFileProviderSource(ILineFileFormat fileFormat, IFileProvider fileProvider, string filepath, ILineFormat lineFormat, bool throwIfNotFound) : base(fileProvider, filepath, throwIfNotFound) { this.FileFormat = fileFormat ?? throw new ArgumentNullException(nameof(fileFormat)); this.LineFormat = lineFormat; }
/// <summary> /// Add byte[] dictionary to composition. /// </summary> /// <param name="composition"></param> /// <param name="dictionary"></param> /// <param name="lineFormat">instructions how to convert key to byte[]</param> /// <returns></returns> public static IAssetComposition AddResources(this IAssetComposition composition, IReadOnlyDictionary <String, byte[]> dictionary, ILineFormat lineFormat) { composition.Add(new ResourceStringDictionary(dictionary, lineFormat)); return(composition); }
/// <summary> /// Read localization lines from <see cref="Stream"/> into most suitable asset implementation. /// /// File cannot be reloaded. /// </summary> /// <param name="fileFormat"></param> /// <param name="stream"></param> /// <param name="lineFormat">(optional) possibly needed for string and line conversions. Used also for choosing whether to instantiate parameter into hint or key</param> /// <returns>localization asset</returns> public static IAsset StreamAsset(this ILineFileFormat fileFormat, Stream stream, ILineFormat lineFormat = default) { if (fileFormat is ILineTreeTextReader || fileFormat is ILineTreeStreamReader) { return(new StringAsset().Add(new ILineTree[] { fileFormat.ReadLineTree(stream, lineFormat) }, lineFormat).Load()); } else if (fileFormat is ILineTextReader || fileFormat is ILineStreamReader) { return(new StringAsset().Add(fileFormat.ReadLines(stream, lineFormat), lineFormat).Load()); } else if (fileFormat is ILineStringTextReader || fileFormat is ILineStringStreamReader) { return(new StringAsset().Add(fileFormat.ReadStringLines(stream, lineFormat), lineFormat).Load()); } throw new ArgumentException($"Cannot create asset for {fileFormat}."); }
/// <summary> /// Create language byte[] resolver that uses a dictionary as a backend. /// </summary> /// <param name="dictionary">dictionary</param> /// <param name="lineFormat">line format for converting lines to strings</param> public ResourceStringDictionary(IReadOnlyDictionary <string, byte[]> dictionary, ILineFormat lineFormat = default) { this.dictionary = dictionary ?? throw new ArgumentNullException(nameof(dictionary)); this.lineFormat = lineFormat ?? throw new ArgumentNullException(nameof(lineFormat)); }
/// <summary> /// Convert <paramref name="lines"/> to asset. /// /// Lines are reloaded into the asset if <see cref="IAssetExtensions.Reload(IAsset)"/> is called. /// </summary> /// <param name="lines"></param> /// <param name="lineFormat"><see cref="ILineFormatParser"/> parses strings to lines.</param> /// <returns></returns> public static IAsset ToAsset(this IEnumerable <KeyValuePair <string, IString> > lines, ILineFormat lineFormat) => new StringAsset().Add(lines, lineFormat).Load();
/// <summary> /// Read localization strings from <see cref="Stream"/> into most suitable asset implementation. /// /// File cannot be reloaded. /// </summary> /// <param name="fileFormat"></param> /// <param name="streamSource"></param> /// <param name="lineFormat">(optional) possibly needed for string and line conversions. Used also for choosing whether to instantiate parameter into hint or key</param> /// <returns>localization asset</returns> public static IAssetSource StreamAssetSource(this ILineFileFormat fileFormat, Func <Stream> streamSource, ILineFormat lineFormat = default) => new StreamProviderAssetSource(fileFormat, streamSource, lineFormat);
/// <summary> /// Convert <paramref name="lines"/> to <see cref="IAssetSource"/>. /// </summary> /// <param name="lines"></param> /// <param name="policy"></param> /// <returns></returns> public static IAssetSource ToAssetSource(this IEnumerable <KeyValuePair <string, IString> > lines, ILineFormat policy) => new StringLinesSource(lines, policy);