@@ -192,10 +192,11 @@ class map_jnse: public Json::map_jne {
192
192
public:
193
193
194
194
#define NSOPT \
195
- NsReferAll, /* reference all ns values - local and remote */ \
196
- NsMove, /* move local ns values, reference remote entriess */ \
197
- NsUpdate, /* same as NsMove, but for non-existent (new) entries only*/ \
198
- NsMoveAll /* move all ns values - local & remote */
195
+ NsUpdateRef, /* reference all ns values - only non-existent ones */ \
196
+ NsReferAll, /* reference all ns values - local and remote */ \
197
+ NsMove, /* move local ns values, reference remote entriess */ \
198
+ NsUpdate, /* same as NsMove, but for non-existent (new) entries only*/ \
199
+ NsMoveAll /* move all ns values - local & remote */
199
200
ENUM (NsOpType, NSOPT)
200
201
201
202
void sync_out (Json::map_jne &to, NsOpType nsopt);
@@ -208,11 +209,16 @@ class map_jnse: public Json::map_jne {
208
209
209
210
void map_jnse::sync_out (Json::map_jne &to, NsOpType nsopt) {
210
211
// sync all entries from this map to Json namespace `to``
211
- if (nsopt = = NsOpType::NsReferAll) { // reference all entries
212
+ if (nsopt < = NsOpType::NsReferAll) { // reference all entries
212
213
for (auto &ns: *this ) { // for all entries in this map
213
214
if (ns.KEY .front () < ' ' and ns.KEY .front () > ' \0 ' ) continue ; // sync only valid namespaces
214
- auto ip = to.emplace (ns.KEY , Json::JnEntry{}); // ip: insertion pair
215
- ip.first ->VALUE .ptr (&ns.VALUE .ref ()); // override existing or refer new
215
+ auto found = to.find (ns.KEY );
216
+ if (found == to.end ())
217
+ to.emplace (ns.KEY , Json::JnEntry{}).first ->VALUE .ptr (&ns.VALUE .ref ());
218
+ else {
219
+ if (nsopt == NsOpType::NsUpdateRef) continue ;
220
+ found->VALUE .ptr (&ns.VALUE .ref ());
221
+ }
216
222
}
217
223
return ;
218
224
}
@@ -236,7 +242,7 @@ void map_jnse::sync_out(Json::map_jne &to, NsOpType nsopt) {
236
242
237
243
void map_jnse::sync_in (Json::map_jne &from, NsOpType nsopt) {
238
244
// sync all entries `from` map according to given handling type `nsopt`
239
- if (nsopt = = NsOpType::NsReferAll) { // reference all entries
245
+ if (nsopt < = NsOpType::NsReferAll) { // reference all entries
240
246
for (auto &ns: from) { // for all entries in from
241
247
if (ns.KEY .front () < ' ' and ns.KEY .front () > ' \0 ' ) continue ; // sync only valid namespaces
242
248
auto mp = emplace (ns.KEY , Json::JnEntry{}); // mp: my pair
@@ -479,6 +485,8 @@ class Jtc {
479
485
480
486
size_t group{0 };
481
487
size_t counter{0 };
488
+
489
+ COUTABLE (Grouping, group, counter) // for debugs only
482
490
};
483
491
484
492
@@ -634,6 +642,7 @@ class Jtc {
634
642
size_t jscur_{0 }; // current walk in jsrc_
635
643
map<Json::iterator*, map_jnse>
636
644
wns_; // namespaces for walked (-w) paths
645
+ map_jnse ins_; // holds interleaved namespaces
637
646
Json::iterator * last_dwi_ptr_{nullptr };
638
647
Jnode hwlk_{ARY{STR{}}}; // last walked value (interpolated)
639
648
set<string> c2a_; // used in jsonized_output_obj_()
@@ -1947,6 +1956,7 @@ void Jtc::output_by_iterator(Json::iterator &wi, Grouping grp) {
1947
1956
wns_[&wi][WLK_HPFX] = move (hwlk_[0 ]);
1948
1957
hwlk_[0 ].type (Jnode::Neither);
1949
1958
}
1959
+
1950
1960
if (opt ()[CHR (OPT_TMP)].hits () > 0 ) { // interpolate each tmp per walk
1951
1961
// in all other cases - templates are round-robin applied onto each walk iteration
1952
1962
if (is_tpw_) // template per walk:
@@ -1958,10 +1968,13 @@ void Jtc::output_by_iterator(Json::iterator &wi, Grouping grp) {
1958
1968
opt ()[CHR (OPT_TMP)].str (tpw_.size () + 1 ));
1959
1969
size_t tmp_idx = is_tpw_?
1960
1970
wi.walk_uid (): key_++ % (opt ()[CHR (OPT_TMP)].size () - 1 );
1961
- tmp = Json::interpolate (tpw_[tmp_idx], wi, wns_[&wi]);
1971
+ ins_.sync_out (wns_[&wi], map_jnse::NsUpdateRef); // this is done so that walks could
1972
+ tmp = Json::interpolate (tpw_[tmp_idx], wi, wns_[&wi]); // propagate namespaces interleaved
1973
+ ins_.sync_in (wns_[&wi], map_jnse::NsReferAll); // way rather than sequentially
1962
1974
if (use_hpfx_) hwlk_ = move (ARY{tmp.root ()});
1963
1975
}
1964
1976
1977
+
1965
1978
if (use_hpfx_ and hwlk_[0 ].is_neither ()) { // templating failed or was none
1966
1979
if (wi->has_label ()) hwlk_ = move (OBJ{LBL{wi->label (), *wi}}); // preserve also the label if exist
1967
1980
else hwlk_ = move (ARY{*wi});
@@ -2618,9 +2631,10 @@ void Jtc::walk_interleaved_(wlk_subscr Jtc::* subscriber) {
2618
2631
subscriber_ = subscriber;
2619
2632
deque<deq_jit> wpi; // wpi holds queues of iterators
2620
2633
2621
- cr_.global_ns ().sync_out (json ().ns (), map_jnse::NsOpType::NsReferAll);
2622
2634
2623
2635
for (const auto &walk_str: opt ()[CHR (OPT_WLK)]) { // process each -w arguments
2636
+ cr_.global_ns ().sync_out (json ().clear_ns ().ns (), map_jnse::NsOpType::NsReferAll);
2637
+
2624
2638
// wpi: push back deq_jit init'ed with -w inited walk
2625
2639
wpi.push_back ( deq_jit{json ().walk (walk_str.find_first_not_of (" " ) == string::npos?
2626
2640
" " : walk_str, Json::Keep_cache)} );
@@ -2630,9 +2644,7 @@ void Jtc::walk_interleaved_(wlk_subscr Jtc::* subscriber) {
2630
2644
}
2631
2645
auto & dwi = wpi.back (); // dwi: deque<Json::iterator>
2632
2646
while (dwi.back () != dwi.back ().end ()) { // extend all iterators until end
2633
- // cerr << " extending interators" << endl;
2634
- if (wns_.empty ()) wns_[&dwi.back ()].sync_in (json ().ns (), map_jnse::NsOpType::NsMoveAll);
2635
- else wns_[&dwi.back ()].sync_in (json ().ns (), map_jnse::NsOpType::NsMove);
2647
+ wns_[&dwi.back ()].sync_in (json ().ns (), map_jnse::NsMove);
2636
2648
if (use_hpfx_) {
2637
2649
wns_[&dwi.back ()][WLK_RSTH] = BUL{wns_[&dwi.back ()].erase (WLK_HPFX)? true : false };
2638
2650
if (dwi.back ()->has_label ()) hwlk_ = move (OBJ{ LBL{dwi.back ()->label (), *dwi.back ()} });
@@ -2644,11 +2656,11 @@ void Jtc::walk_interleaved_(wlk_subscr Jtc::* subscriber) {
2644
2656
++dwi.back (); // json.ns now is partial
2645
2657
}
2646
2658
dwi.pop_back (); // remove last (->end()) iterator
2659
+ // json.ns() may hold now the latest updated namespace while wns_ might not even have been
2660
+ // updated (e.g.: when walk has ended as <>F, or out of iterations), thus require syncing
2661
+ wns_[last_dwi_ptr_].sync_in (json ().ns (), map_jnse::NsOpType::NsUpdate);
2647
2662
}
2648
2663
hwlk_ = move (ARY{STR{}}); // reset hwlk_ to init value
2649
- // json.ns() may hold now the latest updated namespace while wns_ might not even have been
2650
- // updated (e.g.: when walk has ended as <>F, or out of iterations), thus require syncing
2651
- wns_[last_dwi_ptr_].sync_in (json ().ns (), map_jnse::NsOpType::NsUpdate);
2652
2664
2653
2665
is_multi_walk_ = opt ()[CHR (OPT_WLK)].hits () > 1 or // i.e. -w.. -w.., else (one -w..)
2654
2666
wpi.size () > 1 or // wpi.size > 1, otherwise:
0 commit comments