From aa0352ff605a0b04a0700cd69f8dcb4c6dbc207f Mon Sep 17 00:00:00 2001 From: "Sergey V. Zhdanovskih" Date: Tue, 2 Jul 2024 21:13:41 +0300 Subject: [PATCH] Identifying differences between records, structures, and tags using HashCode (#583) --- projects/GKCore/GDModel/GDMAddress.cs | 20 +++++++++ projects/GKCore/GDModel/GDMAssociation.cs | 11 ++++- projects/GKCore/GDModel/GDMChangeDate.cs | 9 +++- .../GKCore/GDModel/GDMChildToFamilyLink.cs | 10 ++++- .../GKCore/GDModel/GDMCommunicationRecord.cs | 13 +++++- projects/GKCore/GDModel/GDMCustomEvent.cs | 19 ++++++++- projects/GKCore/GDModel/GDMCutoutPosition.cs | 12 +++++- projects/GKCore/GDModel/GDMDate.cs | 13 ++++++ projects/GKCore/GDModel/GDMDateInterpreted.cs | 10 ++++- projects/GKCore/GDModel/GDMDatePeriod.cs | 8 ++++ projects/GKCore/GDModel/GDMDateRange.cs | 8 ++++ projects/GKCore/GDModel/GDMDateValue.cs | 7 ++++ projects/GKCore/GDModel/GDMFamilyEvent.cs | 7 ++++ projects/GKCore/GDModel/GDMFamilyRecord.cs | 12 +++++- projects/GKCore/GDModel/GDMFileReference.cs | 10 ++++- .../GDModel/GDMFileReferenceWithTitle.cs | 9 +++- projects/GKCore/GDModel/GDMGroupRecord.cs | 10 ++++- .../GKCore/GDModel/GDMIndividualAttribute.cs | 8 ++++ projects/GKCore/GDModel/GDMIndividualEvent.cs | 7 ++++ projects/GKCore/GDModel/GDMIndividualLink.cs | 11 +++++ .../GKCore/GDModel/GDMIndividualRecord.cs | 14 ++++++- projects/GKCore/GDModel/GDMInterfaces.cs | 2 + projects/GKCore/GDModel/GDMLanguage.cs | 7 ++++ projects/GKCore/GDModel/GDMLines.cs | 12 ++++++ projects/GKCore/GDModel/GDMLocationLink.cs | 8 ++++ projects/GKCore/GDModel/GDMLocationName.cs | 9 ++++ projects/GKCore/GDModel/GDMLocationRecord.cs | 9 ++++ projects/GKCore/GDModel/GDMLocationType.cs | 8 ++++ projects/GKCore/GDModel/GDMMap.cs | 8 ++++ projects/GKCore/GDModel/GDMMultimediaLink.cs | 13 +++++- .../GKCore/GDModel/GDMMultimediaRecord.cs | 9 +++- projects/GKCore/GDModel/GDMNoteRecord.cs | 9 +++- projects/GKCore/GDModel/GDMNotes.cs | 16 ++++++- projects/GKCore/GDModel/GDMPersonalName.cs | 22 +++++++++- projects/GKCore/GDModel/GDMPlace.cs | 10 +++++ projects/GKCore/GDModel/GDMPointer.cs | 8 ++++ .../GKCore/GDModel/GDMPointerWithNotes.cs | 9 +++- projects/GKCore/GDModel/GDMRecord.cs | 13 ++++++ .../GKCore/GDModel/GDMRecordWithEvents.cs | 10 ++++- .../GKCore/GDModel/GDMRepositoryCitation.cs | 8 +++- .../GKCore/GDModel/GDMRepositoryRecord.cs | 10 ++++- projects/GKCore/GDModel/GDMResearchRecord.cs | 15 +++++++ projects/GKCore/GDModel/GDMSourceCitation.cs | 13 ++++++ .../GKCore/GDModel/GDMSourceCitationData.cs | 10 ++++- projects/GKCore/GDModel/GDMSourceData.cs | 12 +++++- projects/GKCore/GDModel/GDMSourceEvent.cs | 11 ++++- projects/GKCore/GDModel/GDMSourceRecord.cs | 14 +++++++ .../GKCore/GDModel/GDMSpouseToFamilyLink.cs | 8 +++- .../GKCore/GDModel/GDMSubmissionRecord.cs | 13 ++++++ projects/GKCore/GDModel/GDMSubmitterRecord.cs | 13 +++++- projects/GKCore/GDModel/GDMTag.cs | 30 +++++++++++++ projects/GKCore/GDModel/GDMTaskRecord.cs | 10 +++++ projects/GKCore/GDModel/GDMTime.cs | 12 +++++- projects/GKCore/GDModel/GDMUserReference.cs | 9 +++- projects/GKCore/GKCore/HashCode.cs | 42 ++++++++++++------- projects/GKCore/GKCore/NetDiff/DiffUtil.cs | 14 +++++-- projects/GKCore/GKCore/Tools/SyncTool.cs | 9 +++- projects/plugins/GKTreeSyncPlugin/TSForm.cs | 3 +- 58 files changed, 617 insertions(+), 49 deletions(-) diff --git a/projects/GKCore/GDModel/GDMAddress.cs b/projects/GKCore/GDModel/GDMAddress.cs index 470acfdad..892868b72 100644 --- a/projects/GKCore/GDModel/GDMAddress.cs +++ b/projects/GKCore/GDModel/GDMAddress.cs @@ -240,5 +240,25 @@ public void SetAddressArray(string[] value) fLines.Clear(); fLines.AddRange(value); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddHash(fLines.GetHashCode()); + + hashCode.AddObj(fAddressLine1); + hashCode.AddObj(fAddressLine2); + hashCode.AddObj(fAddressLine3); + hashCode.AddObj(fAddressCity); + hashCode.AddObj(fAddressState); + hashCode.AddObj(fAddressPostalCode); + hashCode.AddObj(fAddressCountry); + + ProcessHashes(ref hashCode, fPhoneList); + ProcessHashes(ref hashCode, fEmailList); + ProcessHashes(ref hashCode, fFaxList); + ProcessHashes(ref hashCode, fWWWList); + } } } diff --git a/projects/GKCore/GDModel/GDMAssociation.cs b/projects/GKCore/GDModel/GDMAssociation.cs index 828b90ecd..359df411e 100644 --- a/projects/GKCore/GDModel/GDMAssociation.cs +++ b/projects/GKCore/GDModel/GDMAssociation.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -102,5 +102,14 @@ public override void Assign(GDMTag source) fRelation = sourceObj.fRelation; if (sourceObj.fSourceCitations != null) AssignList(sourceObj.fSourceCitations, SourceCitations); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fRelation); + + ProcessHashes(ref hashCode, fSourceCitations); + } } } diff --git a/projects/GKCore/GDModel/GDMChangeDate.cs b/projects/GKCore/GDModel/GDMChangeDate.cs index b8e9613b7..74593606c 100644 --- a/projects/GKCore/GDModel/GDMChangeDate.cs +++ b/projects/GKCore/GDModel/GDMChangeDate.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2019 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -71,5 +71,12 @@ public override bool IsEmpty() { return base.IsEmpty() && (fChangeDateTime.Equals(ZeroDateTime)); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddVal(fChangeDateTime); + } } } diff --git a/projects/GKCore/GDModel/GDMChildToFamilyLink.cs b/projects/GKCore/GDModel/GDMChildToFamilyLink.cs index 3a201b796..c2184b310 100644 --- a/projects/GKCore/GDModel/GDMChildToFamilyLink.cs +++ b/projects/GKCore/GDModel/GDMChildToFamilyLink.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2022 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -82,5 +82,13 @@ public override void Assign(GDMTag source) fChildLinkageStatus = srcCFL.fChildLinkageStatus; fPedigreeLinkageType = srcCFL.fPedigreeLinkageType; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddVal(fChildLinkageStatus); + hashCode.AddVal(fPedigreeLinkageType); + } } } diff --git a/projects/GKCore/GDModel/GDMCommunicationRecord.cs b/projects/GKCore/GDModel/GDMCommunicationRecord.cs index 4ee71e799..97c958c52 100644 --- a/projects/GKCore/GDModel/GDMCommunicationRecord.cs +++ b/projects/GKCore/GDModel/GDMCommunicationRecord.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2022 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -155,5 +155,16 @@ public override void ReplaceXRefs(GDMXRefReplacer map) base.ReplaceXRefs(map); fCorresponder.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fCommName); + hashCode.AddVal(fCommunicationType); + hashCode.AddObj(fDate); + hashCode.AddVal(fCommDirection); + hashCode.AddObj(fCorresponder); + } } } diff --git a/projects/GKCore/GDModel/GDMCustomEvent.cs b/projects/GKCore/GDModel/GDMCustomEvent.cs index 2e9a5c678..2caa7ebce 100644 --- a/projects/GKCore/GDModel/GDMCustomEvent.cs +++ b/projects/GKCore/GDModel/GDMCustomEvent.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2023 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -296,5 +296,22 @@ public int GetChronologicalYear() { return Date.GetChronologicalYear(); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fAddress); + hashCode.AddObj(fAgency); + hashCode.AddObj(fCause); + hashCode.AddObj(fClassification); + hashCode.AddObj(fDate); + hashCode.AddObj(fPlace); + hashCode.AddObj(fReligiousAffilation); + hashCode.AddVal(fRestriction); + ProcessHashes(ref hashCode, fNotes); + ProcessHashes(ref hashCode, fSourceCitations); + ProcessHashes(ref hashCode, fMultimediaLinks); + } } } diff --git a/projects/GKCore/GDModel/GDMCutoutPosition.cs b/projects/GKCore/GDModel/GDMCutoutPosition.cs index b9dc81783..ea240e049 100644 --- a/projects/GKCore/GDModel/GDMCutoutPosition.cs +++ b/projects/GKCore/GDModel/GDMCutoutPosition.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -126,5 +126,15 @@ internal void SetRawData(int x1, int y1, int x2, int y2) fX2 = x2; fY2 = y2; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddVal(fX1); + hashCode.AddVal(fY1); + hashCode.AddVal(fX2); + hashCode.AddVal(fY2); + } } } diff --git a/projects/GKCore/GDModel/GDMDate.cs b/projects/GKCore/GDModel/GDMDate.cs index 198c77ac7..9164530ee 100644 --- a/projects/GKCore/GDModel/GDMDate.cs +++ b/projects/GKCore/GDModel/GDMDate.cs @@ -698,5 +698,18 @@ private static byte DaysInMonth(bool yearBC, short year, byte month, GDMCalendar return (byte)DateTime.DaysInMonth(year, month); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddVal(fApproximated); + hashCode.AddVal(fCalendar); + hashCode.AddVal(fDay); + hashCode.AddVal(fMonth); + hashCode.AddVal(fYear); + hashCode.AddVal(fYearBC); + hashCode.AddObj(fYearModifier); + } } } diff --git a/projects/GKCore/GDModel/GDMDateInterpreted.cs b/projects/GKCore/GDModel/GDMDateInterpreted.cs index 3ffe58229..2efe8deee 100644 --- a/projects/GKCore/GDModel/GDMDateInterpreted.cs +++ b/projects/GKCore/GDModel/GDMDateInterpreted.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2019 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -75,5 +76,12 @@ public override string ParseString(string strValue) } return result; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fDatePhrase); + } } } diff --git a/projects/GKCore/GDModel/GDMDatePeriod.cs b/projects/GKCore/GDModel/GDMDatePeriod.cs index c224a9504..38391750d 100644 --- a/projects/GKCore/GDModel/GDMDatePeriod.cs +++ b/projects/GKCore/GDModel/GDMDatePeriod.cs @@ -185,5 +185,13 @@ public override void GetDateRange(out GDMDate dateStart, out GDMDate dateEnd) dateStart = fDateFrom; dateEnd = fDateTo; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fDateFrom); + hashCode.AddObj(fDateTo); + } } } diff --git a/projects/GKCore/GDModel/GDMDateRange.cs b/projects/GKCore/GDModel/GDMDateRange.cs index 99ad77325..fc84bd34e 100644 --- a/projects/GKCore/GDModel/GDMDateRange.cs +++ b/projects/GKCore/GDModel/GDMDateRange.cs @@ -197,5 +197,13 @@ public override void GetDateRange(out GDMDate dateStart, out GDMDate dateEnd) dateStart = fDateAfter; dateEnd = fDateBefore; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fDateAfter); + hashCode.AddObj(fDateBefore); + } } } diff --git a/projects/GKCore/GDModel/GDMDateValue.cs b/projects/GKCore/GDModel/GDMDateValue.cs index f8c7a76c9..b2351e084 100644 --- a/projects/GKCore/GDModel/GDMDateValue.cs +++ b/projects/GKCore/GDModel/GDMDateValue.cs @@ -179,5 +179,12 @@ public override void GetDateRange(out GDMDate dateStart, out GDMDate dateEnd) fValue.GetDateRange(out dateStart, out dateEnd); } } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fValue); + } } } diff --git a/projects/GKCore/GDModel/GDMFamilyEvent.cs b/projects/GKCore/GDModel/GDMFamilyEvent.cs index a45bc46da..fdf33fc57 100644 --- a/projects/GKCore/GDModel/GDMFamilyEvent.cs +++ b/projects/GKCore/GDModel/GDMFamilyEvent.cs @@ -18,6 +18,8 @@ * along with this program. If not, see . */ +using System; + namespace GDModel { public sealed class GDMFamilyEvent : GDMCustomEvent @@ -30,5 +32,10 @@ public GDMFamilyEvent(int tagId, string tagValue) { SetNameValue(tagId, tagValue); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + } } } diff --git a/projects/GKCore/GDModel/GDMFamilyRecord.cs b/projects/GKCore/GDModel/GDMFamilyRecord.cs index 754ff0e79..d9e7712d8 100644 --- a/projects/GKCore/GDModel/GDMFamilyRecord.cs +++ b/projects/GKCore/GDModel/GDMFamilyRecord.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2022 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -305,5 +305,15 @@ public bool HasChild(GDMIndividualRecord child) { return IndexOfChild(child) >= 0; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + ProcessHashes(ref hashCode, fChildren); + hashCode.AddObj(fHusband); + hashCode.AddObj(fWife); + hashCode.AddVal(fStatus); + } } } diff --git a/projects/GKCore/GDModel/GDMFileReference.cs b/projects/GKCore/GDModel/GDMFileReference.cs index 2e7761043..f31b54a12 100644 --- a/projects/GKCore/GDModel/GDMFileReference.cs +++ b/projects/GKCore/GDModel/GDMFileReference.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -178,5 +178,13 @@ public static GDMMultimediaFormat RecognizeFormat(string fileName) var strFmt = GetMultimediaExt(fileName); return string.IsNullOrEmpty(strFmt) ? GDMMultimediaFormat.mfUnknown : GEDCOMUtils.GetMultimediaFormatVal(strFmt); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fMultimediaFormat); + hashCode.AddVal(fMediaType); + } } } diff --git a/projects/GKCore/GDModel/GDMFileReferenceWithTitle.cs b/projects/GKCore/GDModel/GDMFileReferenceWithTitle.cs index e49fbb3c9..b70e81bdf 100644 --- a/projects/GKCore/GDModel/GDMFileReferenceWithTitle.cs +++ b/projects/GKCore/GDModel/GDMFileReferenceWithTitle.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2019 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -54,5 +54,12 @@ public override bool IsEmpty() { return base.IsEmpty() && string.IsNullOrEmpty(fTitle); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fTitle); + } } } diff --git a/projects/GKCore/GDModel/GDMGroupRecord.cs b/projects/GKCore/GDModel/GDMGroupRecord.cs index 5f457b9cd..3f3f61d61 100644 --- a/projects/GKCore/GDModel/GDMGroupRecord.cs +++ b/projects/GKCore/GDModel/GDMGroupRecord.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2022 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -160,5 +160,13 @@ public override void MoveTo(GDMRecord targetRecord) targetGroup.Members.Add(obj); } } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fGroupName); + ProcessHashes(ref hashCode, fMembers); + } } } diff --git a/projects/GKCore/GDModel/GDMIndividualAttribute.cs b/projects/GKCore/GDModel/GDMIndividualAttribute.cs index 10a39ed29..aa3ef4003 100644 --- a/projects/GKCore/GDModel/GDMIndividualAttribute.cs +++ b/projects/GKCore/GDModel/GDMIndividualAttribute.cs @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -39,5 +40,12 @@ public GDMIndividualAttribute(int tagId, string tagValue) { SetNameValue(tagId, tagValue); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + //hashCode.AddObj(PhysicalDescription); <- inner Tags + } } } diff --git a/projects/GKCore/GDModel/GDMIndividualEvent.cs b/projects/GKCore/GDModel/GDMIndividualEvent.cs index 27d9a3afb..5104b903b 100644 --- a/projects/GKCore/GDModel/GDMIndividualEvent.cs +++ b/projects/GKCore/GDModel/GDMIndividualEvent.cs @@ -18,6 +18,8 @@ * along with this program. If not, see . */ +using System; + namespace GDModel { public sealed class GDMIndividualEvent : GDMCustomEvent @@ -30,5 +32,10 @@ public GDMIndividualEvent(int tagId, string tagValue) { SetNameValue(tagId, tagValue); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + } } } diff --git a/projects/GKCore/GDModel/GDMIndividualLink.cs b/projects/GKCore/GDModel/GDMIndividualLink.cs index d59f7ee20..819f91e17 100644 --- a/projects/GKCore/GDModel/GDMIndividualLink.cs +++ b/projects/GKCore/GDModel/GDMIndividualLink.cs @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -36,6 +37,11 @@ public GDMIndividualLink(int tagId, string tagValue) { SetNameValue(tagId, tagValue); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + } } @@ -56,5 +62,10 @@ public GDMChildLink(int tagId, string tagValue) { SetNameValue(tagId, tagValue); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + } } } diff --git a/projects/GKCore/GDModel/GDMIndividualRecord.cs b/projects/GKCore/GDModel/GDMIndividualRecord.cs index 97a5daa7c..48281f526 100644 --- a/projects/GKCore/GDModel/GDMIndividualRecord.cs +++ b/projects/GKCore/GDModel/GDMIndividualRecord.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2022 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -565,5 +565,17 @@ public GDMMultimediaLink GetPrimaryMultimediaLink() return result; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + ProcessHashes(ref hashCode, fAssociations); + ProcessHashes(ref hashCode, fChildToFamilyLinks); + ProcessHashes(ref hashCode, fGroups); + ProcessHashes(ref hashCode, fPersonalNames); + ProcessHashes(ref hashCode, fSpouseToFamilyLinks); + hashCode.AddVal(fSex); + } } } diff --git a/projects/GKCore/GDModel/GDMInterfaces.cs b/projects/GKCore/GDModel/GDMInterfaces.cs index d7ff76a38..7b14c54c3 100644 --- a/projects/GKCore/GDModel/GDMInterfaces.cs +++ b/projects/GKCore/GDModel/GDMInterfaces.cs @@ -36,6 +36,8 @@ public interface IGDMTag : IGDMObject GDMList SubTags { get; } bool IsEmpty(); + + int GetHashCode(); } diff --git a/projects/GKCore/GDModel/GDMLanguage.cs b/projects/GKCore/GDModel/GDMLanguage.cs index e109c2646..43101dfbf 100644 --- a/projects/GKCore/GDModel/GDMLanguage.cs +++ b/projects/GKCore/GDModel/GDMLanguage.cs @@ -183,5 +183,12 @@ public GDMLanguage(int tagId, string tagValue) { SetNameValue(tagId, tagValue); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddVal(fValue); + } } } diff --git a/projects/GKCore/GDModel/GDMLines.cs b/projects/GKCore/GDModel/GDMLines.cs index d31bc71dd..b76362d32 100644 --- a/projects/GKCore/GDModel/GDMLines.cs +++ b/projects/GKCore/GDModel/GDMLines.cs @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using System.Collections.Generic; using System.Text; @@ -68,6 +69,17 @@ public GDMLines(string[] list) : this() } } + public override int GetHashCode() + { + var result = new HashCode(); + + for (int i = 0, num = base.Count; i < num; i++) { + result.AddObj(base[i]); + } + + return result.ToHashCode(); + } + public bool IsEmpty() { return (base.Count <= 0) || (base.Count == 1 && (base[0] == "" || base[0] == LINE_BREAK)); diff --git a/projects/GKCore/GDModel/GDMLocationLink.cs b/projects/GKCore/GDModel/GDMLocationLink.cs index 6e9d23090..273488ef2 100644 --- a/projects/GKCore/GDModel/GDMLocationLink.cs +++ b/projects/GKCore/GDModel/GDMLocationLink.cs @@ -94,5 +94,13 @@ public override void ReplaceXRefs(GDMXRefReplacer map) base.ReplaceXRefs(map); fDate.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fDate); + hashCode.AddVal(fRelationship); + } } } diff --git a/projects/GKCore/GDModel/GDMLocationName.cs b/projects/GKCore/GDModel/GDMLocationName.cs index 147209fca..a46523647 100644 --- a/projects/GKCore/GDModel/GDMLocationName.cs +++ b/projects/GKCore/GDModel/GDMLocationName.cs @@ -103,5 +103,14 @@ public override void ReplaceXRefs(GDMXRefReplacer map) base.ReplaceXRefs(map); fDate.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fAbbreviation); + hashCode.AddObj(fDate); + hashCode.AddVal(fLanguage); + } } } diff --git a/projects/GKCore/GDModel/GDMLocationRecord.cs b/projects/GKCore/GDModel/GDMLocationRecord.cs index 567b34ef4..6dd8b74ca 100644 --- a/projects/GKCore/GDModel/GDMLocationRecord.cs +++ b/projects/GKCore/GDModel/GDMLocationRecord.cs @@ -325,6 +325,15 @@ private static int ElementsCompare(IGDMLocationElement cp1, IGDMLocationElement UDN udn2 = cp2.Date.GetUDN(); return udn1.CompareTo(udn2); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fMap); + ProcessHashes(ref hashCode, fNames); + ProcessHashes(ref hashCode, fTopLevels); + } } public interface IGDMLocationElement diff --git a/projects/GKCore/GDModel/GDMLocationType.cs b/projects/GKCore/GDModel/GDMLocationType.cs index fafdaac40..2ed516f5a 100644 --- a/projects/GKCore/GDModel/GDMLocationType.cs +++ b/projects/GKCore/GDModel/GDMLocationType.cs @@ -88,5 +88,13 @@ public override void ReplaceXRefs(GDMXRefReplacer map) base.ReplaceXRefs(map); fDate.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fAbbreviation); + hashCode.AddObj(fDate); + } } } diff --git a/projects/GKCore/GDModel/GDMMap.cs b/projects/GKCore/GDModel/GDMMap.cs index 751426890..b8c4a27ad 100644 --- a/projects/GKCore/GDModel/GDMMap.cs +++ b/projects/GKCore/GDModel/GDMMap.cs @@ -71,5 +71,13 @@ public override bool IsEmpty() { return base.IsEmpty() && (fLati == 0.0d && fLong == 0.0d); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddVal(fLati); + hashCode.AddVal(fLong); + } } } diff --git a/projects/GKCore/GDModel/GDMMultimediaLink.cs b/projects/GKCore/GDModel/GDMMultimediaLink.cs index 92a5e59af..2156a88c6 100644 --- a/projects/GKCore/GDModel/GDMMultimediaLink.cs +++ b/projects/GKCore/GDModel/GDMMultimediaLink.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -164,5 +164,16 @@ public override void ReplaceXRefs(GDMXRefReplacer map) base.ReplaceXRefs(map); fFileReferences.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fCutoutPosition); + ProcessHashes(ref hashCode, fFileReferences); + hashCode.AddVal(fIsPrimary); + hashCode.AddVal(fIsPrimaryCutout); + hashCode.AddObj(fTitle); + } } } diff --git a/projects/GKCore/GDModel/GDMMultimediaRecord.cs b/projects/GKCore/GDModel/GDMMultimediaRecord.cs index 416fe686a..b093c51e6 100644 --- a/projects/GKCore/GDModel/GDMMultimediaRecord.cs +++ b/projects/GKCore/GDModel/GDMMultimediaRecord.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -90,5 +90,12 @@ public string GetFileTitle() GDMFileReferenceWithTitle fileRef = fFileReferences[0]; return fileRef.Title; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + ProcessHashes(ref hashCode, fFileReferences); + } } } diff --git a/projects/GKCore/GDModel/GDMNoteRecord.cs b/projects/GKCore/GDModel/GDMNoteRecord.cs index 5c9aa082b..a9a62537b 100644 --- a/projects/GKCore/GDModel/GDMNoteRecord.cs +++ b/projects/GKCore/GDModel/GDMNoteRecord.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -131,5 +131,12 @@ public void SetNoteText(string text) fLines.Text = text; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fLines); + } } } diff --git a/projects/GKCore/GDModel/GDMNotes.cs b/projects/GKCore/GDModel/GDMNotes.cs index 5ed4e8eaf..b05117796 100644 --- a/projects/GKCore/GDModel/GDMNotes.cs +++ b/projects/GKCore/GDModel/GDMNotes.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -83,6 +83,13 @@ public override string ParseString(string strValue) fLines.Add(strValue); return string.Empty; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fLines); + } } @@ -145,5 +152,12 @@ public override string ParseString(string strValue) } return result; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fLines); + } } } diff --git a/projects/GKCore/GDModel/GDMPersonalName.cs b/projects/GKCore/GDModel/GDMPersonalName.cs index fc0a3c1d4..717485e15 100644 --- a/projects/GKCore/GDModel/GDMPersonalName.cs +++ b/projects/GKCore/GDModel/GDMPersonalName.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -383,5 +383,25 @@ public float IsMatch(GDMPersonalName otherName, bool onlyFirstPart) return match; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fGiven); + hashCode.AddVal(fLanguage); + hashCode.AddObj(fNamePrefix); + hashCode.AddObj(fNameSuffix); + hashCode.AddVal(fNameType); + hashCode.AddObj(fNickname); + ProcessHashes(ref hashCode, fNotes); + ProcessHashes(ref hashCode, fSourceCitations); + hashCode.AddObj(fSurnamePrefix); + hashCode.AddObj(fSurname); + hashCode.AddObj(fPatronymicName); + hashCode.AddObj(fMarriedName); + hashCode.AddObj(fReligiousName); + hashCode.AddObj(fCensusName); + } } } diff --git a/projects/GKCore/GDModel/GDMPlace.cs b/projects/GKCore/GDModel/GDMPlace.cs index c49141562..07d531a01 100644 --- a/projects/GKCore/GDModel/GDMPlace.cs +++ b/projects/GKCore/GDModel/GDMPlace.cs @@ -131,5 +131,15 @@ public override void ReplaceXRefs(GDMXRefReplacer map) if (fMap != null) fMap.ReplaceXRefs(map); if (fNotes != null) fNotes.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fForm); + hashCode.AddObj(fLocation); + hashCode.AddObj(fMap); + ProcessHashes(ref hashCode, fNotes); + } } } diff --git a/projects/GKCore/GDModel/GDMPointer.cs b/projects/GKCore/GDModel/GDMPointer.cs index cf8601f78..f64275bde 100644 --- a/projects/GKCore/GDModel/GDMPointer.cs +++ b/projects/GKCore/GDModel/GDMPointer.cs @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -83,5 +84,12 @@ public override void ReplaceXRefs(GDMXRefReplacer map) XRef = map.FindNewXRef(XRef); } } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fXRef); + } } } diff --git a/projects/GKCore/GDModel/GDMPointerWithNotes.cs b/projects/GKCore/GDModel/GDMPointerWithNotes.cs index 0caa1e1e8..bc5bc7a85 100644 --- a/projects/GKCore/GDModel/GDMPointerWithNotes.cs +++ b/projects/GKCore/GDModel/GDMPointerWithNotes.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -84,5 +84,12 @@ public override void ReplaceXRefs(GDMXRefReplacer map) base.ReplaceXRefs(map); if (fNotes != null) fNotes.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + ProcessHashes(ref hashCode, fNotes); + } } } diff --git a/projects/GKCore/GDModel/GDMRecord.cs b/projects/GKCore/GDModel/GDMRecord.cs index 3eee9b693..295d2fa03 100644 --- a/projects/GKCore/GDModel/GDMRecord.cs +++ b/projects/GKCore/GDModel/GDMRecord.cs @@ -317,5 +317,18 @@ public long GetId() { return GEDCOMUtils.GetXRefNumber(XRef); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fAutomatedRecordID); + // without fChangeDate and fUID! + hashCode.AddObj(fXRef); + ProcessHashes(ref hashCode, fMultimediaLinks); + ProcessHashes(ref hashCode, fNotes); + ProcessHashes(ref hashCode, fSourceCitations); + ProcessHashes(ref hashCode, fUserReferences); + } } } diff --git a/projects/GKCore/GDModel/GDMRecordWithEvents.cs b/projects/GKCore/GDModel/GDMRecordWithEvents.cs index cc5eafae8..99c2cc428 100644 --- a/projects/GKCore/GDModel/GDMRecordWithEvents.cs +++ b/projects/GKCore/GDModel/GDMRecordWithEvents.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2023 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -202,5 +202,13 @@ public int GetChronologicalYear(string eventSign) GDMCustomEvent evt = FindEvent(eventSign); return (evt == null) ? 0 : evt.GetChronologicalYear(); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + ProcessHashes(ref hashCode, fEvents); + hashCode.AddVal(fRestriction); + } } } diff --git a/projects/GKCore/GDModel/GDMRepositoryCitation.cs b/projects/GKCore/GDModel/GDMRepositoryCitation.cs index 88310e15c..aa0860606 100644 --- a/projects/GKCore/GDModel/GDMRepositoryCitation.cs +++ b/projects/GKCore/GDModel/GDMRepositoryCitation.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2019 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -28,5 +29,10 @@ public GDMRepositoryCitation() { SetName(GEDCOMTagType.REPO); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + } } } diff --git a/projects/GKCore/GDModel/GDMRepositoryRecord.cs b/projects/GKCore/GDModel/GDMRepositoryRecord.cs index 7664cfe21..d47f4eef0 100644 --- a/projects/GKCore/GDModel/GDMRepositoryRecord.cs +++ b/projects/GKCore/GDModel/GDMRepositoryRecord.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2022 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -107,5 +107,13 @@ public override void ReplaceXRefs(GDMXRefReplacer map) base.ReplaceXRefs(map); if (fAddress != null) fAddress.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fAddress); + hashCode.AddObj(fRepositoryName); + } } } diff --git a/projects/GKCore/GDModel/GDMResearchRecord.cs b/projects/GKCore/GDModel/GDMResearchRecord.cs index c0f0bdf8d..ce657fad2 100644 --- a/projects/GKCore/GDModel/GDMResearchRecord.cs +++ b/projects/GKCore/GDModel/GDMResearchRecord.cs @@ -311,5 +311,20 @@ public int IndexOfCommunication(GDMCommunicationRecord commRec) return result; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fResearchName); + hashCode.AddVal(fPriority); + hashCode.AddVal(fStatus); + hashCode.AddObj(fStartDate); + hashCode.AddObj(fStopDate); + hashCode.AddVal(fPercent); + ProcessHashes(ref hashCode, fTasks); + ProcessHashes(ref hashCode, fCommunications); + ProcessHashes(ref hashCode, fGroups); + } } } diff --git a/projects/GKCore/GDModel/GDMSourceCitation.cs b/projects/GKCore/GDModel/GDMSourceCitation.cs index 640528b95..fe5d9757b 100644 --- a/projects/GKCore/GDModel/GDMSourceCitation.cs +++ b/projects/GKCore/GDModel/GDMSourceCitation.cs @@ -233,5 +233,18 @@ public int GetValidCertaintyAssessment() int val = fCertaintyAssessment; return (val >= 0 && val <= 3) ? val : 0; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddVal(fCertaintyAssessment); + hashCode.AddObj(fData); + hashCode.AddObj(fPage); + hashCode.AddObj(fDescription); + ProcessHashes(ref hashCode, fMultimediaLinks); + ProcessHashes(ref hashCode, fNotes); + hashCode.AddObj(fText); + } } } diff --git a/projects/GKCore/GDModel/GDMSourceCitationData.cs b/projects/GKCore/GDModel/GDMSourceCitationData.cs index 092e41944..17638d290 100644 --- a/projects/GKCore/GDModel/GDMSourceCitationData.cs +++ b/projects/GKCore/GDModel/GDMSourceCitationData.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -88,5 +88,13 @@ public override bool IsEmpty() { return base.IsEmpty() && fDate.IsEmpty() && fText.IsEmpty(); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fDate); + hashCode.AddObj(fText); + } } } diff --git a/projects/GKCore/GDModel/GDMSourceData.cs b/projects/GKCore/GDModel/GDMSourceData.cs index b66b3258d..557b96df3 100644 --- a/projects/GKCore/GDModel/GDMSourceData.cs +++ b/projects/GKCore/GDModel/GDMSourceData.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -101,5 +102,14 @@ public override void ReplaceXRefs(GDMXRefReplacer map) fEvents.ReplaceXRefs(map); if (fNotes != null) fNotes.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fAgency); + ProcessHashes(ref hashCode, fEvents); + ProcessHashes(ref hashCode, fNotes); + } } } diff --git a/projects/GKCore/GDModel/GDMSourceEvent.cs b/projects/GKCore/GDModel/GDMSourceEvent.cs index b0e6ef133..d9e370dd1 100644 --- a/projects/GKCore/GDModel/GDMSourceEvent.cs +++ b/projects/GKCore/GDModel/GDMSourceEvent.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -84,5 +85,13 @@ public override void ReplaceXRefs(GDMXRefReplacer map) base.ReplaceXRefs(map); if (fPlace != null) fPlace.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fDate); + hashCode.AddObj(fPlace); + } } } diff --git a/projects/GKCore/GDModel/GDMSourceRecord.cs b/projects/GKCore/GDModel/GDMSourceRecord.cs index a688654f1..44d4a8030 100644 --- a/projects/GKCore/GDModel/GDMSourceRecord.cs +++ b/projects/GKCore/GDModel/GDMSourceRecord.cs @@ -279,5 +279,19 @@ public GDMRepositoryCitation FindRepository(GDMRepositoryRecord repoRec) return null; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fData); + hashCode.AddObj(fDate); + hashCode.AddObj(fOriginator); + hashCode.AddObj(fPublication); + ProcessHashes(ref hashCode, fRepositoryCitations); + hashCode.AddObj(fShortTitle); + hashCode.AddObj(fText); + hashCode.AddObj(fTitle); + } } } diff --git a/projects/GKCore/GDModel/GDMSpouseToFamilyLink.cs b/projects/GKCore/GDModel/GDMSpouseToFamilyLink.cs index 5bd6fc2bb..579c1e5db 100644 --- a/projects/GKCore/GDModel/GDMSpouseToFamilyLink.cs +++ b/projects/GKCore/GDModel/GDMSpouseToFamilyLink.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2022 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -34,5 +35,10 @@ public GDMSpouseToFamilyLink(string familyXRef) SetName(GEDCOMTagType.FAMS); XRef = familyXRef; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + } } } diff --git a/projects/GKCore/GDModel/GDMSubmissionRecord.cs b/projects/GKCore/GDModel/GDMSubmissionRecord.cs index 4a3395151..fb42cb0e1 100644 --- a/projects/GKCore/GDModel/GDMSubmissionRecord.cs +++ b/projects/GKCore/GDModel/GDMSubmissionRecord.cs @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -119,5 +120,17 @@ public override void ReplaceXRefs(GDMXRefReplacer map) fSubmitter.ReplaceXRefs(map); } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fFamilyFileName); + hashCode.AddObj(fTempleCode); + hashCode.AddVal(fGenerationsOfAncestors); + hashCode.AddVal(fGenerationsOfDescendants); + hashCode.AddVal(fOrdinanceProcessFlag); + hashCode.AddObj(fSubmitter); + } } } diff --git a/projects/GKCore/GDModel/GDMSubmitterRecord.cs b/projects/GKCore/GDModel/GDMSubmitterRecord.cs index 851c68401..54998c11a 100644 --- a/projects/GKCore/GDModel/GDMSubmitterRecord.cs +++ b/projects/GKCore/GDModel/GDMSubmitterRecord.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2023 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -18,6 +18,7 @@ * along with this program. If not, see . */ +using System; using GDModel.Providers.GEDCOM; namespace GDModel @@ -118,5 +119,15 @@ public void SetLanguage(int index, string value) } fLanguages[index].StringValue = value; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fAddress); + ProcessHashes(ref hashCode, fLanguages); + hashCode.AddObj(fName); + hashCode.AddObj(fRegisteredReference); + } } } diff --git a/projects/GKCore/GDModel/GDMTag.cs b/projects/GKCore/GDModel/GDMTag.cs index bc9a4dba5..edf1552dd 100644 --- a/projects/GKCore/GDModel/GDMTag.cs +++ b/projects/GKCore/GDModel/GDMTag.cs @@ -283,6 +283,29 @@ public virtual string ParseString(string strValue) } #endregion + + protected static void ProcessHashes(ref HashCode hashCode, GDMList tags) where T : GDMTag + { + if (tags == null) return; + + for (int i = 0; i < tags.Count; i++) { + var tag = tags[i]; + tag.ProcessHashes(ref hashCode); + } + } + + protected virtual void ProcessHashes(ref HashCode hashCode) + { + hashCode.AddVal(fId); + ProcessHashes(ref hashCode, fTags); + } + + public override int GetHashCode() + { + var result = new HashCode(); + ProcessHashes(ref result); + return result.ToHashCode(); + } } @@ -326,5 +349,12 @@ public override string ParseString(string strValue) fStringValue = strValue; return string.Empty; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fStringValue); + } } } diff --git a/projects/GKCore/GDModel/GDMTaskRecord.cs b/projects/GKCore/GDModel/GDMTaskRecord.cs index 66d7b9d2e..6aa6d3a12 100644 --- a/projects/GKCore/GDModel/GDMTaskRecord.cs +++ b/projects/GKCore/GDModel/GDMTaskRecord.cs @@ -120,5 +120,15 @@ public override void ReplaceXRefs(GDMXRefReplacer map) fGoal = GEDCOMUtils.EncloseXRef(map.FindNewXRef(GEDCOMUtils.CleanXRef(fGoal))); } } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fGoal); + hashCode.AddVal(fPriority); + hashCode.AddObj(fStartDate); + hashCode.AddObj(fStopDate); + } } } diff --git a/projects/GKCore/GDModel/GDMTime.cs b/projects/GKCore/GDModel/GDMTime.cs index 681bea06c..0fffe8cdb 100644 --- a/projects/GKCore/GDModel/GDMTime.cs +++ b/projects/GKCore/GDModel/GDMTime.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2019 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -115,5 +115,15 @@ internal void SetRawData(byte hour, byte minutes, byte seconds, short fraction) fSeconds = seconds; fFraction = fraction; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddVal(fHour); + hashCode.AddVal(fMinutes); + hashCode.AddVal(fSeconds); + hashCode.AddVal(fFraction); + } } } diff --git a/projects/GKCore/GDModel/GDMUserReference.cs b/projects/GKCore/GDModel/GDMUserReference.cs index 02b8ebf95..57dc5a379 100644 --- a/projects/GKCore/GDModel/GDMUserReference.cs +++ b/projects/GKCore/GDModel/GDMUserReference.cs @@ -1,6 +1,6 @@ /* * "GEDKeeper", the personal genealogical database editor. - * Copyright (C) 2009-2021 by Sergey V. Zhdanovskih. + * Copyright (C) 2009-2024 by Sergey V. Zhdanovskih. * * This file is part of "GEDKeeper". * @@ -60,5 +60,12 @@ public override void Assign(GDMTag source) fReferenceType = srcUserRef.fReferenceType; } + + protected override void ProcessHashes(ref HashCode hashCode) + { + base.ProcessHashes(ref hashCode); + + hashCode.AddObj(fReferenceType); + } } } diff --git a/projects/GKCore/GKCore/HashCode.cs b/projects/GKCore/GKCore/HashCode.cs index 2abd1da82..d1cfe818d 100644 --- a/projects/GKCore/GKCore/HashCode.cs +++ b/projects/GKCore/GKCore/HashCode.cs @@ -68,10 +68,12 @@ private static unsafe uint GenerateGlobalSeed() [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void Initialize(out uint v1, out uint v2, out uint v3, out uint v4) { - v1 = s_seed + Prime1 + Prime2; - v2 = s_seed + Prime2; - v3 = s_seed; - v4 = s_seed - Prime1; + unchecked { + v1 = s_seed + Prime1 + Prime2; + v2 = s_seed + Prime2; + v3 = s_seed; + v4 = s_seed - Prime1; + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -83,35 +85,45 @@ private static uint RotateLeft(uint value, int offset) [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint Round(uint hash, uint input) { - return RotateLeft(hash + input * Prime2, 13) * Prime1; + unchecked { + return RotateLeft(hash + input * Prime2, 13) * Prime1; + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint QueueRound(uint hash, uint queuedValue) { - return RotateLeft(hash + queuedValue * Prime3, 17) * Prime4; + unchecked { + return RotateLeft(hash + queuedValue * Prime3, 17) * Prime4; + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint MixState(uint v1, uint v2, uint v3, uint v4) { - return RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18); + unchecked { + return RotateLeft(v1, 1) + RotateLeft(v2, 7) + RotateLeft(v3, 12) + RotateLeft(v4, 18); + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint MixEmptyState() { - return s_seed + Prime5; + unchecked { + return s_seed + Prime5; + } } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint MixFinal(uint hash) { - hash ^= hash >> 15; - hash *= Prime2; - hash ^= hash >> 13; - hash *= Prime3; - hash ^= hash >> 16; + unchecked { + hash ^= hash >> 15; + hash *= Prime2; + hash ^= hash >> 13; + hash *= Prime3; + hash ^= hash >> 16; + } return hash; } @@ -150,7 +162,7 @@ public void AddHash(int value) // To see what's really going on here, have a look at the Combine // methods. - uint val = (uint)value; + uint val = unchecked((uint)value); // Storing the value of _length locally shaves of quite a few bytes // in the resulting machine code. @@ -213,7 +225,7 @@ public int ToHashCode() } hash = MixFinal(hash); - return (int)hash; + return unchecked((int)hash); } } } diff --git a/projects/GKCore/GKCore/NetDiff/DiffUtil.cs b/projects/GKCore/GKCore/NetDiff/DiffUtil.cs index 661d85b66..784204e25 100644 --- a/projects/GKCore/GKCore/NetDiff/DiffUtil.cs +++ b/projects/GKCore/GKCore/NetDiff/DiffUtil.cs @@ -18,6 +18,7 @@ public enum DiffStatus Deleted, Inserted, Modified, + DeepModified, } @@ -186,10 +187,15 @@ public static char GetStatusChar(DiffStatus status) { switch (status) { - case DiffStatus.Equal: return '='; - case DiffStatus.Deleted: return '-'; - case DiffStatus.Inserted: return '+'; - case DiffStatus.Modified: return '≠'; + case DiffStatus.Equal: + return '='; + case DiffStatus.Deleted: + return '-'; + case DiffStatus.Inserted: + return '+'; + case DiffStatus.Modified: + case DiffStatus.DeepModified: + return '≠'; } throw new System.Exception(); diff --git a/projects/GKCore/GKCore/Tools/SyncTool.cs b/projects/GKCore/GKCore/Tools/SyncTool.cs index 765e326bd..019225c53 100644 --- a/projects/GKCore/GKCore/Tools/SyncTool.cs +++ b/projects/GKCore/GKCore/Tools/SyncTool.cs @@ -70,9 +70,16 @@ private void CheckModified() foreach (var diffRes in Results) { if (diffRes.Status != DiffStatus.Equal) continue; - if ((diffRes.Obj1.XRef != diffRes.Obj2.XRef) || (diffRes.Obj1.ChangeDate.ChangeDateTime != diffRes.Obj2.ChangeDate.ChangeDateTime)) { + var rec1 = diffRes.Obj1; + var rec2 = diffRes.Obj2; + + if ((rec1.XRef != rec2.XRef) || (rec1.ChangeDate.ChangeDateTime != rec2.ChangeDate.ChangeDateTime)) { diffRes.Status = DiffStatus.Modified; } + + if (rec1.GetHashCode() != rec2.GetHashCode()) { + diffRes.Status = DiffStatus.DeepModified; + } } } diff --git a/projects/plugins/GKTreeSyncPlugin/TSForm.cs b/projects/plugins/GKTreeSyncPlugin/TSForm.cs index 65b6992be..264160c79 100644 --- a/projects/plugins/GKTreeSyncPlugin/TSForm.cs +++ b/projects/plugins/GKTreeSyncPlugin/TSForm.cs @@ -125,9 +125,10 @@ private void UpdateLists() break; case DiffStatus.Modified: + case DiffStatus.DeepModified: item1 = diffChar + " " + compRes.Obj1.XRef; item2 = diffChar + " " + compRes.Obj2.XRef; - backColor = Color.Yellow; + backColor = (compRes.Status == DiffStatus.Modified) ? Color.Yellow : Color.Orange; break; }