Esempio n. 1
0
 public static string[] SplitPatternList(SplitterOptions options, string originalString, string stringPattern, Regex regexPattern)
 {
     return(regexPattern == null
         ? Regex.Split(originalString, stringPattern)
         : options.LimitLength > 0
             ? regexPattern.Split(originalString, options.LimitLength)
             : regexPattern.Split(originalString));
 }
Esempio n. 2
0
            public static (string, string) SplitMap(SplitterOptions options, string middleString)
            {
                var t     = middleString.Split(options.MapSeparator);
                var key   = t[0];
                var value = t.Length > 1 ? t[1] : string.Empty;

                return(key, value);
            }
            public static (string, string) SplitMap(SplitterOptions options, string middleString)
            {
#if NETFRAMEWORK || NETSTANDARD2_0
                var t = middleString.Split(new[] { options.MapSeparator }, StringSplitOptions.None);
#else
                var t = middleString.Split(options.MapSeparator);
#endif
                var key   = t[0];
                var value = t.Length > 1 ? t[1] : string.Empty;
                return(key, value);
            }
Esempio n. 4
0
 public static string[] SplitList(SplitterOptions options, string originalString, string[] on)
 {
     return(originalString.Split(on, options.GetStringSplitOptions()));
 }
Esempio n. 5
0
 public static IEnumerable <string> OptionalRange(SplitterOptions options, string[] middleStrings)
 {
     return(options.TrimResultsFlag ? middleStrings.Select(options.TrimFunc) : middleStrings);
 }
Esempio n. 6
0
 /// <summary>
 /// Splits the supplied PolyMeshes on the specified plane and
 /// returns the desired results (specified by the options parameter)
 /// in a pair containing lists of PolyMeshes for the negative
 /// (element 0) and the positive side (element 1) of the plane.
 /// Note that the normal vector of the plane need not be normalized.
 /// </summary>
 public static (List <PolyMesh>, List <PolyMesh>) SplitOnPlane(
     this IEnumerable <PolyMesh> polyMeshes,
     Plane3d plane, double epsilon, SplitterOptions options)
 {
     return(polyMeshes.SplitOnPlane(plane, epsilon, options, s_polyMeshSplitOnPlane));
 }
Esempio n. 7
0
        /// <summary>
        /// Splits the mesh on the specified plane in a pair containing the negative
        /// (element 0) and the positive side (element 1) of the plane.
        /// Note that the normal vector of the plane need not be normalized.
        /// </summary>
        public (PolyMesh, PolyMesh) SplitOnPlane(
            Plane3d plane, double epsilon, SplitterOptions options)
        {
            var heightArray = m_positionArray.Map(
                m_vertexCount, p => plane.Height(p));
            var splitter = new PolygonSplitter(
                m_firstIndexArray, m_faceCount,
                m_vertexIndexArray, m_faceVertexCountRange.Max,
                heightArray, epsilon, options);

            var result = (default(PolyMesh), default(PolyMesh));

            for (int side = 0; side < 2; side++)
            {
                var fia = splitter.FirstIndexArray(side);
                if (fia != null)
                {
                    if (splitter.IsEqualToInput(side))
                    {
                        //result[side] = this;
                        switch (side)
                        {
                        case 0:
                            result = (this, result.Item2);
                            break;

                        case 1:
                            result = (result.Item1, this);
                            break;

                        default:
                            throw new IndexOutOfRangeException();
                        }
                    }
                    else
                    {
                        var pm = new PolyMesh()
                        {
                            FirstIndexArray    = fia,
                            VertexIndexArray   = splitter.VertexIndexArray(side),
                            InstanceAttributes = InstanceAttributes,
                            FaceAttributes     = FaceIAttributes.Select(
                                a => splitter.FaceAttribute(side, a)).ToSymbolDict(),
                            VertexAttributes = VertexIAttributes.Select(
                                a => splitter.VertexAttribute(side, a)).ToSymbolDict(),
                            FaceVertexAttributes = FaceVertexIAttributes.Select(
                                a => splitter.FaceVertexAttribute(side, a)).ToSymbolDict(),
                        };

                        //result[side] = pm;
                        switch (side)
                        {
                        case 0:
                            result = (pm, result.Item2);
                            break;

                        case 1:
                            result = (result.Item1, pm);
                            break;

                        default:
                            throw new IndexOutOfRangeException();
                        }
                    }
                }
            }

            return(result);
        }
