public static ParseResult <Image> Parse(GedcomLine first, ILineProvider lineProvider) { var image = new Image(); image.ID = ParserHelper.ParseID(first.GetFirstItem()).ToString(); var initialLevel = first.Level; GedcomLine line = default; ReadOnlySpan <char> currentRawLine; while ((currentRawLine = lineProvider.ReadLine()) != null) { line = ParserHelper.ParseLine(currentRawLine); if (line.Level == first.Level) { break; } var splitLine = line.GetFirstItem(); if (ParserHelper.Equals(splitLine, "TITL")) { var title = line.GetLineContent(4); image.Title = title.ToString(); } else if (ParserHelper.Equals(splitLine, "FILE")) { var filePath = line.GetLineContent(4); image.FilePath = filePath.ToString(); } } return(ParseResult.Create(image, line)); }
public static ParseResult <GedcomEvent> Parse(GedcomLine first, ILineProvider lineProvider) { GedcomEvent gedcomEvent = new GedcomEvent(); var initialLevel = first.Level; GedcomLine line = default; ReadOnlySpan <char> currentRawLine; while ((currentRawLine = lineProvider.ReadLine()).Length > 0) { line = ParserHelper.ParseLine(currentRawLine); if (line.Level <= first.Level) { break; } ReadOnlySpan <char> tag = line.GetFirstItem(); if (ParserHelper.Equals(tag, "DATE")) { // If checks we're parsing actual date and not // CREA or CHAN tags // TODO: should actually put CREA and CHAN into different parser if (line.Level == initialLevel + 1) { var dateContent = line.GetLineContent(4); gedcomEvent.Date = dateContent.Length == 0 ? null : dateContent.ToString(); } } else if (ParserHelper.Equals(tag, "PLAC")) { // If checks we're parsing actual date and not // CREA or CHAN tags // TODO: should actually put CREA and CHAN into different parser if (line.Level == initialLevel + 1) { var placContent = line.GetLineContent(4); gedcomEvent.Location = placContent.Length == 0 ? null : placContent.ToString(); } } } return(ParseResult.Create(gedcomEvent, line)); }
private static void ParseNames(GedcomLine gedcomLine, Individual individual) { individual.FirstName = string.Empty; individual.FirstNames = string.Empty; var content = gedcomLine.GetLineContent(); // If there are no slashes to indicate surname, assume that the last entry is the surname int lastNameStart = content.IndexOf("/", StringComparison.Ordinal); if (lastNameStart != -1) { var preLine = content.Slice(0, lastNameStart).Trim(); var remainingLine = content.Slice(lastNameStart + 1, content.Length - lastNameStart - 1); int trailingSlashStart = remainingLine.IndexOf("/", StringComparison.Ordinal); string lastName; if (trailingSlashStart != -1) { lastName = remainingLine.Slice(0, trailingSlashStart).ToString(); } else { lastName = remainingLine.ToString(); } individual.LastName = lastName; var firstNames = preLine.ToString(); individual.FirstNames = firstNames; var indexOfSpace = preLine.IndexOf(' '); individual.FirstName = (indexOfSpace == -1) ? firstNames : preLine.Slice(0, indexOfSpace).ToString(); } else { var indexOfLast = content.LastIndexOf(' '); if (indexOfLast != -1) { individual.LastName = content.Slice(indexOfLast + 1, content.Length - indexOfLast - 1).ToString(); var firstNamesSlice = content.Slice(0, indexOfLast); var firstNames = firstNamesSlice.ToString(); individual.FirstNames = firstNames; var indexOfSpace = firstNamesSlice.IndexOf(' '); individual.FirstName = (indexOfSpace == -1) ? firstNames : firstNamesSlice.Slice(0, indexOfSpace).ToString(); } else { individual.LastName = content.ToString(); } } }
public static ParseResult <Note> Parse(GedcomLine first, ILineProvider lineProvider) { string id = ParserHelper.ParseID(first.GetFirstItem()).ToString(); string text = null; var initialLevel = first.Level; GedcomLine line = default; ReadOnlySpan <char> currentRawLine; while ((currentRawLine = lineProvider.ReadLine()).Length > 0) { line = ParserHelper.ParseLine(currentRawLine); if (line.Level == first.Level) { break; } ReadOnlySpan <char> tag = line.GetFirstItem(); if (ParserHelper.Equals(tag, "CONT")) { string contText = line.GetLineContent(4).ToString(); text += Environment.NewLine + contText; } else if (ParserHelper.Equals(tag, "CONC")) { // TODO: is GenesReunited maintaining the trailing space? // If so, is this correct? string concText = line.GetLineContent(4).ToString(); text += concText; } } return(ParseResult.Create(new Note(id, text), line)); }
public static ParseResult <Family> Parse(GedcomLine first, ILineProvider lineProvider) { var family = new Family(); family.ID = ParserHelper.ParseID(first.GetFirstItem()).ToString(); bool inMarriage = false; var initialLevel = first.Level; GedcomLine line = default; ReadOnlySpan <char> currentRawLine; while ((currentRawLine = lineProvider.ReadLine()).Length > 0) { line = ParserHelper.ParseLine(currentRawLine); if (line.Level == first.Level) { break; } var tag = line.GetFirstItem(); if (ParserHelper.Equals(tag, "MARR")) { inMarriage = true; } else if (ParserHelper.Equals(tag, "DATE")) { if (inMarriage) // TODO: should have MARR parser { var date = line.GetLineContent(4); if (family.Marriage == null) { family.Marriage = new GedcomEvent(); } family.Marriage.Date = date.ToString(); } } else if (ParserHelper.Equals(tag, "PLAC")) { if (inMarriage) // Assume level + 1 is MARR { var place = line.GetLineContent(4); if (family.Marriage == null) { family.Marriage = new GedcomEvent(); } family.Marriage.Location = place.ToString(); } } else if (ParserHelper.Equals(tag, "HUSB")) { // Ignore any husband and wife information in the middle of a marriage tag. // Present for torture test files - and info redundant? // can have e.g. "2 HUSB", with no additional info var husbContent = line.GetLineContent(4); if (husbContent.Length > 0) { family.HusbandID = ParserHelper.ParseID(husbContent).ToString(); } } else if (ParserHelper.Equals(tag, "WIFE")) { var wifeContent = line.GetLineContent(4); // Ignore any husband and wife information in the middle of a marriage tag. // Present for torture test files - and info redundant? // can have e.g. "2 HUSB", with no additional info if (wifeContent.Length > 0) { family.WifeID = ParserHelper.ParseID(wifeContent).ToString(); } } else if (ParserHelper.Equals(tag, "CHIL")) { var childContent = line.GetLineContent(4); family.ChildIDs.Add(ParserHelper.ParseID(childContent).ToString()); } else { inMarriage = false; } } return(ParseResult.Create(family, line)); }
public static ParseResult <Individual> Parse(GedcomLine first, ILineProvider lineProvider) { var individual = new Individual(); individual.ID = ParserHelper.ParseID(first.GetFirstItem()).ToString(); GedcomLine line = default; ReadOnlySpan <char> currentRawLine; var newLine = false; while (true) { // TODO: this loop is really messy, as some of the parsing // works on lines as retrieved from the parser, where some // other iterations call onto a sub-parser which return a final // line. Should split this logic if (!newLine) { currentRawLine = lineProvider.ReadLine(); if (currentRawLine == null) { break; } line = ParserHelper.ParseLine(currentRawLine); } newLine = false; if (line.Level == 0) { break; } var tag = line.GetFirstItem(); if (ParserHelper.Equals(tag, "NAME") && individual.LastName == null && individual.FirstNames == null) { ParseNames(line, individual); } else if (ParserHelper.Equals(tag, "SEX")) { individual.Gender = ParserHelper.Equals(line.GetLineContent(3), "M") ? Gender.Male : Gender.Female; } else if (ParserHelper.Equals(tag, "FAMS")) { individual.FamilyIDSpouse = ParserHelper.ParseID(line.GetLineContent(4)).ToString(); } else if (ParserHelper.Equals(tag, "FAMC")) { individual.FamilyIDChild = ParserHelper.ParseID(line.GetLineContent(4)).ToString(); } else if (ParserHelper.Equals(tag, "OBJE")) { var content = line.GetLineContent(4); if (content.Length > 0) { individual.ImageID = ParserHelper.ParseID(content).ToString(); } } else if (ParserHelper.Equals(tag, "NOTE")) { var noteContent = line.GetLineContent(4); if (noteContent.Length > 0) { if (noteContent[0] == '@') { individual.NoteID = ParserHelper.ParseID(noteContent).ToString(); } else { individual.Note = noteContent.ToString(); } } } else if (ParserHelper.Equals(tag, "CONT")) { var contContent = line.GetLineContent(4); individual.Note += Environment.NewLine + contContent.ToString(); } else if (ParserHelper.Equals(tag, "CONC")) { // TODO: is GenesReunited maintaining the trailing space? // If so, is this correct? var concContent = line.GetLineContent(4); if (concContent.Length > 0) { individual.Note += concContent.ToString(); } } else if (ParserHelper.Equals(tag, "BIRT")) { var birthParseResult = EventParser.Parse(line, lineProvider); if (individual.Birth == null) { individual.Birth = birthParseResult.Result; } line = birthParseResult.Line; newLine = true; } else if (ParserHelper.Equals(tag, "DEAT")) { var deathParseResult = EventParser.Parse(line, lineProvider); if (individual.Death == null) { individual.Death = deathParseResult.Result; } line = deathParseResult.Line; newLine = true; } else if (ParserHelper.Equals(tag, "BAPM")) { var baptismParseResult = EventParser.Parse(line, lineProvider); if (individual.Baptism == null) { individual.Baptism = baptismParseResult.Result; } line = baptismParseResult.Line; newLine = true; } else if (ParserHelper.Equals(tag, "RESI")) { var residenceParseResult = EventParser.Parse(line, lineProvider); individual.Residences.Add(residenceParseResult.Result); line = residenceParseResult.Line; newLine = true; } else if (ParserHelper.Equals(tag, "CENS")) { var censusParseResult = EventParser.Parse(line, lineProvider); individual.Census.Add(censusParseResult.Result); line = censusParseResult.Line; newLine = true; } else if (ParserHelper.Equals(tag, "MARR")) { var marriageParseResult = EventParser.Parse(line, lineProvider); if (marriageParseResult.Result != null) { individual.Marriages.Add(marriageParseResult.Result); } line = marriageParseResult.Line; newLine = true; // TODO: cope with multiple marriage records // It seems that ancestry only outputs multiple marriage records in an individual // if there's conflicting information, not for multiple marriages // Multiple marriages for an individual are put into the FAMs tag } //case "ENGA": // // TODO: // // individual.Engagement = EventParser.Parse(parserLinesEnga); // break; if (line.Level == 0) { break; } } if (individual.LastName == null) { individual.LastName = string.Empty; } if (individual.FirstName == null) { individual.FirstName = string.Empty; } if (individual.FirstNames == null) { individual.FirstNames = string.Empty; } return(ParseResult.Create(individual, line)); }
public static ParseResult <GedcomHeader> Parse(GedcomLine first, ILineProvider lineProvider) { CurrentLevel currentLevel = CurrentLevel.None; var header = new GedcomHeader(); GedcomLine line = default; ReadOnlySpan <char> currentRawLine; while ((currentRawLine = lineProvider.ReadLine()).Length > 0) { line = ParserHelper.ParseLine(currentRawLine); if (line.Level == 0) { break; } if (line.Level == 1) { var tag = line.GetFirstItem(); if (ParserHelper.Equals(tag, "SOUR")) { currentLevel = CurrentLevel.Sour; } else if (ParserHelper.Equals(tag, "GEDC")) { currentLevel = CurrentLevel.Gedc; } else if (ParserHelper.Equals(tag, "CHAR")) { header.GedcomCharacterSet = line.GetLineContent(4).ToString(); } } else if (line.Level == 2) { if (currentLevel == CurrentLevel.Sour) { var tag = line.GetFirstItem(); if (ParserHelper.Equals(tag, "NAME")) { header.SourceName = line.GetLineContent(4).ToString(); } else if (ParserHelper.Equals(tag, "VERS")) { header.SourceVers = line.GetLineContent(4).ToString(); } else if (ParserHelper.Equals(tag, "CORP")) { header.SourceCorp = line.GetLineContent(4).ToString(); } } else if (currentLevel == CurrentLevel.Gedc) { if (ParserHelper.Equals(line.GetFirstItem(), "VERS")) { header.GedcomVers = line.GetLineContent(4).ToString(); } } } } return(ParseResult.Create(header, line)); }