GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/zserio/Walker.h Lines: 241 241 100.0 %
Date: 2023-12-13 14:51:09 Branches: 141 248 56.9 %

Line Branch Exec Source
1
#ifndef ZSERIO_WALKER_H_INC
2
#define ZSERIO_WALKER_H_INC
3
4
#include <functional>
5
#include <regex>
6
#include <algorithm>
7
8
#include "zserio/IReflectable.h"
9
#include "zserio/ITypeInfo.h"
10
#include "zserio/WalkerConst.h"
11
#include "zserio/IWalkObserver.h"
12
#include "zserio/IWalkFilter.h"
13
#include "zserio/TypeInfoUtil.h"
14
#include "zserio/StringConvertUtil.h"
15
#include "zserio/String.h"
16
#include "zserio/Vector.h"
17
18
namespace zserio
19
{
20
21
template <typename ALLOC>
22
class BasicDefaultWalkFilter;
23
24
/**
25
 * Walker through zserio objects, based on generated type info (see -withTypeInfoCode) and
26
 * reflectable interface (see -withReflectionCode).
27
 */
28
template <typename ALLOC = std::allocator<uint8_t>>
29
class BasicWalker
30
{
31
public:
32
    /**
33
     * Constructor using default walk filter.
34
     *
35
     * \param walkObserver Observer to use during walking.
36
     */
37
    explicit BasicWalker(IBasicWalkObserver<ALLOC>& walkObserver);
38
39
    /**
40
     * Constructor.
41
     *
42
     * \param walkObserver Observer to use during walking.
43
     * \param walkFilter Walk filter to use.
44
     */
45
    BasicWalker(IBasicWalkObserver<ALLOC>& walkObserver, IBasicWalkFilter<ALLOC>& walkFilter);
46
47
    /**
48
     * Method generated by default.
49
     */
50
56
    ~BasicWalker() = default;
51
52
    /**
53
     * Copying and moving is disallowed!
54
     * \{
55
     */
56
    BasicWalker(const BasicWalker& other) = delete;
57
    BasicWalker& operator=(const BasicWalker& other) = delete;
58
59
    BasicWalker(BasicWalker&& other) = delete;
60
    BasicWalker& operator=(BasicWalker&& other) = delete;
61
    /**
62
     * \}
63
     */
64
65
    /**
66
     * Walks given reflectable zserio compound object.
67
     *
68
     * \param compound Zserio compound object to walk.
69
     */
70
    void walk(const IBasicReflectableConstPtr<ALLOC>& compound);
71
72
private:
73
    void walkFields(const IBasicReflectableConstPtr<ALLOC>& compound, const IBasicTypeInfo<ALLOC>& typeInfo);
74
    bool walkField(const IBasicReflectableConstPtr<ALLOC>& reflectable, const BasicFieldInfo<ALLOC>& fieldInfo);
75
    bool walkFieldValue(const IBasicReflectableConstPtr<ALLOC>& reflectable,
76
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex = WALKER_NOT_ELEMENT);
77
78
    IBasicWalkObserver<ALLOC>& m_walkObserver;
79
    BasicDefaultWalkFilter<ALLOC> m_defaultWalkFilter;
80
    IBasicWalkFilter<ALLOC>& m_walkFilter;
81
};
82
83
/**
84
 * Default walk observer which just does nothing.
85
 */
86
template <typename ALLOC = std::allocator<uint8_t>>
87
class BasicDefaultWalkObserver : public IBasicWalkObserver<ALLOC>
88
{
89
public:
90
    /**
91
     * Method generated by default.
92
     * \{
93
     */
94
    BasicDefaultWalkObserver() = default;
95
14
    ~BasicDefaultWalkObserver() override = default;
96
    /**
97
     * \}
98
     */
99
100
    /**
101
     * Copying and moving is disallowed!
102
     * \{
103
     */
104
    BasicDefaultWalkObserver(const BasicDefaultWalkObserver& other) = delete;
105
    BasicDefaultWalkObserver& operator=(const BasicDefaultWalkObserver& other) = delete;
106
107
    BasicDefaultWalkObserver(BasicDefaultWalkObserver&& other) = delete;
108
    BasicDefaultWalkObserver& operator=(BasicDefaultWalkObserver&& other) = delete;
109
    /**
110
     * \}
111
     */
112
113
12
    void beginRoot(const IBasicReflectableConstPtr<ALLOC>&) override {}
114
12
    void endRoot(const IBasicReflectableConstPtr<ALLOC>&) override {}
115
116
3
    void beginArray(const IBasicReflectableConstPtr<ALLOC>&,
117
3
            const BasicFieldInfo<ALLOC>&) override {}
118
3
    void endArray(const IBasicReflectableConstPtr<ALLOC>&,
119
3
            const BasicFieldInfo<ALLOC>&) override {}
120
121
3
    void beginCompound(const IBasicReflectableConstPtr<ALLOC>&,
122
3
            const BasicFieldInfo<ALLOC>&, size_t) override {}
123
3
    void endCompound(const IBasicReflectableConstPtr<ALLOC>&,
124
3
            const BasicFieldInfo<ALLOC>&, size_t) override {}
125
126
9
    void visitValue(const IBasicReflectableConstPtr<ALLOC>&,
127
9
            const BasicFieldInfo<ALLOC>&, size_t) override {}
128
};
129
130
/**
131
 * Default walk filter which filters nothing.
132
 */
133
template <typename ALLOC = std::allocator<uint8_t>>
134
class BasicDefaultWalkFilter : public IBasicWalkFilter<ALLOC>
135
{
136
public:
137
    /**
138
     * Method generated by default.
139
     * \{
140
     */
141
84
    BasicDefaultWalkFilter() = default;
142

92
    ~BasicDefaultWalkFilter() override = default;
143
    /**
144
     * \}
145
     */
146
147
    /**
148
     * Copying and moving is disallowed!
149
     * \{
150
     */
151
    BasicDefaultWalkFilter(const BasicDefaultWalkFilter& other) = delete;
152
    BasicDefaultWalkFilter& operator=(const BasicDefaultWalkFilter& other) = delete;
153
154
    BasicDefaultWalkFilter(BasicDefaultWalkFilter&& other) = delete;
155
    BasicDefaultWalkFilter& operator=(BasicDefaultWalkFilter&& other) = delete;
156
    /**
157
     * \}
158
     */
159
160
5
    bool beforeArray(const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>&) override
161
    {
162
5
        return true;
163
    }
164
165
5
    bool afterArray(const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>&) override
166
    {
167
5
        return true;
168
    }
169
170
12
    bool beforeCompound(const IBasicReflectableConstPtr<ALLOC>&,
171
            const BasicFieldInfo<ALLOC>&, size_t) override
172
    {
173
12
        return true;
174
    }
175
176
12
    bool afterCompound(const IBasicReflectableConstPtr<ALLOC>&,
177
            const BasicFieldInfo<ALLOC>&, size_t) override
178
    {
179
12
        return true;
180
    }
181
182
48
    bool beforeValue(const IBasicReflectableConstPtr<ALLOC>&,
183
            const BasicFieldInfo<ALLOC>&, size_t) override
184
    {
185
48
        return true;
186
    }
187
188
48
    bool afterValue(const IBasicReflectableConstPtr<ALLOC>&,
189
            const BasicFieldInfo<ALLOC>&, size_t) override
190
    {
191
48
        return true;
192
    }
193
};
194
195
/**
196
 * Walk filter which allows to walk only to the given maximum depth.
197
 */
198
template <typename ALLOC = std::allocator<uint8_t>>
199
class BasicDepthWalkFilter : public IBasicWalkFilter<ALLOC>
200
{
201
public:
202
    /**
203
     * Constructor.
204
     *
205
     * \param maxDepth Maximum depth to walk to.
206
     */
207
    explicit BasicDepthWalkFilter(size_t maxDepth);
208
209
    /**
210
     * Method generated by default.
211
     */
212

7
    ~BasicDepthWalkFilter() override = default;
213
214
    /**
215
     * Copying is disallowed!
216
     * \{
217
     */
218
    BasicDepthWalkFilter(const BasicDepthWalkFilter& other) = delete;
219
    BasicDepthWalkFilter& operator=(const BasicDepthWalkFilter& other) = delete;
220
221
    BasicDepthWalkFilter(BasicDepthWalkFilter&& other) = delete;
222
    BasicDepthWalkFilter& operator=(BasicDepthWalkFilter&& other) = delete;
223
    /**
224
     * \}
225
     */
226
227
    bool beforeArray(const IBasicReflectableConstPtr<ALLOC>& array,
228
            const BasicFieldInfo<ALLOC>& fieldInfo) override;
229
    bool afterArray(const IBasicReflectableConstPtr<ALLOC>& array,
230
            const BasicFieldInfo<ALLOC>& fieldInfo) override;
231
232
    bool beforeCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
233
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
234
    bool afterCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
235
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
236
237
    bool beforeValue(const IBasicReflectableConstPtr<ALLOC>& value,
238
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
239
    bool afterValue(const IBasicReflectableConstPtr<ALLOC>& value,
240
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
241
242
private:
243
    bool enterDepthLevel();
244
    bool leaveDepthLevel();
245
246
    size_t m_maxDepth;
247
    size_t m_depth;
248
};
249
250
/**
251
 * Walk filter which allows to walk only paths matching the given regex.
252
 *
253
 * The path is constructed from field names within the root object, thus the root object itself
254
 * is not part of the path.
255
 *
256
 * Array elements have the index appended to the path so that e.g. "compound.arrayField[0]" will match
257
 * only the first element in the array "arrayField".
258
 */
259
template <typename ALLOC = std::allocator<uint8_t>>
260
class BasicRegexWalkFilter : public IBasicWalkFilter<ALLOC>
261
{
262
public:
263
    /**
264
     * Constructor.
265
     *
266
     * \param pathRegex Path regex to use for filtering.
267
     */
268
    explicit BasicRegexWalkFilter(const char* pathRegex, const ALLOC& allocator = ALLOC());
269
270
    /**
271
     * Method generated by default.
272
     */
273
8
    ~BasicRegexWalkFilter() override = default;
274
275
    /**
276
     * Copying is disallowed!
277
     * \{
278
     */
279
    BasicRegexWalkFilter(const BasicRegexWalkFilter& other) = delete;
280
    BasicRegexWalkFilter& operator=(const BasicRegexWalkFilter& other) = delete;
281
282
    BasicRegexWalkFilter(BasicRegexWalkFilter&& other) = delete;
283
    BasicRegexWalkFilter& operator=(BasicRegexWalkFilter&& other) = delete;
284
    /**
285
     * \}
286
     */
287
288
    bool beforeArray(const IBasicReflectableConstPtr<ALLOC>& array,
289
            const BasicFieldInfo<ALLOC>& fieldInfo) override;
290
    bool afterArray(const IBasicReflectableConstPtr<ALLOC>& array,
291
            const BasicFieldInfo<ALLOC>& fieldInfo) override;
292
293
    bool beforeCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
294
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
295
    bool afterCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
296
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
297
298
    bool beforeValue(const IBasicReflectableConstPtr<ALLOC>& value,
299
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
300
    bool afterValue(const IBasicReflectableConstPtr<ALLOC>& value,
301
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
302
303
private:
304
    void appendPath(const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex);
305
    void popPath(const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex);
306
    string<ALLOC> getCurrentPath() const;
307
    bool matchSubtree(const IBasicReflectableConstPtr<ALLOC>& value,
308
            const BasicFieldInfo<ALLOC>& fieldInfo) const;
309
310
    vector<string<ALLOC>, ALLOC> m_currentPath;
311
    std::regex m_pathRegex;
312
    ALLOC m_allocator; // TODO[Mi-L@]: Check how std::regex_match allocates when results are omitted!
313
};
314
315
/**
316
 * Walk filter which allows to walk only to the given maximum array length.
317
 */
318
template <typename ALLOC = std::allocator<uint8_t>>
319
class BasicArrayLengthWalkFilter : public IBasicWalkFilter<ALLOC>
320
{
321
public:
322
    /**
323
     * Constructor.
324
     *
325
     * \param maxArrayLength Maximum array length to walk to.
326
     */
327
    explicit BasicArrayLengthWalkFilter(size_t maxArrayLength);
328
329
    /**
330
     * Method generated by default.
331
     */
332
1
    ~BasicArrayLengthWalkFilter() override = default;
333
334
    /**
335
     * Copying and moving is disallowed!
336
     * \{
337
     */
338
    BasicArrayLengthWalkFilter(const BasicArrayLengthWalkFilter& other) = delete;
339
    BasicArrayLengthWalkFilter& operator=(const BasicArrayLengthWalkFilter& other) = delete;
340
341
    BasicArrayLengthWalkFilter(BasicArrayLengthWalkFilter&& other) = delete;
342
    BasicArrayLengthWalkFilter& operator=(BasicArrayLengthWalkFilter&& other) = delete;
343
    /**
344
     * \}
345
     */
346
347
    bool beforeArray(const IBasicReflectableConstPtr<ALLOC>& array,
348
            const BasicFieldInfo<ALLOC>& fieldInfo) override;
349
    bool afterArray(const IBasicReflectableConstPtr<ALLOC>& array,
350
            const BasicFieldInfo<ALLOC>& fieldInfo) override;
351
352
    bool beforeCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
353
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
354
    bool afterCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
355
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
356
357
    bool beforeValue(const IBasicReflectableConstPtr<ALLOC>& value,
358
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
359
    bool afterValue(const IBasicReflectableConstPtr<ALLOC>& value,
360
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
361
362
private:
363
    bool filterArrayElement(size_t elementIndex);
364
365
    size_t m_maxArrayLength;
366
};
367
368
/**
369
 * Walk filter which implements composition of particular filters.
370
 *
371
 * The filters are called sequentially and logical and is applied on theirs results.
372
 * Note that all filters are always called.
373
 */
374
template <typename ALLOC = std::allocator<uint8_t>>
375
class BasicAndWalkFilter : public IBasicWalkFilter<ALLOC>
376
{
377
public:
378
    using WalkFilterRef = std::reference_wrapper<IBasicWalkFilter<ALLOC>>;
379
    using WalkFilters = vector<WalkFilterRef, ALLOC>;
380
381
    /**
382
     * Constructor.
383
     *
384
     * \param walkFilters List of filters to use in composition.
385
     */
386
    explicit BasicAndWalkFilter(const WalkFilters& walkFilters);
387
388
    /**
389
     * Method generated by default.
390
     */
391
4
    ~BasicAndWalkFilter() override = default;
392
393
    /**
394
     * Copying and moving is disallowed!
395
     * \{
396
     */
397
    BasicAndWalkFilter(const BasicAndWalkFilter& other) = delete;
398
    BasicAndWalkFilter& operator=(const BasicAndWalkFilter& other) = delete;
399
400
    BasicAndWalkFilter(BasicAndWalkFilter&& other) = delete;
401
    BasicAndWalkFilter& operator=(BasicAndWalkFilter&& other) = delete;
402
    /**
403
     * \}
404
     */
405
406
    bool beforeArray(const IBasicReflectableConstPtr<ALLOC>& array,
407
            const BasicFieldInfo<ALLOC>& fieldInfo) override;
408
    bool afterArray(const IBasicReflectableConstPtr<ALLOC>& array,
409
            const BasicFieldInfo<ALLOC>& fieldInfo) override;
410
411
    bool beforeCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
412
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
413
    bool afterCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
414
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
415
416
    bool beforeValue(const IBasicReflectableConstPtr<ALLOC>& value,
417
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
418
    bool afterValue(const IBasicReflectableConstPtr<ALLOC>& value,
419
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override;
420
421
private:
422
    template <typename FILTER_FUNC, typename ...ARGS>
423
24
    bool applyFilters(FILTER_FUNC filterFunc, ARGS... args)
424
    {
425
24
        bool result = true;
426

60
        for (IBasicWalkFilter<ALLOC>& walkFilter : m_walkFilters)
427


36
            result &= (walkFilter.*filterFunc)(args...);
428
24
        return result;
429
    }
430
431
    WalkFilters m_walkFilters;
432
};
433
434
/** Typedefs to walker related classes provided for convenience - using default std::allocator<uint8_t>. */
435
/** \{ */
436
using Walker = BasicWalker<>;
437
using DefaultWalkObserver = BasicDefaultWalkObserver<>;
438
using DefaultWalkFilter = BasicDefaultWalkFilter<>;
439
using DepthWalkFilter = BasicDepthWalkFilter<>;
440
using RegexWalkFilter = BasicRegexWalkFilter<>;
441
using ArrayLengthWalkFilter = BasicArrayLengthWalkFilter<>;
442
using AndWalkFilter = BasicAndWalkFilter<>;
443
/** \} */
444
445
template <typename ALLOC>
446
2
BasicWalker<ALLOC>::BasicWalker(IBasicWalkObserver<ALLOC>& walkObserver) :
447
2
        m_walkObserver(walkObserver), m_walkFilter(m_defaultWalkFilter)
448
2
{}
449
450
template <typename ALLOC>
451
54
BasicWalker<ALLOC>::BasicWalker(IBasicWalkObserver<ALLOC>& walkObserver, IBasicWalkFilter<ALLOC>& walkFilter) :
452
54
        m_walkObserver(walkObserver), m_walkFilter(walkFilter)
453
54
{}
454
455
template <typename ALLOC>
456
56
void BasicWalker<ALLOC>::walk(const IBasicReflectableConstPtr<ALLOC>& compound)
457
{
458

56
    if (!compound)
459

1
        throw CppRuntimeException("Walker: Root object cannot be NULL!");
460
461
55
    const IBasicTypeInfo<ALLOC>& typeInfo = compound->getTypeInfo();
462

55
    if (!TypeInfoUtil::isCompound(typeInfo.getSchemaType()))
463
    {
464




2
        throw CppRuntimeException("Walker: Root object '") << typeInfo.getSchemaName() <<
465
2
                "' is not a compound type!";
466
    }
467
468
54
    m_walkObserver.beginRoot(compound);
469
54
    walkFields(compound, typeInfo);
470
54
    m_walkObserver.endRoot(compound);
471
54
}
472
473
template <typename ALLOC>
474
71
void BasicWalker<ALLOC>::walkFields(const IBasicReflectableConstPtr<ALLOC>& compound,
475
        const IBasicTypeInfo<ALLOC>& typeInfo)
476
{
477

71
    if (TypeInfoUtil::hasChoice(typeInfo.getSchemaType()))
478
    {
479

21
        StringView compoundChoice = compound->getChoice();
480

21
        if (!compoundChoice.empty())
481
        {
482

18
            Span<const BasicFieldInfo<ALLOC>> fields = typeInfo.getFields();
483
18
            auto fieldsIt = std::find_if(fields.begin(), fields.end(),
484
38
                    [compoundChoice](const BasicFieldInfo<ALLOC>& fieldInfo) {
485

56
                            return fieldInfo.schemaName == compoundChoice; });
486

18
            if (fieldsIt != fields.end())
487
            {
488


17
                walkField(compound->getField(compoundChoice), *fieldsIt);
489
            }
490
        }
491
        // else uninitialized or empty branch
492
    }
493
    else
494
    {
495

122
        for (const BasicFieldInfo<ALLOC>& fieldInfo : typeInfo.getFields())
496
        {
497


75
            if (!walkField(compound->getField(fieldInfo.schemaName), fieldInfo))
498
3
                break;
499
        }
500
    }
501
71
}
502
503
template <typename ALLOC>
504
92
bool BasicWalker<ALLOC>::walkField(
505
        const IBasicReflectableConstPtr<ALLOC>& reflectable, const BasicFieldInfo<ALLOC>& fieldInfo)
506
{
507



92
    if (reflectable && fieldInfo.isArray)
508
    {
509

10
        if (m_walkFilter.beforeArray(reflectable, fieldInfo))
510
        {
511
8
            m_walkObserver.beginArray(reflectable, fieldInfo);
512

21
            for (size_t i = 0; i < reflectable->size(); ++i)
513
            {
514


14
                if (!walkFieldValue(reflectable->at(i), fieldInfo, i))
515
1
                    break;
516
            }
517
8
            m_walkObserver.endArray(reflectable, fieldInfo);
518
519
        }
520
10
        return m_walkFilter.afterArray(reflectable, fieldInfo);
521
    }
522
    else
523
    {
524
82
        return walkFieldValue(reflectable, fieldInfo);
525
    }
526
}
527
528
template <typename ALLOC>
529
96
bool BasicWalker<ALLOC>::walkFieldValue(const IBasicReflectableConstPtr<ALLOC>& reflectable,
530
        const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
531
{
532
96
    const IBasicTypeInfo<ALLOC>& typeInfo = fieldInfo.typeInfo;
533



96
    if (reflectable && TypeInfoUtil::isCompound(typeInfo.getSchemaType()))
534
    {
535

22
        if (m_walkFilter.beforeCompound(reflectable, fieldInfo, elementIndex))
536
        {
537
17
            m_walkObserver.beginCompound(reflectable, fieldInfo, elementIndex);
538
17
            walkFields(reflectable, typeInfo);
539
17
            m_walkObserver.endCompound(reflectable, fieldInfo, elementIndex);
540
        }
541
22
        return m_walkFilter.afterCompound(reflectable, fieldInfo, elementIndex);
542
    }
543
    else
544
    {
545

74
        if (m_walkFilter.beforeValue(reflectable, fieldInfo, elementIndex))
546
68
            m_walkObserver.visitValue(reflectable, fieldInfo, elementIndex);
547
74
        return m_walkFilter.afterValue(reflectable, fieldInfo, elementIndex);
548
    }
549
}
550
551
template <typename ALLOC>
552
7
BasicDepthWalkFilter<ALLOC>::BasicDepthWalkFilter(size_t maxDepth) :
553
7
        m_maxDepth(maxDepth), m_depth(1)
554
7
{}
555
556
template <typename ALLOC>
557
4
bool BasicDepthWalkFilter<ALLOC>::beforeArray(const IBasicReflectableConstPtr<ALLOC>&,
558
        const BasicFieldInfo<ALLOC>&)
559
{
560
4
    return enterDepthLevel();
561
}
562
563
template <typename ALLOC>
564
4
bool BasicDepthWalkFilter<ALLOC>::afterArray(const IBasicReflectableConstPtr<ALLOC>&,
565
        const BasicFieldInfo<ALLOC>&)
566
{
567
4
    return leaveDepthLevel();
568
}
569
570
template <typename ALLOC>
571
4
bool BasicDepthWalkFilter<ALLOC>::beforeCompound(const IBasicReflectableConstPtr<ALLOC>&,
572
        const BasicFieldInfo<ALLOC>&, size_t)
573
{
574
4
    return enterDepthLevel();
575
}
576
577
template <typename ALLOC>
578
4
bool BasicDepthWalkFilter<ALLOC>::afterCompound(const IBasicReflectableConstPtr<ALLOC>&,
579
        const BasicFieldInfo<ALLOC>&, size_t)
580
{
581
4
    return leaveDepthLevel();
582
}
583
584
template <typename ALLOC>
585
9
bool BasicDepthWalkFilter<ALLOC>::beforeValue(const IBasicReflectableConstPtr<ALLOC>&,
586
        const BasicFieldInfo<ALLOC>&, size_t)
587
{
588
9
    return m_depth <= m_maxDepth;
589
}
590
591
template <typename ALLOC>
592
9
bool BasicDepthWalkFilter<ALLOC>::afterValue(const IBasicReflectableConstPtr<ALLOC>&,
593
        const BasicFieldInfo<ALLOC>&, size_t)
594
{
595
9
    return true;
596
}
597
598
template <typename ALLOC>
599
8
bool BasicDepthWalkFilter<ALLOC>::enterDepthLevel()
600
{
601
8
    const bool enter = (m_depth <= m_maxDepth);
602
8
    m_depth += 1;
603
8
    return enter;
604
}
605
606
template <typename ALLOC>
607
8
bool BasicDepthWalkFilter<ALLOC>::leaveDepthLevel()
608
{
609
8
    m_depth -= 1;
610
8
    return true;
611
}
612
613
namespace detail
614
{
615
616
template <typename ALLOC>
617
31
string<ALLOC> getCurrentPathImpl(
618
        const vector<string<ALLOC>, ALLOC>& currentPath,
619
        const ALLOC& allocator)
620
{
621
31
    string<ALLOC> currentPathStr(allocator);
622
80
    for (auto it = currentPath.begin(); it != currentPath.end(); ++it)
623
    {
624
49
        if (!currentPathStr.empty())
625
18
            currentPathStr += ".";
626
49
        currentPathStr += *it;
627
    }
628
31
    return currentPathStr;
629
}
630
631
template <typename ALLOC>
632
23
void appendPathImpl(vector<string<ALLOC>, ALLOC>& currentPath,
633
        const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex, const ALLOC& allocator)
634
{
635
23
    if (elementIndex == WALKER_NOT_ELEMENT)
636
    {
637
18
        currentPath.emplace_back(fieldInfo.schemaName.data(), fieldInfo.schemaName.size(), allocator);
638
    }
639
    else
640
    {
641


5
        currentPath.back() = toString(fieldInfo.schemaName, allocator) +
642
                "[" + toString(elementIndex, allocator) + "]";
643
    }
644
23
}
645
646
template <typename ALLOC>
647
23
void popPathImpl(vector<string<ALLOC>, ALLOC>& currentPath,
648
        const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex, const ALLOC& allocator)
649
{
650
23
    if (elementIndex == WALKER_NOT_ELEMENT)
651
18
        currentPath.pop_back();
652
    else
653
5
        currentPath.back() = toString(fieldInfo.schemaName, allocator);
654
23
}
655
656
template <typename ALLOC>
657
11
class SubtreeRegexWalkFilter : public IBasicWalkFilter<ALLOC>
658
{
659
public:
660
11
    SubtreeRegexWalkFilter(const vector<string<ALLOC>, ALLOC>& currentPath,
661
            const std::regex& pathRegex, const ALLOC& allocator) :
662
11
            m_currentPath(currentPath), m_pathRegex(pathRegex), m_allocator(allocator)
663
11
    {}
664
665
11
    bool matches()
666
    {
667
11
        return m_matches;
668
    }
669
670
4
    bool beforeArray(const IBasicReflectableConstPtr<ALLOC>&,
671
            const BasicFieldInfo<ALLOC>& fieldInfo) override
672
    {
673
4
        m_currentPath.emplace_back(fieldInfo.schemaName.data(), fieldInfo.schemaName.size());
674
4
        m_matches = std::regex_match(getCurrentPath(), m_pathRegex);
675
676
        // terminate when the match is already found (note that array is never null here)
677
4
        return !m_matches;
678
    }
679
680
4
    bool afterArray(const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>&) override
681
    {
682
4
        m_currentPath.pop_back();
683
4
        return !m_matches; // terminate when the match is already found
684
    }
685
686
2
    bool beforeCompound(const IBasicReflectableConstPtr<ALLOC>&,
687
            const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex) override
688
    {
689
2
        appendPath(fieldInfo, elementIndex);
690
2
        m_matches = std::regex_match(getCurrentPath(), m_pathRegex);
691
692
        // terminate when the match is already found (note that compound is never null here)
693
2
        return !m_matches;
694
    }
695
696
2
    bool afterCompound(const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>& fieldInfo,
697
            size_t elementIndex) override
698
    {
699
2
        popPath(fieldInfo, elementIndex);
700
2
        return !m_matches; // terminate when the match is already found
701
    }
702
703
9
    bool beforeValue(const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>& fieldInfo,
704
            size_t elementIndex) override
705
    {
706
9
        appendPath(fieldInfo, elementIndex);
707
9
        m_matches = std::regex_match(getCurrentPath(), m_pathRegex);
708
709
9
        return !m_matches; // terminate when the match is already found
710
    }
711
712
9
    bool afterValue(const IBasicReflectableConstPtr<ALLOC>&, const BasicFieldInfo<ALLOC>& fieldInfo,
713
            size_t elementIndex) override
714
    {
715
9
        popPath(fieldInfo, elementIndex);
716
9
        return !m_matches; // terminate when the match is already found
717
    }
718
719
private:
720
15
    string<ALLOC> getCurrentPath() const
721
    {
722
15
        return detail::getCurrentPathImpl(m_currentPath, m_allocator);
723
    }
724
725
11
    void appendPath(const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
726
    {
727
11
        detail::appendPathImpl(m_currentPath, fieldInfo, elementIndex, m_allocator);
728
11
    }
729
730
11
    void popPath(const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
731
    {
732
11
        detail::popPathImpl(m_currentPath, fieldInfo, elementIndex, m_allocator);
733
11
    }
734
735
    vector<string<ALLOC>, ALLOC> m_currentPath;
736
    std::regex m_pathRegex;
737
    ALLOC m_allocator;
738
    bool m_matches = false;
739
};
740
741
} // namespace detail
742
743
template <typename ALLOC>
744
8
BasicRegexWalkFilter<ALLOC>::BasicRegexWalkFilter(const char* pathRegex, const ALLOC& allocator) :
745
8
        m_pathRegex(pathRegex), m_allocator(allocator)
746
8
{}
747
748
template <typename ALLOC>
749
4
bool BasicRegexWalkFilter<ALLOC>::beforeArray(const IBasicReflectableConstPtr<ALLOC>& array,
750
        const BasicFieldInfo<ALLOC>& fieldInfo)
751
{
752
4
    m_currentPath.emplace_back(fieldInfo.schemaName.data(), fieldInfo.schemaName.size(), m_allocator);
753
754

4
    if (std::regex_match(getCurrentPath(), m_pathRegex))
755
1
        return true; // the array itself matches
756
757
9
    for (size_t i = 0; i < array->size(); ++i)
758
    {
759


7
        m_currentPath.back() = toString(fieldInfo.schemaName, m_allocator) +
760
                "[" + toString(i, m_allocator) + "]";
761
762

7
        if (matchSubtree(array->at(i), fieldInfo))
763
1
            return true;
764
    }
765
766
2
    m_currentPath.back() = toString(fieldInfo.schemaName, m_allocator);
767
768
2
    return false;
769
}
770
771
template <typename ALLOC>
772
4
bool BasicRegexWalkFilter<ALLOC>::afterArray(const IBasicReflectableConstPtr<ALLOC>&,
773
        const BasicFieldInfo<ALLOC>&)
774
{
775
4
    m_currentPath.pop_back();
776
4
    return true;
777
}
778
779
template <typename ALLOC>
780
5
bool BasicRegexWalkFilter<ALLOC>::beforeCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
781
        const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
782
{
783
5
    appendPath(fieldInfo, elementIndex);
784

5
    if (std::regex_match(getCurrentPath(), m_pathRegex))
785
1
        return true; // the compound itself matches
786
787
4
    return matchSubtree(compound, fieldInfo);
788
}
789
790
template <typename ALLOC>
791
5
bool BasicRegexWalkFilter<ALLOC>::afterCompound(const IBasicReflectableConstPtr<ALLOC>&,
792
        const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
793
{
794
5
    popPath(fieldInfo, elementIndex);
795
5
    return true;
796
}
797
798
template <typename ALLOC>
799
7
bool BasicRegexWalkFilter<ALLOC>::beforeValue(const IBasicReflectableConstPtr<ALLOC>& value,
800
        const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
801
{
802
7
    appendPath(fieldInfo, elementIndex);
803
7
    return matchSubtree(value, fieldInfo);
804
}
805
806
template <typename ALLOC>
807
7
bool BasicRegexWalkFilter<ALLOC>::afterValue(const IBasicReflectableConstPtr<ALLOC>&,
808
        const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
809
{
810
7
    popPath(fieldInfo, elementIndex);
811
7
    return true;
812
}
813
814
template <typename ALLOC>
815
12
void BasicRegexWalkFilter<ALLOC>::appendPath(const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
816
{
817
12
    detail::appendPathImpl(m_currentPath, fieldInfo, elementIndex, m_allocator);
818
12
}
819
820
template <typename ALLOC>
821
12
void BasicRegexWalkFilter<ALLOC>::popPath(const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
822
{
823
12
    detail::popPathImpl(m_currentPath, fieldInfo, elementIndex, m_allocator);
824
12
}
825
826
template <typename ALLOC>
827
16
string<ALLOC> BasicRegexWalkFilter<ALLOC>::getCurrentPath() const
828
{
829
16
    return detail::getCurrentPathImpl(m_currentPath, m_allocator);
830
}
831
832
template <typename ALLOC>
833
18
bool BasicRegexWalkFilter<ALLOC>::matchSubtree(const IBasicReflectableConstPtr<ALLOC>& value,
834
        const BasicFieldInfo<ALLOC>& fieldInfo) const
835
{
836

18
    if (value != nullptr && TypeInfoUtil::isCompound(fieldInfo.typeInfo.getSchemaType()))
837
    {
838
        // is a not null compound, try to find match within its subtree
839
22
        BasicDefaultWalkObserver<ALLOC> defaultObserver;
840
22
        detail::SubtreeRegexWalkFilter<ALLOC> subtreeFilter(m_currentPath, m_pathRegex, m_allocator);
841
22
        BasicWalker<ALLOC> walker(defaultObserver, subtreeFilter);
842
11
        walker.walk(value);
843
11
        return subtreeFilter.matches();
844
    }
845
    else
846
    {
847
        // try to match a simple value or null compound
848
7
        return std::regex_match(getCurrentPath(), m_pathRegex);
849
    }
850
}
851
852
template <typename ALLOC>
853
1
BasicArrayLengthWalkFilter<ALLOC>::BasicArrayLengthWalkFilter(size_t maxArrayLength) :
854
1
        m_maxArrayLength(maxArrayLength)
855
1
{}
856
857
template <typename ALLOC>
858
2
bool BasicArrayLengthWalkFilter<ALLOC>::beforeArray(const IBasicReflectableConstPtr<ALLOC>&,
859
        const BasicFieldInfo<ALLOC>&)
860
{
861
2
    return true;
862
}
863
864
template <typename ALLOC>
865
2
bool BasicArrayLengthWalkFilter<ALLOC>::afterArray(const IBasicReflectableConstPtr<ALLOC>&,
866
        const BasicFieldInfo<ALLOC>&)
867
{
868
2
    return true;
869
}
870
871
template <typename ALLOC>
872
2
bool BasicArrayLengthWalkFilter<ALLOC>::beforeCompound(const IBasicReflectableConstPtr<ALLOC>&,
873
        const BasicFieldInfo<ALLOC>&, size_t elementIndex)
874
{
875
2
    return filterArrayElement(elementIndex);
876
}
877
878
template <typename ALLOC>
879
2
bool BasicArrayLengthWalkFilter<ALLOC>::afterCompound(const IBasicReflectableConstPtr<ALLOC>&,
880
        const BasicFieldInfo<ALLOC>&, size_t elementIndex)
881
{
882
2
    return filterArrayElement(elementIndex);
883
}
884
885
template <typename ALLOC>
886
3
bool BasicArrayLengthWalkFilter<ALLOC>::beforeValue(const IBasicReflectableConstPtr<ALLOC>&,
887
        const BasicFieldInfo<ALLOC>&, size_t elementIndex)
888
{
889
3
    return filterArrayElement(elementIndex);
890
}
891
892
template <typename ALLOC>
893
3
bool BasicArrayLengthWalkFilter<ALLOC>::afterValue(const IBasicReflectableConstPtr<ALLOC>&,
894
        const BasicFieldInfo<ALLOC>&, size_t elementIndex)
895
{
896
3
    return filterArrayElement(elementIndex);
897
}
898
899
template <typename ALLOC>
900
10
bool BasicArrayLengthWalkFilter<ALLOC>::filterArrayElement(size_t elementIndex)
901
{
902

10
    return elementIndex == WALKER_NOT_ELEMENT ? true : elementIndex < m_maxArrayLength;
903
}
904
905
template <typename ALLOC>
906
4
BasicAndWalkFilter<ALLOC>::BasicAndWalkFilter(const WalkFilters& walkFilters) :
907
4
        m_walkFilters(walkFilters)
908
4
{}
909
910
template <typename ALLOC>
911
4
bool BasicAndWalkFilter<ALLOC>::beforeArray(const IBasicReflectableConstPtr<ALLOC>& array,
912
        const BasicFieldInfo<ALLOC>& fieldInfo)
913
{
914
4
    return applyFilters(&IBasicWalkFilter<ALLOC>::beforeArray, array, fieldInfo);
915
}
916
917
template <typename ALLOC>
918
4
bool BasicAndWalkFilter<ALLOC>::afterArray(const IBasicReflectableConstPtr<ALLOC>& array,
919
        const BasicFieldInfo<ALLOC>& fieldInfo)
920
{
921
4
    return applyFilters(&IBasicWalkFilter<ALLOC>::afterArray, array, fieldInfo);
922
}
923
924
template <typename ALLOC>
925
4
bool BasicAndWalkFilter<ALLOC>::beforeCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
926
        const BasicFieldInfo<ALLOC>& fieldInfo,
927
        size_t elementIndex)
928
{
929
4
    return applyFilters(&IBasicWalkFilter<ALLOC>::beforeCompound, compound, fieldInfo, elementIndex);
930
}
931
932
template <typename ALLOC>
933
4
bool BasicAndWalkFilter<ALLOC>::afterCompound(const IBasicReflectableConstPtr<ALLOC>& compound,
934
        const BasicFieldInfo<ALLOC>& fieldInfo,
935
        size_t elementIndex)
936
{
937
4
    return applyFilters(&IBasicWalkFilter<ALLOC>::afterCompound, compound, fieldInfo, elementIndex);
938
}
939
940
template <typename ALLOC>
941
4
bool BasicAndWalkFilter<ALLOC>::beforeValue(const IBasicReflectableConstPtr<ALLOC>& value,
942
        const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
943
{
944
4
    return applyFilters(&IBasicWalkFilter<ALLOC>::beforeValue, value, fieldInfo, elementIndex);
945
}
946
947
template <typename ALLOC>
948
4
bool BasicAndWalkFilter<ALLOC>::afterValue(const IBasicReflectableConstPtr<ALLOC>& value,
949
        const BasicFieldInfo<ALLOC>& fieldInfo, size_t elementIndex)
950
{
951
4
    return applyFilters(&IBasicWalkFilter<ALLOC>::afterValue, value, fieldInfo, elementIndex);
952
}
953
954
} // namespace zserio
955
956
#endif // ZSERIO_WALKER_H_INC