internal static unsafe void ParseSkip(LineParserState state) { if (state.p >= state.end) { state.IsInvalid = true; return; } while (*state.p == ' ' && state.p < state.end) { state.p++; } if (state.p >= state.end || *state.p == '\n' || *state.p == '\r') { state.IsInvalid = true; return; } while (state.p < state.end) { switch ((char)*state.p) { case '\r': case '\n': case ' ': return; } state.p++; } }
internal static unsafe void ParseInt(LineParserState state, Action <int> setResult) { if (state.p >= state.end) { state.IsInvalid = true; return; } while (*state.p == ' ' && state.p < state.end) { state.p++; } if (state.p >= state.end || *state.p == '\n' || *state.p == '\r') { state.IsInvalid = true; return; } var minus = *state.p == ((byte)'-'); if (minus) { state.p++; } var x = 0; while (state.p < state.end) { switch ((char)*state.p) { case '0': x = x * 10; break; case '1': x = x * 10 + 1; break; case '2': x = x * 10 + 2; break; case '3': x = x * 10 + 3; break; case '4': x = x * 10 + 4; break; case '5': x = x * 10 + 5; break; case '6': x = x * 10 + 6; break; case '7': x = x * 10 + 7; break; case '8': x = x * 10 + 8; break; case '9': x = x * 10 + 9; break; case '\r': case '\n': case ' ': setResult(minus ? -x : x); return; default: { state.IsInvalid = true; return; } } state.p++; } setResult(minus ? -x : x); }
internal static unsafe bool SkipToNextLine(LineParserState state) { while (state.p < state.end && *state.p != '\n') { state.p++; } state.p++; return(state.p < state.end); }
internal static unsafe void ParseByte(LineParserState state, Action <byte> setResult) { if (state.p >= state.end) { state.IsInvalid = true; return; } while (*state.p == ' ' && state.p < state.end) { state.p++; } if (state.p >= state.end || *state.p == '\n' || *state.p == '\r') { state.IsInvalid = true; return; } var x = 0; while (state.p < state.end) { switch ((char)*state.p) { case '0': x = x * 10; break; case '1': x = x * 10 + 1; break; case '2': x = x * 10 + 2; break; case '3': x = x * 10 + 3; break; case '4': x = x * 10 + 4; break; case '5': x = x * 10 + 5; break; case '6': x = x * 10 + 6; break; case '7': x = x * 10 + 7; break; case '8': x = x * 10 + 8; break; case '9': x = x * 10 + 9; break; case '\r': case '\n': case ' ': if (x < 256) { setResult((byte)x); } else { state.IsInvalid = true; } return; default: { state.IsInvalid = true; return; } } state.p++; } if (x < 256) { setResult((byte)x); } else { state.IsInvalid = true; } }
internal static unsafe void ParseFloat32(LineParserState state, Action <float> setResult) { if (state.p >= state.end) { state.IsInvalid = true; return; } while (*state.p == ' ' && state.p < state.end) { state.p++; } if (state.p >= state.end || *state.p == '\n' || *state.p == '\r') { state.IsInvalid = true; return; } var minus = *state.p == ((byte)'-'); if (minus) { state.p++; } var x = 0.0f; var parse = true; while (parse && state.p < state.end) { switch ((char)*state.p) { case '0': x = x * 10.0f; break; case '1': x = x * 10.0f + 1.0f; break; case '2': x = x * 10.0f + 2.0f; break; case '3': x = x * 10.0f + 3.0f; break; case '4': x = x * 10.0f + 4.0f; break; case '5': x = x * 10.0f + 5.0f; break; case '6': x = x * 10.0f + 6.0f; break; case '7': x = x * 10.0f + 7.0f; break; case '8': x = x * 10.0f + 8.0f; break; case '9': x = x * 10.0f + 9.0f; break; case '.': parse = false; break; case ' ': setResult(minus ? -x : x); return; default: { state.IsInvalid = true; return; } } state.p++; } if (state.p >= state.end) { setResult(minus ? -x : x); return; } var y = 0.0f; var r = 0.1f; while (state.p < state.end) { switch ((char)*state.p) { case '0': break; case '1': y = y + r; break; case '2': y = y + r * 2; break; case '3': y = y + r * 3; break; case '4': y = y + r * 4; break; case '5': y = y + r * 5; break; case '6': y = y + r * 6; break; case '7': y = y + r * 7; break; case '8': y = y + r * 8; break; case '9': y = y + r * 9; break; case ' ': setResult(minus ? -x - y : x + y); return; default: { state.IsInvalid = true; return; } } r *= 0.1f; state.p++; } setResult(minus ? -x - y : x + y); }
/// <summary> /// Buffer is expected to contain ASCII. Lines separated by '\n'. /// </summary> public static Chunk?Custom(byte[] buffer, int count, double filterDist, Token[] layout) { var hasColor = layout.HasColorTokens(); var hasNormal = layout.HasNormalTokens(); var hasIntensity = layout.HasIntensityTokens(); var ps = new List <V3d>(); var cs = hasColor ? new List <C4b>() : null; var ns = hasNormal ? new List <V3f>() : null; var js = hasIntensity ? new List <int>() : null; var prev = V3d.PositiveInfinity; var filterDistM = -filterDist; var doFilterDist = filterDist > 0.0; var tokenParsers = layout.Map(x => s_parsers[x]); unsafe { fixed(byte *begin = buffer) { var state = new LineParserState { p = begin, end = begin + count }; while (state.p < state.end) { // parse single line state.IsInvalid = false; for (var i = 0; i < tokenParsers.Length; i++) { tokenParsers[i](state); if (state.IsInvalid) { break; } } SkipToNextLine(state); if (state.IsInvalid) { continue; } // min dist filtering if (doFilterDist) { if (Utils.DistLessThanL1(ref state.Position, ref prev, filterDist)) { continue; } prev = state.Position; } // add point to chunk ps.Add(state.Position); if (hasColor) { cs.Add(state.Color); } if (hasNormal) { ns.Add(state.Normal); } if (hasIntensity) { js.Add(state.Intensity); } } } } if (ps.Count == 0) { return(null); } return(new Chunk(ps, cs, ns, js)); }