Esempio n. 8
0
        /// <summary>
        /// A splitter can split a vertex-indexed face set, based on the
        /// supplied array of vertexHeights, which indicate for each vertex
        /// vi if it belongs to the negative split side (vertexHeights[vi]
        /// &lt; 0.0) or positive split side (vertexHeights[vi] &gt;= 0.0).
        /// </summary>
        public PolygonSplitter(
            int[] fia, int faceCount,
            int[] via, int maxFaceVertexCount,
            double[] vertexHeights, double eps,
            SplitterOptions options)
        {
            int vc = vertexHeights.Length;
            int vertexIndexCount = fia[faceCount];

            bool doNeg = (options & SplitterOptions.Negative) != 0;
            bool doPos = (options & SplitterOptions.Positive) != 0;

            if (doPos && vertexHeights.All(h => h >= -eps))
            {
                m_pfia = fia; m_pvia = via; m_ofia = null; return;
            }

            if (doNeg && vertexHeights.All(h => h <= eps))
            {
                m_nfia = fia; m_nvia = via; m_ofia = null; return;
            }

            m_ofia = fia;

            var lineMap = new Dict <Line1i, (int, int, int)>();

            m_spl = doNeg ? new List <SplitPoint>() : null;
            m_nvl = doPos ? new List <Vertex>() : null;
            m_pvl = doPos ? new List <Vertex>() : null;
            m_nfl = doNeg ? new List <Face>() : null;
            m_pfl = doPos ? new List <Face>() : null;

            int[] nffm = doNeg ? new int[faceCount].Set(-1) : null;
            int[] pffm = doPos ? new int[faceCount].Set(-1) : null;

            int[] nvfm = doNeg ? new int[vc].Set(-1) : null;
            int[] pvfm = doPos ? new int[vc].Set(-1) : null;

            var ha = new double[maxFaceVertexCount];
            int nfc = 0, pfc = 0, nvic = 0, pvic = 0, nvc = 0, pvc = 0;

            for (int fvi = fia[0], fi = 0; fi < faceCount; fi++)
            {
                int nc = 0, pc = 0, zc = 0, fve = fia[fi + 1], fvc = fve - fvi;
                for (int fs = 0; fs < fvc; fs++)
                {
                    double height = ha[fs] = vertexHeights[via[fvi + fs]];
                    if (height < -eps)
                    {
                        ++nc; continue;
                    }
                    if (height > +eps)
                    {
                        ++pc; continue;
                    }
                    ++zc;
                }
                if (nc == 0)
                {
                    if (doPos)
                    {
                        pffm[fi] = pfc++; pvic += fvc;
                        for (int fs = 0; fs < fvc; fs++)
                        {
                            pvfm.ForwardMapAdd(via[fvi + fs], ref pvc);
                        }
                    }
                }
                else if (pc == 0)
                {
                    if (doNeg)
                    {
                        nffm[fi] = nfc++; nvic += fvc;
                        for (int fs = 0; fs < fvc; fs++)
                        {
                            nvfm.ForwardMapAdd(via[fvi + fs], ref nvc);
                        }
                    }
                }
                else
                {
                    if (zc > 2)
                    {
                        Report.Warn("non-convex polygon encountered");
                    }
                    var nfvl = new List <FaceVertex>(nc + 2);
                    var pfvl = new List <FaceVertex>(pc + 2);

                    int sb = ha[0] > eps ? 1 : (ha[0] < -eps ? -1 : 0), vib = via[fvi];
                    int i0 = 0, s0 = sb, vi0 = vib;
                    if (doNeg && sb <= 0)
                    {
                        nfvl.Add(new FaceVertex(nvfm.ForwardMapAdd(vib, ref nvc), 0));
                    }
                    if (doPos && sb >= 0)
                    {
                        pfvl.Add(new FaceVertex(pvfm.ForwardMapAdd(vib, ref pvc), 0));
                    }
                    for (int i1 = 1; i1 < fvc; i0 = i1++)
                    {
                        int s1 = ha[i1] > eps ? 1 : (ha[i1] < -eps ? -1 : 0), vi1 = via[fvi + i1];
                        if (s0 != 0 && s1 != 0 && s0 != s1)
                        {
                            double t   = ha[i0] / (ha[i0] - ha[i1]);
                            var    key = Line1i.CreateSorted(vi0, vi1);
                            (int, int, int)v;
                            if (!lineMap.TryGetValue(key, out v))
                            {
                                v = lineMap[key] = (nvc++, pvc++, m_spl.Count);
                                m_spl.Add(new SplitPoint(t, vi0, vi1));
                            }
                            if (doNeg)
                            {
                                m_nvl.Add(new Vertex(v.Item1, v.Item3, t, i0));
                                nfvl.Add(new FaceVertex(v.Item1, -m_nvl.Count));
                            }
                            if (doPos)
                            {
                                m_pvl.Add(new Vertex(v.Item2, v.Item3, t, i0));
                                pfvl.Add(new FaceVertex(v.Item2, -m_pvl.Count));
                            }
                        }
                        if (doNeg && s1 <= 0)
                        {
                            nfvl.Add(new FaceVertex(nvfm.ForwardMapAdd(vi1, ref nvc), i1));
                        }
                        if (doPos && s1 >= 0)
                        {
                            pfvl.Add(new FaceVertex(pvfm.ForwardMapAdd(vi1, ref pvc), i1));
                        }
                        vi0 = vi1; s0 = s1;
                    }
                    if (s0 != 0 && sb != 0 && s0 != sb)
                    {
                        double t   = ha[i0] / (ha[i0] - ha[0]);
                        var    key = Line1i.CreateSorted(vi0, vib);
                        (int, int, int)v;
                        if (!lineMap.TryGetValue(key, out v))
                        {
                            v = lineMap[key] = (nvc++, pvc++, m_spl.Count);
                            m_spl.Add(new SplitPoint(t, vi0, vib));
                        }
                        if (doNeg)
                        {
                            m_nvl.Add(new Vertex(v.Item1, v.Item3, t, i0));
                            nfvl.Add(new FaceVertex(v.Item1, -m_nvl.Count));
                        }
                        if (doPos)
                        {
                            m_pvl.Add(new Vertex(v.Item2, v.Item3, t, i0));
                            pfvl.Add(new FaceVertex(v.Item2, -m_pvl.Count));
                        }
                    }
                    if (doNeg && nfvl.Count > 2)
                    {
                        m_nfl.Add(new Face(fi, nfvl)); nvic += nfvl.Count;
                    }
                    if (doPos && pfvl.Count > 2)
                    {
                        m_pfl.Add(new Face(fi, pfvl)); pvic += pfvl.Count;
                    }
                }
                fvi = fve;
            }

            if (doNeg && (nfc > 0 || m_nfl.Count > 0))
            {
                CalculateIndices(fia, faceCount, via, nfc, nvic, nvc, nffm, m_nfl, nvfm,
                                 out m_nfia, out m_nvia, out m_nfbm, out m_nvbm);
            }
            if (doPos && (pfc > 0 || m_pfl.Count > 0))
            {
                CalculateIndices(fia, faceCount, via, pfc, pvic, pvc, pffm, m_pfl, pvfm,
                                 out m_pfia, out m_pvia, out m_pfbm, out m_pvbm);
            }
        }
