@@ -13,7 +13,9 @@ use strum::EnumCount;
1313use crate :: block:: Block ;
1414use crate :: context:: ScopeContext ;
1515use crate :: everything:: Everything ;
16- use crate :: helpers:: { dup_error, exact_dup_advice, exact_dup_error, TigerHashMap , TigerHashSet } ;
16+ use crate :: helpers:: {
17+ dup_error, exact_dup_advice, exact_dup_error, DupReporter , TigerHashMap , TigerHashSet ,
18+ } ;
1719use crate :: item:: Item ;
1820use crate :: lowercase:: Lowercase ;
1921use crate :: token:: Token ;
@@ -50,17 +52,7 @@ impl Default for Db {
5052
5153impl Db {
5254 pub fn add ( & mut self , item : Item , key : Token , block : Block , kind : Box < dyn DbKind > ) {
53- if let Some ( other) = self . database [ item as usize ] . get ( key. as_str ( ) ) {
54- if other. key . loc . ptr . kind >= key. loc . ptr . kind {
55- if other. block . equivalent ( & block) {
56- exact_dup_error ( & key, & other. key , & item. to_string ( ) ) ;
57- } else {
58- dup_error ( & key, & other. key , & item. to_string ( ) ) ;
59- }
60- }
61- }
62- self . items_lc [ item as usize ] . insert ( Lowercase :: new ( key. as_str ( ) ) , key. as_str ( ) ) ;
63- self . database [ item as usize ] . insert ( key. as_str ( ) , DbEntry { key, block, kind } ) ;
55+ self . add_with_reporter ( item, key, block, kind, exact_dup_error) ;
6456 }
6557
6658 #[ allow( dead_code) ]
@@ -71,17 +63,51 @@ impl Db {
7163 block : Block ,
7264 kind : Box < dyn DbKind > ,
7365 ) {
74- if let Some ( other) = self . database [ item as usize ] . get ( key. as_str ( ) ) {
75- if other. key . loc . ptr . kind >= key. loc . ptr . kind {
76- if other. block . equivalent ( & block) {
77- exact_dup_advice ( & key, & other. key , & item. to_string ( ) ) ;
78- } else {
79- dup_error ( & key, & other. key , & item. to_string ( ) ) ;
66+ self . add_with_reporter ( item, key, block, kind, exact_dup_advice) ;
67+ }
68+
69+ fn add_with_reporter (
70+ & mut self ,
71+ item : Item ,
72+ key : Token ,
73+ block : Block ,
74+ kind : Box < dyn DbKind > ,
75+ exact_dup_reporter : DupReporter ,
76+ ) {
77+ use std:: collections:: hash_map:: Entry ;
78+
79+ match self . database [ item as usize ] . entry ( key. as_str ( ) ) {
80+ Entry :: Occupied ( mut occupied_entry) => {
81+ let new = DbEntry { key, block, kind } ;
82+ let existing = occupied_entry. get ( ) ;
83+
84+ let ( keep, overwriten) =
85+ // Just compare the top loc, not the whole stack
86+ if new. key . loc . ptr > existing. key . loc . ptr {
87+ ( & new, existing)
88+ } else {
89+ ( existing, & new)
90+ } ;
91+
92+ if overwriten. key . loc . ptr . kind >= keep. key . loc . ptr . kind {
93+ if overwriten. block . equivalent ( & keep. block ) {
94+ exact_dup_reporter ( & keep. key , & overwriten. key , & item. to_string ( ) ) ;
95+ } else {
96+ dup_error ( & keep. key , & overwriten. key , & item. to_string ( ) ) ;
97+ }
8098 }
99+ // Update the db if the new entry is the one we're keeping
100+ if & raw const new == & raw const * keep {
101+ self . items_lc [ item as usize ]
102+ . insert ( Lowercase :: new ( new. key . as_str ( ) ) , new. key . as_str ( ) ) ;
103+ occupied_entry. insert ( new) ;
104+ }
105+ }
106+ Entry :: Vacant ( vacant_entry) => {
107+ self . items_lc [ item as usize ] . insert ( Lowercase :: new ( key. as_str ( ) ) , key. as_str ( ) ) ;
108+ vacant_entry. insert ( DbEntry { key, block, kind } ) ;
81109 }
82110 }
83- self . items_lc [ item as usize ] . insert ( Lowercase :: new ( key. as_str ( ) ) , key. as_str ( ) ) ;
84- self . database [ item as usize ] . insert ( key. as_str ( ) , DbEntry { key, block, kind } ) ;
85111 }
86112
87113 #[ cfg( feature = "hoi4" ) ]
0 commit comments