< Summary

Line coverage
99%
Covered lines: 543
Uncovered lines: 1
Coverable lines: 544
Total lines: 1395
Line coverage: 99.8%
Branch coverage
99%
Covered branches: 521
Total branches: 522
Branch coverage: 99.8%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
MoveNextSkipEmpty(...)75%4475%
MoveNextSkipEmpty(...)75%4475%
GetNextValue(...)100%11100%
GetNextValue(...)100%11100%
FloatParse(...)100%11100%
IntParse(...)100%11100%
LongParse(...)100%11100%
FromStream(...)100%386386100%
ParseTriplet(...)100%3838100%
ParseCurveIndex(...)100%88100%
ParseCurveIndex(...)100%88100%
ParseCurveIndex(...)100%66100%
ParseCurveIndex(...)100%66100%
ParseFreeFormType(...)100%1818100%
ParseFreeFormType(...)100%1818100%
ParseSurfaceConnection(...)100%2020100%
ParseSurfaceConnection(...)100%2020100%
ParseGroupName(...)100%1010100%
ParseGroupName(...)100%1010100%
ParseApproximationTechnique(...)100%3232100%
ParseApproximationTechnique(...)100%3232100%

File(s)

https://raw.githubusercontent.com/JeremyAnsel/JeremyAnsel.Media.WavefrontObj/636b700b450d7d3262bf9218a7cc67966be4ced8/JeremyAnsel.Media.WavefrontObj/JeremyAnsel.Media.WavefrontObj/ObjFileReader9.cs