Esempio n. 9
0
        /// <summary>
        /// A splitter can split a vertex-indexed triangle set, based on the
        /// supplied array of vertexHeights, which indicate for each vertex
        /// vi if it belongs to the negative split side (vertexHeights[vi]
        /// &lt; 0.0) or positive split side (vertexHeights[vi] &gt;= 0.0).
        /// </summary>
        public TriangleSplitter(int[] indices, double[] vertexHeights, double eps,
                                SplitterOptions options)
        {
            m_negativeIndices = null;
            m_positiveIndices = null;

            bool doNeg = (options & SplitterOptions.Negative) != 0;
            bool doPos = (options & SplitterOptions.Positive) != 0;

            if (doPos && vertexHeights.All(h => h >= -eps))
            {
                m_positiveIndices           = indices;
                m_positiveVertexBackwardMap = null; // flag: move input to positive
                return;
            }
            if (doNeg && vertexHeights.All(h => h <= eps))
            {
                m_negativeIndices           = indices;
                m_negativeVertexBackwardMap = null; // flag: move input to negative
                return;
            }

            var lineMap         = new Dictionary <Line1i, Line1i>();
            var negTriangleList = doNeg ? new List <(int, Triangle1i)>() : null;
            var posTriangleList = doPos ? new List <(int, Triangle1i)>() : null;

            m_negVertexMap = doNeg ? new Dictionary <int, Line1iPoint>() : null;
            m_posVertexMap = doPos ? new Dictionary <int, Line1iPoint>() : null;

            int tc = indices.Length / 3;

            int ntc = 0;
            int ptc = 0;

            int nvc = 0;
            int pvc = 0;

            int[] negTriangleForwardMap = doNeg ? new int[tc].Set(-1) : null;
            int[] posTriangleForwardMap = doPos ? new int[tc].Set(-1) : null;

            int[] negVertexForwardMap = doNeg ? new int[vertexHeights.Length].Set(-1) : null;
            int[] posVertexForwardMap = doPos ? new int[vertexHeights.Length].Set(-1) : null;

            var ia         = new int[3];
            var ha         = new double[3];
            var negIndices = new List <int>(4);
            var posIndices = new List <int>(4);

            for (int ti = 0; ti < tc; ti++)
            {
                int nc = 0, pc = 0;
                int tvi = 3 * ti;

                for (int ts = 0; ts < 3; ts++)
                {
                    int vi = indices[tvi + ts];
                    ia[ts] = vi;
                    double height = ha[ts] = vertexHeights[vi];
                    if (height < -eps)
                    {
                        ++nc; continue;
                    }
                    if (height > +eps)
                    {
                        ++pc; continue;
                    }
                }

                if (nc == 0)
                {
                    if (doPos)
                    {
                        posTriangleForwardMap[ti] = ptc++;
                        foreach (var vi in ia)
                        {
                            posVertexForwardMap.ForwardMapAdd(vi, ref pvc);
                        }
                    }
                }
                else if (pc == 0)
                {
                    if (doNeg)
                    {
                        negTriangleForwardMap[ti] = ntc++;
                        foreach (var vi in ia)
                        {
                            negVertexForwardMap.ForwardMapAdd(vi, ref nvc);
                        }
                    }
                }
                else
                {
                    int sb = ha[0] > eps ? 1 : (ha[0] < -eps ? -1 : 0);

                    int vi = ia[0];
                    if (doNeg && sb <= 0)
                    {
                        negIndices.Add(negVertexForwardMap.ForwardMapAdd(vi, ref nvc));
                    }
                    if (doPos && sb >= 0)
                    {
                        posIndices.Add(posVertexForwardMap.ForwardMapAdd(vi, ref pvc));
                    }

                    int i0 = 0, i1 = 1;
                    int s0 = sb;

                    while (i1 < 3)
                    {
                        int s1 = ha[i1] > eps ? 1 : (ha[i1] < -eps ? -1 : 0);

                        if (s0 != 0 && s1 != 0 && s0 != s1)
                        {
                            double t = ha[i0] / (ha[i0] - ha[i1]);
                            int    vi0 = ia[i0], vi1 = ia[i1];
                            var    key = Line1i.CreateSorted(vi0, vi1);
                            if (!lineMap.TryGetValue(key, out Line1i line))
                            {
                                var sp = new Line1iPoint(vi0, vi1, t);
                                if (doNeg)
                                {
                                    m_negVertexMap[line.I0 = nvc++] = sp;
                                }
                                if (doPos)
                                {
                                    m_posVertexMap[line.I1 = pvc++] = sp;
                                }
                                lineMap[key] = line;
                            }
                            if (doNeg)
                            {
                                negIndices.Add(line.I0);
                            }
                            if (doPos)
                            {
                                posIndices.Add(line.I1);
                            }
                        }

                        vi = ia[i1];
                        if (doNeg && s1 <= 0)
                        {
                            negIndices.Add(negVertexForwardMap.ForwardMapAdd(vi, ref nvc));
                        }
                        if (doPos && s1 >= 0)
                        {
                            posIndices.Add(posVertexForwardMap.ForwardMapAdd(vi, ref pvc));
                        }

                        i0 = i1++;  s0 = s1;
                    }
                    if (s0 != 0 && sb != 0 && s0 != sb)
                    {
                        double t = ha[i0] / (ha[i0] - ha[0]);
                        int    vi0 = ia[i0], vi1 = ia[0];
                        var    key = Line1i.CreateSorted(vi0, vi1);
                        if (!lineMap.TryGetValue(key, out Line1i line))
                        {
                            var sp = new Line1iPoint(vi0, vi1, t);
                            if (doNeg)
                            {
                                m_negVertexMap[line.I0 = nvc++] = sp;
                            }
                            if (doPos)
                            {
                                m_posVertexMap[line.I1 = pvc++] = sp;
                            }
                            lineMap[key] = line;
                        }
                        if (doNeg)
                        {
                            negIndices.Add(line.I0);
                        }
                        if (doPos)
                        {
                            posIndices.Add(line.I1);
                        }
                    }

                    // at this point we have lists of indices for the positive and
                    // negative triangles
                    if (doNeg && negIndices.Count > 2)
                    {
                        for (int i = 1; i < negIndices.Count - 1; i++)
                        {
                            negTriangleList.Add(
                                (ntc++, new Triangle1i(negIndices[0],
                                                       negIndices[i], negIndices[i + 1])));
                        }
                    }
                    if (doPos && posIndices.Count > 2)
                    {
                        for (int i = 1; i < posIndices.Count - 1; i++)
                        {
                            posTriangleList.Add(
                                (ptc++, new Triangle1i(posIndices[0],
                                                       posIndices[i], posIndices[i + 1])));
                        }
                    }
                    negIndices.Clear(); posIndices.Clear();
                }
            }

            if (doNeg && ntc > 0)
            {
                m_negativeIndices = CalculateIndices(indices, ntc, negTriangleForwardMap,
                                                     negTriangleList, negVertexForwardMap);
                m_negativeVertexBackwardMap = negVertexForwardMap.CreateBackMap(nvc);
            }
            if (doPos && ptc > 0)
            {
                m_positiveIndices = CalculateIndices(indices, ptc, posTriangleForwardMap,
                                                     posTriangleList, posVertexForwardMap);
                m_positiveVertexBackwardMap = posVertexForwardMap.CreateBackMap(pvc);
            }
        }
        /// <summary>
        /// Main processing method
        /// </summary>
        /// <returns>0 if no error, error code if an error</returns>
        public static int Main()
        {
            var commandLineParser = new clsParseCommandLine();

            // Initialize the options
            mInputFilePath       = string.Empty;
            mOutputDirectoryName = string.Empty;
            mParameterFilePath   = string.Empty;
            mRecurseDirectories  = false;
            mMaxLevelsToRecurse  = 0;
            mLogMessagesToFile   = false;

            var options = new SplitterOptions();

            try
            {
                var proceed = commandLineParser.ParseCommandLine() && SetOptionsUsingCommandLineParameters(commandLineParser, options);

                if (!proceed || commandLineParser.NeedToShowHelp || commandLineParser.ParameterCount + commandLineParser.NonSwitchParameterCount == 0 || mInputFilePath.Length == 0)
                {
                    ShowProgramHelp();
                    return(-1);
                }

                // Note: mSplitCount and mSplitCount will be overridden if mParameterFilePath points to a valid parameter file that has these settings defined
                var fastaFileSplitter = new clsFastaFileSplitter(options)
                {
                    LogMessagesToFile = mLogMessagesToFile
                };

                RegisterEvents(fastaFileSplitter);
                fastaFileSplitter.ProgressReset += ProgressReset;

                int returnCode;
                if (mRecurseDirectories)
                {
                    if (fastaFileSplitter.ProcessFilesAndRecurseDirectories(mInputFilePath, mOutputDirectoryName, mOutputDirectoryAlternatePath, mRecreateDirectoryHierarchyInAlternatePath, mParameterFilePath, mMaxLevelsToRecurse))
                    {
                        returnCode = 0;
                    }
                    else
                    {
                        if (fastaFileSplitter.ErrorCode == ProcessFilesBase.ProcessFilesErrorCodes.NoError)
                        {
                            returnCode = -1;
                        }
                        else
                        {
                            returnCode = (int)fastaFileSplitter.ErrorCode;
                        }
                    }
                }
                else if (fastaFileSplitter.ProcessFilesWildcard(mInputFilePath, mOutputDirectoryName, mParameterFilePath))
                {
                    returnCode = 0;
                }
                else
                {
                    if (fastaFileSplitter.ErrorCode != ProcessFilesBase.ProcessFilesErrorCodes.NoError)
                    {
                        Console.WriteLine("Error while processing: " + fastaFileSplitter.GetErrorMessage());
                    }

                    returnCode = (int)fastaFileSplitter.ErrorCode;
                }

                DisplayProgressPercent(mLastProgressReportValue, true);
                return(returnCode);
            }
            catch (Exception ex)
            {
                ConsoleMsgUtils.ShowError("Error occurred in modMain->Main", ex);
                return(-1);
            }
        }
        private static bool SetOptionsUsingCommandLineParameters(clsParseCommandLine commandLineParser, SplitterOptions options)
        {
            // Returns True if no problems; otherwise, returns false

            var validParameters = new List <string> {
                "I", "N", "MB", "O", "P", "S", "A", "R", "L"
            };

            try
            {
                // Make sure no invalid parameters are present
                if (commandLineParser.InvalidParametersPresent(validParameters))
                {
                    ConsoleMsgUtils.ShowErrors("Invalid command line parameters", (from item in commandLineParser.InvalidParameters(validParameters)
                                                                                   select("/" + item)).ToList());
                    return(false);
                }

                // Query commandLineParser to see if various parameters are present
                if (commandLineParser.RetrieveValueForParameter("I", out var inputFilePath))
                {
                    mInputFilePath = inputFilePath;
                }
                else if (commandLineParser.NonSwitchParameterCount > 0)
                {
                    mInputFilePath = commandLineParser.RetrieveNonSwitchParameter(0);
                }

                if (commandLineParser.RetrieveValueForParameter("N", out var splitCount))
                {
                    if (int.TryParse(splitCount, out var value))
                    {
                        options.SplitCount = value;
                    }
                    else
                    {
                        ConsoleMsgUtils.ShowError(
                            "Error parsing number from the /N parameter; " +
                            "for example, use /N:{0} to specify the file be split into {0} parts",
                            SplitterOptions.DEFAULT_SPLIT_COUNT);

                        options.SplitCount = SplitterOptions.DEFAULT_SPLIT_COUNT;
                    }
                }

                if (commandLineParser.RetrieveValueForParameter("MB", out var targetSizeMB))
                {
                    options.UseTargetFileSize = true;

                    if (int.TryParse(targetSizeMB, out var value))
                    {
                        options.TargetFastaFileSizeMB = value;
                    }
                    else
                    {
                        ConsoleMsgUtils.ShowError(
                            "Error parsing number from the /MB parameter; " +
                            "for example, use /MB:{0} to specify the file be split into files that are each {0} MB in size",
                            SplitterOptions.DEFAULT_TARGET_FILE_SIZE_MB);

                        options.TargetFastaFileSizeMB = SplitterOptions.DEFAULT_TARGET_FILE_SIZE_MB;
                    }
                }

                if (commandLineParser.RetrieveValueForParameter("O", out var outputDirectory))
                {
                    mOutputDirectoryName = outputDirectory;
                }

                if (commandLineParser.RetrieveValueForParameter("P", out var parameterFile))
                {
                    mParameterFilePath = parameterFile;
                }

                if (commandLineParser.RetrieveValueForParameter("S", out var recurseSubdirectories))
                {
                    mRecurseDirectories = true;
                    if (!int.TryParse(recurseSubdirectories, out mMaxLevelsToRecurse))
                    {
                        mMaxLevelsToRecurse = 0;
                    }
                }

                if (commandLineParser.RetrieveValueForParameter("A", out var alternateOutputDirectory))
                {
                    mOutputDirectoryAlternatePath = alternateOutputDirectory;
                }

                if (commandLineParser.IsParameterPresent("R"))
                {
                    mRecreateDirectoryHierarchyInAlternatePath = true;
                }

                if (commandLineParser.IsParameterPresent("L"))
                {
                    mLogMessagesToFile = true;
                }

                return(true);
            }
            catch (Exception ex)
            {
                ConsoleMsgUtils.ShowError("Error parsing the command line parameters", ex);
                return(false);
            }
        }
Esempio n. 12
0
 public static KeyValuePair <string, TValue> OptionalMap <TValue>(SplitterOptions options, string key, string value, Func <string, TValue> to)
 {
     return(options.MapTrimResultsFlag
         ? new KeyValuePair <string, TValue>(options.KeyTrimFunc(key), to(options.ValueTrimFunc(value)))
         : new KeyValuePair <string, TValue>(key, to(value)));
 }