1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef MACRO_UPDATER_H
17#define MACRO_UPDATER_H
18
19#define DISALLOW_COPY_MOVE_ASSIGN(ClassName)            \
20    ClassName &operator = (const ClassName &) = delete; \
21    ClassName &operator = (ClassName &&) = delete
22
23#define DISALLOW_COPY_MOVE_CONSTRUCT(ClassName) \
24    ClassName(const ClassName &) = delete;      \
25    ClassName(ClassName &&) = delete
26
27#define DISALLOW_COPY_MOVE(ClassName)     \
28    DISALLOW_COPY_MOVE_ASSIGN(ClassName); \
29    DISALLOW_COPY_MOVE_CONSTRUCT(ClassName)
30
31#define STRINGFY_WRAPPER(x) #x
32#define STRINGFY(x) STRINGFY_WRAPPER(x)
33
34#define SIZE(...) SIZE_IMPL(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)
35#define SIZE_IMPL(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, N, ...) N
36
37#define CONCAT(x, y) CONCAT_WRAPPER(x, y)
38#define CONCAT_WRAPPER(x, y) x##y
39
40#define GET_TYPE_2(e1, e2) e1
41#define GET_TYPE_3(e1, e2, e3) e1, e2
42#define GET_TYPE_4(e1, e2, e3, e4) e1, e2, e3
43
44#define GET_NAME_2(e1, e2) e2
45#define GET_NAME_3(e1, e2, e3) e3
46#define GET_NAME_4(e1, e2, e3, e4) e4
47
48#define GET_TYPE(...) CONCAT(GET_TYPE_, SIZE(__VA_ARGS__))(__VA_ARGS__)
49#define GET_NAME(...) CONCAT(GET_NAME_, SIZE(__VA_ARGS__))(__VA_ARGS__)
50#define GET_KEY(...) STRINGFY(GET_NAME(__VA_ARGS__))
51
52#define REPEAT(MACRO, ...) CONCAT(REPEAT_, SIZE(__VA_ARGS__))(MACRO, __VA_ARGS__)
53#define REPEAT_1(MACRO, element, ...) MACRO(0, element)
54#define REPEAT_2(MACRO, element, ...) MACRO(1, element) REPEAT_1(MACRO, __VA_ARGS__)
55#define REPEAT_3(MACRO, element, ...) MACRO(2, element) REPEAT_2(MACRO, __VA_ARGS__)
56#define REPEAT_4(MACRO, element, ...) MACRO(3, element) REPEAT_3(MACRO, __VA_ARGS__)
57#define REPEAT_5(MACRO, element, ...) MACRO(4, element) REPEAT_4(MACRO, __VA_ARGS__)
58#define REPEAT_6(MACRO, element, ...) MACRO(5, element) REPEAT_5(MACRO, __VA_ARGS__)
59#define REPEAT_7(MACRO, element, ...) MACRO(6, element) REPEAT_6(MACRO, __VA_ARGS__)
60#define REPEAT_8(MACRO, element, ...) MACRO(7, element) REPEAT_7(MACRO, __VA_ARGS__)
61#define REPEAT_9(MACRO, element, ...) MACRO(8, element) REPEAT_8(MACRO, __VA_ARGS__)
62#define REPEAT_10(MACRO, element, ...) MACRO(9, element) REPEAT_9(MACRO, __VA_ARGS__)
63
64#define COMMA_IF(i) CONCAT(COMMA_IF_, i)
65#define COMMA_IF_0
66#define COMMA_IF_1 ,
67#define COMMA_IF_2 ,
68#define COMMA_IF_3 ,
69#define COMMA_IF_4 ,
70#define COMMA_IF_5 ,
71#define COMMA_IF_6 ,
72#define COMMA_IF_7 ,
73#define COMMA_IF_8 ,
74#define COMMA_IF_9 ,
75
76#define GET_MEMBER_DECLARTION(idx, tuple) GET_TYPE tuple GET_NAME tuple;
77#define GET_MEMBER_KEY(idx, tuple) GET_KEY tuple COMMA_IF(idx)
78#define GET_MEMBER(idx, tuple) obj.GET_NAME tuple COMMA_IF(idx)
79
80#define DEFINE_STRUCT_TRAIT(NAME, KEY, ...) \
81    DEFINE_STRUCT(NAME, __VA_ARGS__);       \
82    DEFINE_TRAIT(NAME, KEY, __VA_ARGS__)
83
84#define DEFINE_STRUCT(NAME, ...)                   \
85    struct NAME {                                  \
86        REPEAT(GET_MEMBER_DECLARTION, __VA_ARGS__) \
87    }
88
89#define DEFINE_TRAIT(NAME, KEY, ...)                                                       \
90    template <> struct Traits<NAME> {                                                      \
91        constexpr static const char *STRUCT_KEY = KEY;                                     \
92        constexpr static const char *MEMBER_KEY[] = {REPEAT(GET_MEMBER_KEY, __VA_ARGS__)}; \
93        constexpr static int COUNT = sizeof(MEMBER_KEY) / sizeof(char *);                  \
94        template <std::size_t idx> constexpr static auto &Get(NAME &obj)                   \
95        {                                                                                  \
96            return Detail::Get<idx>(REPEAT(GET_MEMBER, __VA_ARGS__));                      \
97        }                                                                                  \
98    }
99#endif