#LineLine coverage
 1// <copyright file="ObjFileReader9.cs" company="Jérémy Ansel">
 2// Copyright (c) 2017, 2019 Jérémy Ansel
 3// </copyright>
 4// <license>
 5// Licensed under the MIT license. See LICENSE.txt
 6// </license>
 7
 8#if NET6_0_OR_GREATER
 9
 10using System.Diagnostics.CodeAnalysis;
 11using System.Globalization;
 12using System.Text;
 13
 14#if NET9_0_OR_GREATER
 15using SpanSplitEnumerator = System.MemoryExtensions.SpanSplitEnumerator<char>;
 16#else
 17using SpanSplitEnumerator = Polyfills.Polyfill.SpanSplitEnumerator<char>;
 18#endif
 19
 20namespace JeremyAnsel.Media.WavefrontObj
 21{
 22    internal static class ObjFileReader9
 23    {
 24        private static void MoveNextSkipEmpty(ref SpanSplitEnumerator values)
 25        {
 675326            while (values.MoveNext())
 27            {
 675328                if (values.Current.Start.Value != values.Current.End.Value)
 29                {
 672630                    return;
 31                }
 32            }
 033        }
 34
 35        private static ReadOnlySpan<char> GetNextValue(ref ReadOnlySpan<char> currentLine, ref SpanSplitEnumerator value
 36        {
 458737            MoveNextSkipEmpty(ref values);
 458738            return currentLine[values.Current];
 39        }
 40
 41        private static float FloatParse(ReadOnlySpan<char> s)
 42        {
 297343            return float.Parse(s, NumberStyles.Float, CultureInfo.InvariantCulture);
 44        }
 45
 46        private static int IntParse(ReadOnlySpan<char> s)
 47        {
 110448            return int.Parse(s, NumberStyles.Integer, CultureInfo.InvariantCulture);
 49        }
 50
 51        private static long LongParse(ReadOnlySpan<char> s)
 52        {
 1853            return long.Parse(s, NumberStyles.Integer, CultureInfo.InvariantCulture);
 54        }
 55
 56        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 57        public static ObjFile FromStream(Stream? stream, ObjFileReaderSettings settings)
 58        {
 84659            if (stream == null)
 60            {
 361                throw new ArgumentNullException(nameof(stream));
 62            }
 63
 84364            var obj = new ObjFile();
 84365            var context = new ObjFileReaderContext(obj, settings);
 84366            var lineReader = new LineReader9();
 67
 84368            int valueBufferSize = 16;
 84369            Span<char> valueBuffer = stackalloc char[valueBufferSize];
 70
 546071            foreach (var currentLineString in lineReader.Read9(stream))
 72            {
 213973                ReadOnlySpan<char> currentLine = currentLineString.Buffer.AsSpan()[..currentLineString.Length];
 74
 213975                int valuesCount = 0;
 76
 1922477                foreach (Range range in currentLine.SplitAny(LineReader9.LineSeparators))
 78                {
 747379                    if (currentLine[range].Length == 0)
 80                    {
 81                        continue;
 82                    }
 83
 742284                    valuesCount++;
 85                }
 86
 213987                SpanSplitEnumerator values = currentLine.SplitAny(LineReader9.LineSeparators);
 88
 213989                MoveNextSkipEmpty(ref values);
 90
 213991                if (values.Current.End.Value - values.Current.Start.Value > valueBufferSize)
 92                {
 93                    continue;
 94                }
 95
 213696                ReadOnlySpan<char> value0 = currentLine[values.Current];
 213697                int value0Length = value0.ToLowerInvariant(valueBuffer);
 98
 99                //if (value0Length == -1)
 100                //{
 101                //    throw new InvalidDataException("the buffer is too small");
 102                //}
 103
 2136104                switch (valueBuffer[..value0Length])
 105                {
 106                    case "v":
 107                        {
 504108                            if (valuesCount < 4)
 109                            {
 9110                                throw new InvalidDataException("A v statement must specify at least 3 values.");
 111                            }
 112
 495113                            float x = FloatParse(GetNextValue(ref currentLine, ref values));
 495114                            float y = FloatParse(GetNextValue(ref currentLine, ref values));
 495115                            float z = FloatParse(GetNextValue(ref currentLine, ref values));
 495116                            float w = 1.0f;
 495117                            bool hasColor = false;
 495118                            float r = 0.0f;
 495119                            float g = 0.0f;
 495120                            float b = 0.0f;
 495121                            float a = 1.0f;
 122
 495123                            if (valuesCount == 4 || valuesCount == 5)
 124                            {
 483125                                if (valuesCount == 5)
 126                                {
 3127                                    w = FloatParse(GetNextValue(ref currentLine, ref values));
 128                                }
 129                            }
 12130                            else if (valuesCount == 7 || valuesCount == 8)
 131                            {
 6132                                hasColor = true;
 6133                                r = FloatParse(GetNextValue(ref currentLine, ref values));
 6134                                g = FloatParse(GetNextValue(ref currentLine, ref values));
 6135                                b = FloatParse(GetNextValue(ref currentLine, ref values));
 136
 6137                                if (valuesCount == 8)
 138                                {
 3139                                    a = FloatParse(GetNextValue(ref currentLine, ref values));
 140                                }
 141                            }
 142                            else
 143                            {
 6144                                throw new InvalidDataException("A v statement has too many values.");
 145                            }
 146
 489147                            var v = new ObjVertex();
 489148                            v.Position = new ObjVector4(x, y, z, w);
 149
 489150                            if (hasColor)
 151                            {
 6152                                v.Color = new ObjVector4(r, g, b, a);
 153                            }
 154
 489155                            obj.Vertices.Add(v);
 489156                            break;
 157                        }
 158
 159                    case "vp":
 160                        {
 180161                            if (valuesCount < 2)
 162                            {
 3163                                throw new InvalidDataException("A vp statement must specify at least 1 value.");
 164                            }
 165
 177166                            var v = new ObjVector3();
 177167                            v.X = FloatParse(GetNextValue(ref currentLine, ref values));
 168
 177169                            if (valuesCount == 2)
 170                            {
 3171                                v.Y = 0.0f;
 3172                                v.Z = 1.0f;
 173                            }
 174174                            else if (valuesCount == 3)
 175                            {
 3176                                v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 3177                                v.Z = 1.0f;
 178                            }
 171179                            else if (valuesCount == 4)
 180                            {
 168181                                v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 168182                                v.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 183                            }
 184                            else
 185                            {
 3186                                throw new InvalidDataException("A vp statement has too many values.");
 187                            }
 188
 174189                            obj.ParameterSpaceVertices.Add(v);
 174190                            break;
 191                        }
 192
 193                    case "vn":
 194                        {
 36195                            if (valuesCount < 4)
 196                            {
 9197                                throw new InvalidDataException("A vn statement must specify 3 values.");
 198                            }
 199
 27200                            if (valuesCount != 4)
 201                            {
 3202                                throw new InvalidDataException("A vn statement has too many values.");
 203                            }
 204
 24205                            var v = new ObjVector3();
 24206                            v.X = FloatParse(GetNextValue(ref currentLine, ref values));
 24207                            v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 24208                            v.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 209
 24210                            obj.VertexNormals.Add(v);
 24211                            break;
 212                        }
 213
 214                    case "vt":
 215                        {
 33216                            if (valuesCount < 2)
 217                            {
 3218                                throw new InvalidDataException("A vt statement must specify at least 1 value.");
 219                            }
 220
 30221                            var v = new ObjVector3();
 30222                            v.X = FloatParse(GetNextValue(ref currentLine, ref values));
 223
 30224                            if (valuesCount == 2)
 225                            {
 21226                                v.Y = 0.0f;
 21227                                v.Z = 0.0f;
 228                            }
 9229                            else if (valuesCount == 3)
 230                            {
 3231                                v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 3232                                v.Z = 0.0f;
 233                            }
 6234                            else if (valuesCount == 4)
 235                            {
 3236                                v.Y = FloatParse(GetNextValue(ref currentLine, ref values));
 3237                                v.Z = FloatParse(GetNextValue(ref currentLine, ref values));
 238                            }
 239                            else
 240                            {
 3241                                throw new InvalidDataException("A vt statement has too many values.");
 242                            }
 243
 27244                            obj.TextureVertices.Add(v);
 27245                            break;
 246                        }
 247
 248                    case "cstype":
 45249                        ParseFreeFormType(context, ref value0, ref currentLine, ref values, valuesCount);
 30250                        break;
 251
 252                    case "deg":
 21253                        if (valuesCount < 2)
 254                        {
 3255                            throw new InvalidDataException("A deg statement must specify at least 1 value.");
 256                        }
 257
 18258                        if (valuesCount == 2)
 259                        {
 3260                            context.DegreeU = IntParse(GetNextValue(ref currentLine, ref values));
 3261                            context.DegreeV = 0;
 262                        }
 15263                        else if (valuesCount == 3)
 264                        {
 12265                            context.DegreeU = IntParse(GetNextValue(ref currentLine, ref values));
 12266                            context.DegreeV = IntParse(GetNextValue(ref currentLine, ref values));
 267                        }
 268                        else
 269                        {
 3270                            throw new InvalidDataException("A deg statement has too many values.");
 271                        }
 272
 273                        break;
 274
 275                    case "bmat":
 276                        {
 15277                            if (valuesCount < 2)
 278                            {
 3279                                throw new InvalidDataException("A bmat statement must specify a direction.");
 280                            }
 281
 282                            int d;
 12283                            var value1 = GetNextValue(ref currentLine, ref values);
 284
 12285                            if (value1.Equals("u", StringComparison.OrdinalIgnoreCase))
 286                            {
 6287                                d = 1;
 288                            }
 6289                            else if (value1.Equals("v", StringComparison.OrdinalIgnoreCase))
 290                            {
 3291                                d = 2;
 292                            }
 293                            else
 294                            {
 3295                                throw new InvalidDataException("A bmat statement has an unknown direction.");
 296                            }
 297
 9298                            int count = (context.DegreeU + 1) * (context.DegreeV + 1);
 299
 9300                            if (valuesCount != count + 2)
 301                            {
 3302                                throw new InvalidDataException("A bmat statement has too many or too few values.");
 303                            }
 304
 6305                            var matrix = new float[count];
 306
 156307                            for (int i = 0; i < count; i++)
 308                            {
 72309                                matrix[i] = FloatParse(GetNextValue(ref currentLine, ref values));
 310                            }
 311
 312                            switch (d)
 313                            {
 314                                case 1:
 3315                                    context.BasicMatrixU = matrix;
 3316                                    break;
 317
 318                                case 2:
 3319                                    context.BasicMatrixV = matrix;
 3320                                    break;
 321                            }
 322
 323                            break;
 324                        }
 325
 326                    case "step":
 12327                        if (valuesCount < 2)
 328                        {
 3329                            throw new InvalidDataException("A step statement must specify at least 1 value.");
 330                        }
 331
 9332                        if (valuesCount == 2)
 333                        {
 3334                            context.StepU = FloatParse(GetNextValue(ref currentLine, ref values));
 3335                            context.StepV = 1.0f;
 336                        }
 6337                        else if (valuesCount == 3)
 338                        {
 3339                            context.StepU = FloatParse(GetNextValue(ref currentLine, ref values));
 3340                            context.StepV = FloatParse(GetNextValue(ref currentLine, ref values));
 341                        }
 342                        else
 343                        {
 3344                            throw new InvalidDataException("A step statement has too many values.");
 345                        }
 346
 347                        break;
 348
 349                    case "p":
 350                        {
 102351                            if (valuesCount < 2)
 352                            {
 3353                                throw new InvalidDataException("A p statement must specify at least 1 value.");
 354                            }
 355
 99356                            var point = new ObjPoint();
 357
 354358                            for (int i = 1; i < valuesCount; i++)
 359                            {
 105360                                point.Vertices.Add(ParseTriplet(obj, GetNextValue(ref currentLine, ref values)));
 361                            }
 362
 72363                            context.ApplyAttributesToElement(point);
 72364                            context.ApplyAttributesToPolygonalElement(point);
 365
 72366                            obj.Points.Add(point);
 367
 288368                            foreach (var group in context.GetCurrentGroups())
 369                            {
 72370                                group.Points.Add(point);
 371                            }
 372
 373                            break;
 374                        }
 375
 376                    case "l":
 377                        {
 12378                            if (valuesCount < 3)
 379                            {
 6380                                throw new InvalidDataException("A l statement must specify at least 2 values.");
 381                            }
 382
 6383                            var line = new ObjLine();
 384
 48385                            for (int i = 1; i < valuesCount; i++)
 386                            {
 18387                                line.Vertices.Add(ParseTriplet(obj, GetNextValue(ref currentLine, ref values)));
 388                            }
 389
 6390                            context.ApplyAttributesToElement(line);
 6391                            context.ApplyAttributesToPolygonalElement(line);
 392
 6393                            obj.Lines.Add(line);
 394
 24395                            foreach (var group in context.GetCurrentGroups())
 396                            {
 6397                                group.Lines.Add(line);
 398                            }
 399
 400                            break;
 401                        }
 402
 403                    case "f":
 404                    case "fo":
 405                        {
 30406                            if (valuesCount < 4)
 407                            {
 18408                                throw new InvalidDataException("A f statement must specify at least 3 values.");
 409                            }
 410
 12411                            var face = new ObjFace();
 412
 144413                            for (int i = 1; i < valuesCount; i++)
 414                            {
 60415                                face.Vertices.Add(ParseTriplet(obj, GetNextValue(ref currentLine, ref values)));
 416                            }
 417
 12418                            context.ApplyAttributesToElement(face);
 12419                            context.ApplyAttributesToPolygonalElement(face);
 420
 12421                            obj.Faces.Add(face);
 422
 48423                            foreach (var group in context.GetCurrentGroups())
 424                            {
 12425                                group.Faces.Add(face);
 426                            }
 427
 428                            break;
 429                        }
 430
 431                    case "curv":
 432                        {
 135433                            if (valuesCount < 5)
 434                            {
 12435                                throw new InvalidDataException("A curv statement must specify at least 4 values.");
 436                            }
 437
 123438                            var curve = new ObjCurve();
 439
 123440                            curve.StartParameter = FloatParse(GetNextValue(ref currentLine, ref values));
 123441                            curve.EndParameter = FloatParse(GetNextValue(ref currentLine, ref values));
 442
 714443                            for (int i = 3; i < valuesCount; i++)
 444                            {
 243445                                int v = IntParse(GetNextValue(ref currentLine, ref values));
 446
 243447                                if (v == 0)
 448                                {
 3449                                    throw new InvalidDataException("A curv statement contains an invalid vertex index.")
 450                                }
 451
 240452                                if (v < 0)
 453                                {
 3454                                    v = obj.Vertices.Count + v + 1;
 455                                }
 456
 240457                                if (v <= 0 || v > obj.Vertices.Count)
 458                                {
 6459                                    throw new IndexOutOfRangeException();
 460                                }
 461
 234462                                curve.Vertices.Add(v);
 463                            }
 464
 114465                            context.ApplyAttributesToElement(curve);
 114466                            context.ApplyAttributesToFreeFormElement(curve);
 114467                            context.CurrentFreeFormElement = curve;
 468
 114469                            obj.Curves.Add(curve);
 470
 456471                            foreach (var group in context.GetCurrentGroups())
 472                            {
 114473                                group.Curves.Add(curve);
 474                            }
 475
 476                            break;
 477                        }
 478
 479                    case "curv2":
 480                        {
 183481                            if (valuesCount < 3)
 482                            {
 6483                                throw new InvalidDataException("A curv2 statement must specify at least 2 values.");
 484                            }
 485
 177486                            var curve = new ObjCurve2D();
 487
 1038488                            for (int i = 1; i < valuesCount; i++)
 489                            {
 351490                                int vp = IntParse(GetNextValue(ref currentLine, ref values));
 491
 351492                                if (vp == 0)
 493                                {
 3494                                    throw new InvalidDataException("A curv2 statement contains an invalid parameter spac
 495                                }
 496
 348497                                if (vp < 0)
 498                                {
 3499                                    vp = obj.ParameterSpaceVertices.Count + vp + 1;
 500                                }
 501
 348502                                if (vp <= 0 || vp > obj.ParameterSpaceVertices.Count)
 503                                {
 6504                                    throw new IndexOutOfRangeException();
 505                                }
 506
 342507                                curve.ParameterSpaceVertices.Add(vp);
 508                            }
 509
 168510                            context.ApplyAttributesToElement(curve);
 168511                            context.ApplyAttributesToFreeFormElement(curve);
 168512                            context.CurrentFreeFormElement = curve;
 513
 168514                            obj.Curves2D.Add(curve);
 515
 672516                            foreach (var group in context.GetCurrentGroups())
 517                            {
 168518                                group.Curves2D.Add(curve);
 519                            }
 520
 521                            break;
 522                        }
 523
 524                    case "surf":
 525                        {
 78526                            if (valuesCount < 6)
 527                            {
 18528                                throw new InvalidDataException("A surf statement must specify at least 5 values.");
 529                            }
 530
 60531                            var surface = new ObjSurface();
 532
 60533                            surface.StartParameterU = FloatParse(GetNextValue(ref currentLine, ref values));
 60534                            surface.EndParameterU = FloatParse(GetNextValue(ref currentLine, ref values));
 60535                            surface.StartParameterV = FloatParse(GetNextValue(ref currentLine, ref values));
 60536                            surface.EndParameterV = FloatParse(GetNextValue(ref currentLine, ref values));
 537
 252538                            for (int i = 5; i < valuesCount; i++)
 539                            {
 72540                                surface.Vertices.Add(ParseTriplet(obj, GetNextValue(ref currentLine, ref values)));
 541                            }
 542
 54543                            context.ApplyAttributesToElement(surface);
 54544                            context.ApplyAttributesToFreeFormElement(surface);
 54545                            context.CurrentFreeFormElement = surface;
 546
 54547                            obj.Surfaces.Add(surface);
 548
 216549                            foreach (var group in context.GetCurrentGroups())
 550                            {
 54551                                group.Surfaces.Add(surface);
 552                            }
 553
 554                            break;
 555                        }
 556
 557                    case "parm":
 558                        {
 21559                            if (context.CurrentFreeFormElement == null)
 560                            {
 561                                break;
 562                            }
 563
 18564                            if (valuesCount < 4)
 565                            {
 9566                                throw new InvalidDataException("A parm statement must specify at least 3 values.");
 567                            }
 568
 569                            List<float> parameters;
 9570                            var value1 = GetNextValue(ref currentLine, ref values);
 571
 9572                            if (value1.Equals("u", StringComparison.OrdinalIgnoreCase))
 573                            {
 3574                                parameters = context.CurrentFreeFormElement.ParametersU;
 575                            }
 6576                            else if (value1.Equals("v", StringComparison.OrdinalIgnoreCase))
 577                            {
 3578                                parameters = context.CurrentFreeFormElement.ParametersV;
 579                            }
 580                            else
 581                            {
 3582                                throw new InvalidDataException("A parm statement has an unknown direction.");
 583                            }
 584
 48585                            for (int i = 2; i < valuesCount; i++)
 586                            {
 18587                                parameters.Add(FloatParse(GetNextValue(ref currentLine, ref values)));
 588                            }
 589
 6590                            break;
 591                        }
 592
 593                    case "trim":
 30594                        if (context.CurrentFreeFormElement == null)
 595                        {
 596                            break;
 597                        }
 598
 27599                        ParseCurveIndex(context.CurrentFreeFormElement.OuterTrimmingCurves, obj, value0, ref currentLine
 3600                        break;
 601
 602                    case "hole":
 30603                        if (context.CurrentFreeFormElement == null)
 604                        {
 605                            break;
 606                        }
 607
 27608                        ParseCurveIndex(context.CurrentFreeFormElement.InnerTrimmingCurves, obj, value0, ref currentLine
 3609                        break;
 610
 611                    case "scrv":
 30612                        if (context.CurrentFreeFormElement == null)
 613                        {
 614                            break;
 615                        }
 616
 27617                        ParseCurveIndex(context.CurrentFreeFormElement.SequenceCurves, obj, value0, ref currentLine, ref
 3618                        break;
 619
 620                    case "sp":
 18621                        if (context.CurrentFreeFormElement == null)
 622                        {
 623                            break;
 624                        }
 625
 15626                        if (valuesCount < 2)
 627                        {
 3628                            throw new InvalidDataException("A sp statement must specify at least 1 value.");
 629                        }
 630
 36631                        for (int i = 1; i < valuesCount; i++)
 632                        {
 15633                            int vp = IntParse(GetNextValue(ref currentLine, ref values));
 634
 15635                            if (vp == 0)
 636                            {
 3637                                throw new InvalidDataException("A sp statement contains an invalid parameter space verte
 638                            }
 639
 12640                            if (vp < 0)
 641                            {
 3642                                vp = obj.ParameterSpaceVertices.Count + vp + 1;
 643                            }
 644
 12645                            if (vp <= 0 || vp > obj.ParameterSpaceVertices.Count)
 646                            {
 6647                                throw new IndexOutOfRangeException();
 648                            }
 649
 6650                            context.CurrentFreeFormElement.SpecialPoints.Add(vp);
 651                        }
 652
 3653                        break;
 654
 655                    case "end":
 18656                        context.CurrentFreeFormElement = null;
 18657                        break;
 658
 659                    case "con":
 66660                        ParseSurfaceConnection(obj, value0, ref currentLine, ref values, valuesCount);
 3661                        break;
 662
 663                    case "g":
 78664                        ParseGroupName(context, value0, ref currentLine, ref values, valuesCount);
 78665                        break;
 666
 667                    case "s":
 668                        {
 27669                            if (valuesCount < 2)
 670                            {
 3671                                throw new InvalidDataException("A s statement must specify a value.");
 672                            }
 673
 24674                            if (valuesCount != 2)
 675                            {
 3676                                throw new InvalidDataException("A s statement has too many values.");
 677                            }
 678
 21679                            var value1 = GetNextValue(ref currentLine, ref values);
 680
 21681                            if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 682                            {
 3683                                context.SmoothingGroupNumber = 0;
 684                            }
 685                            else
 686                            {
 18687                                context.SmoothingGroupNumber = LongParse(value1);
 688                            }
 689
 18690                            break;
 691                        }
 692
 693                    case "mg":
 694                        {
 30695                            if (valuesCount < 2)
 696                            {
 3697                                throw new InvalidDataException("A mg statement must specify a value.");
 698                            }
 699
 27700                            var value1 = GetNextValue(ref currentLine, ref values);
 701
 27702                            if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 703                            {
 3704                                context.MergingGroupNumber = 0;
 705                            }
 706                            else
 707                            {
 24708                                context.MergingGroupNumber = IntParse(value1);
 709                            }
 710
 27711                            if (context.MergingGroupNumber == 0)
 712                            {
 9713                                if (valuesCount > 3)
 714                                {
 3715                                    throw new InvalidDataException("A mg statement has too many values.");
 716                                }
 717                            }
 718                            else
 719                            {
 18720                                if (valuesCount != 3)
 721                                {
 6722                                    throw new InvalidDataException("A mg statement has too many or too few values.");
 723                                }
 724
 12725                                float res = FloatParse(GetNextValue(ref currentLine, ref values));
 726
 12727                                obj.MergingGroupResolutions[context.MergingGroupNumber] = res;
 728                            }
 729
 12730                            break;
 731                        }
 732
 733                    case "o":
 39734                        if (settings.HandleObjectNamesAsGroup)
 735                        {
 9736                            ParseGroupName(context, value0, ref currentLine, ref values, valuesCount);
 9737                            break;
 738                        }
 739
 30740                        if (valuesCount == 1)
 741                        {
 3742                            context.ObjectName = null;
 3743                            break;
 744                        }
 745
 27746                        if (valuesCount != 2)
 747                        {
 3748                            throw new InvalidDataException("A o statement has too many values.");
 749                        }
 750
 24751                        context.ObjectName = GetNextValue(ref currentLine, ref values).ToString();
 24752                        break;
 753
 754                    case "bevel":
 755                        {
 27756                            if (valuesCount < 2)
 757                            {
 3758                                throw new InvalidDataException("A bevel statement must specify a name.");
 759                            }
 760
 24761                            if (valuesCount != 2)
 762                            {
 3763                                throw new InvalidDataException("A bevel statement has too many values.");
 764                            }
 765
 21766                            var value1 = GetNextValue(ref currentLine, ref values);
 767
 21768                            if (value1.Equals("on", StringComparison.OrdinalIgnoreCase))
 769                            {
 15770                                context.IsBevelInterpolationEnabled = true;
 771                            }
 6772                            else if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 773                            {
 3774                                context.IsBevelInterpolationEnabled = false;
 775                            }
 776                            else
 777                            {
 3778                                throw new InvalidDataException("A bevel statement must specify on or off.");
 779                            }
 780
 781                            break;
 782                        }
 783
 784                    case "c_interp":
 785                        {
 27786                            if (valuesCount < 2)
 787                            {
 3788                                throw new InvalidDataException("A c_interp statement must specify a name.");
 789                            }
 790
 24791                            if (valuesCount != 2)
 792                            {
 3793                                throw new InvalidDataException("A c_interp statement has too many values.");
 794                            }
 795
 21796                            var value1 = GetNextValue(ref currentLine, ref values);
 797
 21798                            if (value1.Equals("on", StringComparison.OrdinalIgnoreCase))
 799                            {
 15800                                context.IsColorInterpolationEnabled = true;
 801                            }
 6802                            else if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 803                            {
 3804                                context.IsColorInterpolationEnabled = false;
 805                            }
 806                            else
 807                            {
 3808                                throw new InvalidDataException("A c_interp statement must specify on or off.");
 809                            }
 810
 811                            break;
 812                        }
 813
 814                    case "d_interp":
 815                        {
 27816                            if (valuesCount < 2)
 817                            {
 3818                                throw new InvalidDataException("A d_interp statement must specify a name.");
 819                            }
 820
 24821                            if (valuesCount != 2)
 822                            {
 3823                                throw new InvalidDataException("A d_interp statement has too many values.");
 824                            }
 825
 21826                            var value1 = GetNextValue(ref currentLine, ref values);
 827
 21828                            if (value1.Equals("on", StringComparison.OrdinalIgnoreCase))
 829                            {
 15830                                context.IsDissolveInterpolationEnabled = true;
 831                            }
 6832                            else if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 833                            {
 3834                                context.IsDissolveInterpolationEnabled = false;
 835                            }
 836                            else
 837                            {
 3838                                throw new InvalidDataException("A d_interp statement must specify on or off.");
 839                            }
 840
 841                            break;
 842                        }
 843
 844                    case "lod":
 30845                        if (valuesCount < 2)
 846                        {
 3847                            throw new InvalidDataException("A lod statement must specify a value.");
 848                        }
 849
 27850                        if (valuesCount != 2)
 851                        {
 3852                            throw new InvalidDataException("A lod statement has too many values.");
 853                        }
 854
 24855                        context.LevelOfDetail = IntParse(GetNextValue(ref currentLine, ref values));
 24856                        break;
 857
 858                    case "maplib":
 6859                        if (valuesCount < 2)
 860                        {
 3861                            throw new InvalidDataException("A maplib statement must specify a file name.");
 862                        }
 863
 18864                        for (int i = 1; i < valuesCount; i++)
 865                        {
 6866                            obj.MapLibraries.Add(GetNextValue(ref currentLine, ref values).ToString());
 867                        }
 868
 3869                        break;
 870
 871                    case "mtllib":
 872                        {
 9873                            if (valuesCount < 2)
 874                            {
 3875                                throw new InvalidDataException("A mtllib statement must specify a file name.");
 876                            }
 877
 6878                            var sb = new StringBuilder();
 879
 6880                            sb.Append(GetNextValue(ref currentLine, ref values));
 881
 36882                            for (int i = 2; i < valuesCount; i++)
 883                            {
 12884                                sb.Append(' ');
 12885                                sb.Append(GetNextValue(ref currentLine, ref values));
 886                            }
 887
 6888                            obj.MaterialLibraries.Add(sb.ToString());
 889
 6890                            break;
 891                        }
 892
 893                    case "usemap":
 894                        {
 33895                            if (valuesCount < 2)
 896                            {
 3897                                throw new InvalidDataException("A usemap statement must specify a value.");
 898                            }
 899
 30900                            if (valuesCount != 2)
 901                            {
 3902                                throw new InvalidDataException("A usemap statement has too many values.");
 903                            }
 904
 27905                            var value1 = GetNextValue(ref currentLine, ref values);
 906
 27907                            if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 908                            {
 3909                                context.MapName = null;
 910                            }
 911                            else
 912                            {
 24913                                context.MapName = value1.ToString();
 914                            }
 915
 24916                            break;
 917                        }
 918
 919                    case "usemtl":
 920                        {
 33921                            if (valuesCount < 2)
 922                            {
 3923                                throw new InvalidDataException("A usemtl statement must specify a value.");
 924                            }
 925
 30926                            var value1 = GetNextValue(ref currentLine, ref values);
 927
 30928                            if (value1.Equals("off", StringComparison.OrdinalIgnoreCase))
 929                            {
 6930                                if (valuesCount != 2)
 931                                {
 3932                                    throw new InvalidDataException("A usemtl statement has too many values.");
 933                                }
 934
 3935                                context.MaterialName = null;
 936                            }
 937                            else
 938                            {
 24939                                var sb = new StringBuilder();
 940
 24941                                sb.Append(value1);
 942
 60943                                for (int i = 2; i < valuesCount; i++)
 944                                {
 6945                                    sb.Append(' ');
 6946                                    sb.Append(GetNextValue(ref currentLine, ref values));
 947                                }
 948
 24949                                context.MaterialName = sb.ToString();
 950                            }
 951
 24952                            break;
 953                        }
 954
 955                    case "shadow_obj":
 956                        {
 18957                            if (valuesCount < 2)
 958                            {
 3959                                throw new InvalidDataException("A shadow_obj statement must specify a file name.");
 960                            }
 961
 15962                            var sb = new StringBuilder();
 963
 15964                            sb.Append(GetNextValue(ref currentLine, ref values));
 965
 36966                            for (int i = 2; i < valuesCount; i++)
 967                            {
 3968                                sb.Append(' ');
 3969                                sb.Append(GetNextValue(ref currentLine, ref values));
 970                            }
 971
 15972                            obj.ShadowObjectFileName = sb.ToString();
 15973                            break;
 974                        }
 975
 976                    case "trace_obj":
 977                        {
 12978                            if (valuesCount < 2)
 979                            {
 3980                                throw new InvalidDataException("A trace_obj statement must specify a file name.");
 981                            }
 982
 9983                            var sb = new StringBuilder();
 984
 9985                            sb.Append(GetNextValue(ref currentLine, ref values));
 986
 24987                            for (int i = 2; i < valuesCount; i++)
 988                            {
 3989                                sb.Append(' ');
 3990                                sb.Append(GetNextValue(ref currentLine, ref values));
 991                            }
 992
 9993                            obj.TraceObjectFileName = sb.ToString();
 9994                            break;
 995                        }
 996
 997                    case "ctech":
 54998                        context.CurveApproximationTechnique = ParseApproximationTechnique(value0, ref currentLine, ref v
 27999                        break;
 1000
 1001                    case "stech":
 661002                        context.SurfaceApproximationTechnique = ParseApproximationTechnique(value0, ref currentLine, ref
 301003                        break;
 1004
 1005                    case "bsp":
 1006                    case "bzp":
 1007                    case "cdc":
 1008                    case "cdp":
 1009                    case "res":
 151010                        throw new NotImplementedException(string.Concat(value0.ToString(), " statement have been replace
 1011                }
 1012            }
 1013
 3391014            obj.HeaderText = string.Join("\n", lineReader.HeaderTextLines.ToArray());
 1015
 3391016            return obj;
 1017        }
 1018
 1019        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 1020        private static ObjTriplet ParseTriplet(ObjFile obj, ReadOnlySpan<char> value)
 1021        {
 2551022            int valuesCount = 0;
 1023
 11221024            foreach (Range range in value.Split('/'))
 1025            {
 3061026                valuesCount++;
 1027            }
 1028
 2551029            var values = value.Split('/');
 1030
 2551031            if (valuesCount > 3)
 1032            {
 31033                throw new InvalidDataException("A triplet has too many values.");
 1034            }
 1035
 2521036            values.MoveNext();
 2521037            int v = value[values.Current].Length != 0 ? IntParse(value[values.Current]) : 0;
 1038
 2521039            if (v == 0)
 1040            {
 61041                throw new InvalidDataException("A triplet must specify a vertex index.");
 1042            }
 1043
 2461044            if (v < 0)
 1045            {
 61046                v = obj.Vertices.Count + v + 1;
 1047            }
 1048
 2461049            if (v <= 0 || v > obj.Vertices.Count)
 1050            {
 121051                throw new IndexOutOfRangeException();
 1052            }
 1053
 2341054            values.MoveNext();
 2341055            int vt = valuesCount > 1 && value[values.Current].Length != 0 ? IntParse(value[values.Current]) : 0;
 1056
 2341057            if (vt != 0)
 1058            {
 121059                if (vt < 0)
 1060                {
 31061                    vt = obj.TextureVertices.Count + vt + 1;
 1062                }
 1063
 121064                if (vt <= 0 || vt > obj.TextureVertices.Count)
 1065                {
 61066                    throw new IndexOutOfRangeException();
 1067                }
 1068            }
 1069
 2281070            values.MoveNext();
 2281071            int vn = valuesCount > 2 && value[values.Current].Length != 0 ? IntParse(value[values.Current]) : 0;
 1072
 2281073            if (vn != 0)
 1074            {
 121075                if (vn < 0)
 1076                {
 31077                    vn = obj.VertexNormals.Count + vn + 1;
 1078                }
 1079
 121080                if (vn <= 0 || vn > obj.VertexNormals.Count)
 1081                {
 61082                    throw new IndexOutOfRangeException();
 1083                }
 1084            }
 1085
 2221086            return new ObjTriplet(v, vt, vn);
 1087        }
 1088
 1089        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 1090        private static ObjCurveIndex ParseCurveIndex(ObjFile obj, ref ReadOnlySpan<char> currentLine, ref SpanSplitEnume
 1091        {
 871092            float start = FloatParse(GetNextValue(ref currentLine, ref values));
 871093            float end = FloatParse(GetNextValue(ref currentLine, ref values));
 871094            int curve2D = IntParse(GetNextValue(ref currentLine, ref values));
 1095
 871096            if (curve2D == 0)
 1097            {
 151098                throw new InvalidDataException("A curve index must specify an index.");
 1099            }
 1100
 721101            if (curve2D < 0)
 1102            {
 151103                curve2D = obj.Curves2D.Count + curve2D + 1;
 1104            }
 1105
 721106            if (curve2D <= 0 || curve2D > obj.Curves2D.Count)
 1107            {
 301108                throw new IndexOutOfRangeException();
 1109            }
 1110
 421111            return new ObjCurveIndex(start, end, curve2D);
 1112        }
 1113
 1114        private static void ParseCurveIndex(List<ObjCurveIndex> curves, ObjFile obj, ReadOnlySpan<char> value0, ref Read
 1115        {
 811116            if (valuesCount < 4)
 1117            {
 271118                throw new InvalidDataException(string.Concat("A ", value0.ToString(), " statement must specify at least 
 1119            }
 1120
 541121            if ((valuesCount - 1) % 3 != 0)
 1122            {
 181123                throw new InvalidDataException(string.Concat("A ", value0.ToString(), " statement has too many values.")
 1124            }
 1125
 1081126            for (int i = 1; i < valuesCount; i += 3)
 1127            {
 451128                curves.Add(ParseCurveIndex(obj, ref currentLine, ref values));
 1129            }
 91130        }
 1131
 1132        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 1133        private static void ParseFreeFormType(ObjFileReaderContext context, ref ReadOnlySpan<char> value0, ref ReadOnlyS
 1134        {
 451135            if (valuesCount < 2)
 1136            {
 31137                throw new InvalidDataException("A cstype statement must specify a value.");
 1138            }
 1139
 1140            string type;
 1141
 421142            if (valuesCount == 2)
 1143            {
 181144                context.IsRationalForm = false;
 181145                type = GetNextValue(ref currentLine, ref values).ToString();
 1146            }
 241147            else if (valuesCount == 3 && GetNextValue(ref currentLine, ref values).Equals("rat", StringComparison.Ordina
 1148            {
 181149                context.IsRationalForm = true;
 181150                type = GetNextValue(ref currentLine, ref values).ToString();
 1151            }
 1152            else
 1153            {
 61154                throw new InvalidDataException("A cstype statement has too many values.");
 1155            }
 1156
 361157            switch (type.ToLowerInvariant())
 1158            {
 1159                case "bmatrix":
 61160                    context.FreeFormType = ObjFreeFormType.BasisMatrix;
 61161                    break;
 1162
 1163                case "bezier":
 61164                    context.FreeFormType = ObjFreeFormType.Bezier;
 61165                    break;
 1166
 1167                case "bspline":
 61168                    context.FreeFormType = ObjFreeFormType.BSpline;
 61169                    break;
 1170
 1171                case "cardinal":
 61172                    context.FreeFormType = ObjFreeFormType.Cardinal;
 61173                    break;
 1174
 1175                case "taylor":
 61176                    context.FreeFormType = ObjFreeFormType.Taylor;
 61177                    break;
 1178
 1179                default:
 61180                    throw new InvalidDataException("A cstype statement has an unknown type.");
 1181            }
 1182        }
 1183
 1184        [SuppressMessage("Globalization", "CA1303:Ne pas passer de littéraux en paramètres localisés", Justification = "
 1185        private static void ParseSurfaceConnection(ObjFile obj, ReadOnlySpan<char> value0, ref ReadOnlySpan<char> curren
 1186        {
 661187            if (valuesCount < 9)
 1188            {
 241189                throw new InvalidDataException("A con statement must specify 8 values.");
 1190            }
 1191
 421192            if (valuesCount != 9)
 1193            {
 31194                throw new InvalidDataException("A con statement has too many values.");
 1195            }
 1196
 391197            int surface1 = IntParse(GetNextValue(ref currentLine, ref values));
 1198
 391199            if (surface1 == 0)
 1200            {
 31201                throw new InvalidDataException("A con statement must specify a surface index.");
 1202            }
 1203
 361204            if (surface1 < 0)
 1205            {
 31206                surface1 = obj.Surfaces.Count + surface1 + 1;
 1207            }
 1208
 361209            if (surface1 <= 0 || surface1 > obj.Surfaces.Count)
 1210            {
 61211                throw new IndexOutOfRangeException();
 1212            }
 1213
 301214            var curve1 = ParseCurveIndex(obj, ref currentLine, ref values);
 1215
 211216            int surface2 = IntParse(GetNextValue(ref currentLine, ref values));
 1217
 211218            if (surface2 == 0)
 1219            {
 31220                throw new InvalidDataException("A con statement must specify a surface index.");
 1221            }
 1222
 181223            if (surface2 < 0)
 1224            {
 31225                surface2 = obj.Surfaces.Count + surface2 + 1;
 1226            }
 1227
 181228            if (surface2 <= 0 || surface2 > obj.Surfaces.Count)
 1229            {
 61230                throw new IndexOutOfRangeException();
 1231            }
 1232
 121233            var curve2 = ParseCurveIndex(obj, ref currentLine, ref values);
 1234
 31235            var connection = new ObjSurfaceConnection
 31236            {
 31237                Surface1 = surface1,
 31238                Curve2D1 = curve1,
 31239                Surface2 = surface2,
 31240                Curve2D2 = curve2
 31241            };
 1242
 31243            obj.SurfaceConnections.Add(connection);
 31244        }
 1245
 1246        private static void ParseGroupName(ObjFileReaderContext context, ReadOnlySpan<char> value0, ref ReadOnlySpan<cha
 1247        {
 871248            context.GroupNames.Clear();
 1249
 871250            if (context.Settings.OnlyOneGroupNamePerLine)
 1251            {
 61252                var sb = new StringBuilder();
 1253
 61254                sb.Append(GetNextValue(ref currentLine, ref values));
 1255
 241256                for (int i = 2; i < valuesCount; i++)
 1257                {
 61258                    sb.Append(' ');
 61259                    sb.Append(GetNextValue(ref currentLine, ref values));
 1260                }
 1261
 1262
 61263                var name = sb.ToString();
 61264                if (!string.Equals(name, "default", StringComparison.OrdinalIgnoreCase))
 1265                {
 61266                    context.GroupNames.Add(name);
 1267                }
 1268            }
 1269            else
 1270            {
 3541271                for (int i = 1; i < valuesCount; i++)
 1272                {
 961273                    var name = GetNextValue(ref currentLine, ref values).ToString();
 1274
 961275                    if (!string.Equals(name, "default", StringComparison.OrdinalIgnoreCase))
 1276                    {
 721277                        context.GroupNames.Add(name);
 1278                    }
 1279                }
 1280            }
 1281
 871282            context.GetCurrentGroups();
 871283        }
 1284
 1285        private static ObjApproximationTechnique ParseApproximationTechnique(ReadOnlySpan<char> value0, ref ReadOnlySpan
 1286        {
 1287            ObjApproximationTechnique technique;
 1288
 1201289            if (valuesCount < 2)
 1290            {
 61291                throw new InvalidDataException(string.Concat("A ", value0.ToString(), " statement must specify a techniq
 1292            }
 1293
 1141294            string value1 = GetNextValue(ref currentLine, ref values).ToString().ToLowerInvariant();
 1295
 1296            switch (value1)
 1297            {
 1298                case "cparm":
 1299                    {
 91300                        if (valuesCount < 3)
 1301                        {
 31302                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparm statement must
 1303                        }
 1304
 61305                        if (valuesCount != 3)
 1306                        {
 31307                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparm statement has 
 1308                        }
 1309
 31310                        float res = FloatParse(GetNextValue(ref currentLine, ref values));
 31311                        technique = new ObjConstantParametricSubdivisionTechnique(res);
 31312                        break;
 1313                    }
 1314
 1315                case "cparma":
 1316                    {
 121317                        if (valuesCount < 4)
 1318                        {
 61319                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparma statement mus
 1320                        }
 1321
 61322                        if (valuesCount != 4)
 1323                        {
 31324                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparma statement has
 1325                        }
 1326
 31327                        float resU = FloatParse(GetNextValue(ref currentLine, ref values));
 31328                        float resV = FloatParse(GetNextValue(ref currentLine, ref values));
 31329                        technique = new ObjConstantParametricSubdivisionTechnique(resU, resV);
 31330                        break;
 1331                    }
 1332
 1333                case "cparmb":
 1334                    {
 91335                        if (valuesCount < 3)
 1336                        {
 31337                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparmb statement mus
 1338                        }
 1339
 61340                        if (valuesCount != 3)
 1341                        {
 31342                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cparmb statement has
 1343                        }
 1344
 31345                        float resU = FloatParse(GetNextValue(ref currentLine, ref values));
 31346                        technique = new ObjConstantParametricSubdivisionTechnique(resU);
 31347                        break;
 1348                    }
 1349
 1350                case "cspace":
 1351                    {
 541352                        if (valuesCount < 3)
 1353                        {
 61354                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cspace statement mus
 1355                        }
 1356
 481357                        if (valuesCount != 3)
 1358                        {
 61359                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " cspace statement has
 1360                        }
 1361
 421362                        float length = FloatParse(GetNextValue(ref currentLine, ref values));
 421363                        technique = new ObjConstantSpatialSubdivisionTechnique(length);
 421364                        break;
 1365                    }
 1366
 1367                case "curv":
 1368                    {
 241369                        if (valuesCount < 4)
 1370                        {
 121371                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " curv statement must 
 1372                        }
 1373
 121374                        if (valuesCount != 4)
 1375                        {
 61376                            throw new InvalidDataException(string.Concat("A ", value0.ToString(), " curv statement has t
 1377                        }
 1378
 61379                        float distance = FloatParse(GetNextValue(ref currentLine, ref values));
 61380                        float angle = FloatParse(GetNextValue(ref currentLine, ref values));
 61381                        technique = new ObjCurvatureDependentSubdivisionTechnique(distance, angle);
 61382                        break;
 1383                    }
 1384
 1385                default:
 61386                    throw new InvalidDataException(string.Concat("A ", value0.ToString(), " statement contains an unknow
 1387            }
 1388
 571389            return technique;
 1390        }
 1391    }
 1392}
 1393
 1394#endif
 1395

Methods/Properties

MoveNextSkipEmpty(System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&)
MoveNextSkipEmpty(Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&)
GetNextValue(System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&)
GetNextValue(System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&)
FloatParse(System.ReadOnlySpan`1<System.Char>)
IntParse(System.ReadOnlySpan`1<System.Char>)
LongParse(System.ReadOnlySpan`1<System.Char>)
FromStream(System.IO.Stream,JeremyAnsel.Media.WavefrontObj.ObjFileReaderSettings)
ParseTriplet(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>)
ParseCurveIndex(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&)
ParseCurveIndex(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&)
ParseCurveIndex(System.Collections.Generic.List`1<JeremyAnsel.Media.WavefrontObj.ObjCurveIndex>,JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseCurveIndex(System.Collections.Generic.List`1<JeremyAnsel.Media.WavefrontObj.ObjCurveIndex>,JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseFreeFormType(JeremyAnsel.Media.WavefrontObj.ObjFileReaderContext,System.ReadOnlySpan`1<System.Char>&,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseFreeFormType(JeremyAnsel.Media.WavefrontObj.ObjFileReaderContext,System.ReadOnlySpan`1<System.Char>&,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseSurfaceConnection(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseSurfaceConnection(JeremyAnsel.Media.WavefrontObj.ObjFile,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseGroupName(JeremyAnsel.Media.WavefrontObj.ObjFileReaderContext,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseGroupName(JeremyAnsel.Media.WavefrontObj.ObjFileReaderContext,System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseApproximationTechnique(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,System.MemoryExtensions/SpanSplitEnumerator`1<System.Char>&,System.Int32)
ParseApproximationTechnique(System.ReadOnlySpan`1<System.Char>,System.ReadOnlySpan`1<System.Char>&,Polyfills.Polyfill/SpanSplitEnumerator`1<System.Char>&,System.Int32)