/**
 * Copyright (c) 2021 OceanBase
 * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#ifndef _OB_MACRO_UTILS_H_
#define _OB_MACRO_UTILS_H_
#include <unistd.h>
#define SELECT100_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9,           \
                   _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
                   _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \
                   _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \
                   _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \
                   _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \
                   _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, \
                   _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, \
                   _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, \
                   _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, \
                   _100, ...) _100

#define _SELECT100_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9,          \
                   _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
                   _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \
                   _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \
                   _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \
                   _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \
                   _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, \
                   _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, \
                   _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, \
                   _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, \
                   _100, ...) _100

// These two macros do same work that select the 100th argument from
// argument list.
#define _SELECT100(...) _SELECT100_(__VA_ARGS__)
#define SELECT100(...) SELECT100_(__VA_ARGS__)

// Expand to the number of arguments
#define ARGS_NUM(args...)                               \
  SELECT100(, ##args,                                   \
            99, 98, 97, 96, 95, 94, 93, 92, 91, 90,     \
            89, 88, 87, 86, 85, 84, 83, 82, 81, 80,     \
            79, 78, 77, 76, 75, 74, 73, 72, 71, 70,     \
            69, 68, 67, 66, 65, 64, 63, 62, 61, 60,     \
            59, 58, 57, 56, 55, 54, 53, 52, 51, 50,     \
            49, 48, 47, 46, 45, 44, 43, 42, 41, 40,     \
            39, 38, 37, 36, 35, 34, 33, 32, 31, 30,     \
            29, 28, 27, 26, 25, 24, 23, 22, 21, 20,     \
            19, 18, 17, 16, 15, 14, 13, 12, 11, 10,     \
            9, 8, 7, 6, 5, 4, 3, 2, 1, 0)

// SELF expands to the argument itself, special processing for comma
// since GCC macro would treat comma in argument list as a separator
// between argument, Hence macro SELF accept two arguments and then
// expand to a single comma and the concrete name of these two
// arguments.
#define SELF_2(...) ,
#define SELF_1(x) x
#define SELECT3(_1, _2, _3,...) _3
#define SELF(args...) SELECT3(args, SELF_2, SELF_1)(args)

// ignore all arguments
#define IGNORE(...)
#define IGNORE_(...)

#define CONCAT_(x, y) x ## y
#define CONCAT(x, y) CONCAT_(x, y)
// same as CONCAT defined above, just avoid self referential macros
#define _CONCAT_(x, y) x ## y
#define _CONCAT(x, y) _CONCAT_(x, y)

// make that many duplicates of X, X should be surrounded by parentheses.
//
// DUP1((=)) => =
// DUP2((,)) => ,,
// DUP5((a++;)) => a++;a++;a++;a++;a++;
//
#define DUP1(X) SELF X
#define DUP2(X) SELF X DUP1(X)
#define DUP3(X) SELF X DUP2(X)
#define DUP4(X) SELF X DUP3(X)
#define DUP5(X) SELF X DUP4(X)
#define DUP6(X) SELF X DUP5(X)
#define DUP7(X) SELF X DUP6(X)
#define DUP8(X) SELF X DUP7(X)
#define DUP9(X) SELF X DUP8(X)
#define DUP10(X) SELF X DUP9(X)
#define DUP11(X) SELF X DUP10(X)
#define DUP12(X) SELF X DUP11(X)
#define DUP13(X) SELF X DUP12(X)
#define DUP14(X) SELF X DUP13(X)
#define DUP15(X) SELF X DUP14(X)
#define DUP16(X) SELF X DUP15(X)
#define DUP17(X) SELF X DUP16(X)
#define DUP18(X) SELF X DUP17(X)
#define DUP19(X) SELF X DUP18(X)
#define DUP20(X) SELF X DUP19(X)
#define DUP21(X) SELF X DUP20(X)
#define DUP22(X) SELF X DUP21(X)
#define DUP23(X) SELF X DUP22(X)
#define DUP24(X) SELF X DUP23(X)
#define DUP25(X) SELF X DUP24(X)
#define DUP26(X) SELF X DUP25(X)
#define DUP27(X) SELF X DUP26(X)
#define DUP28(X) SELF X DUP27(X)
#define DUP29(X) SELF X DUP28(X)
#define DUP30(X) SELF X DUP29(X)
#define DUP31(X) SELF X DUP30(X)
#define DUP32(X) SELF X DUP31(X)
#define DUP33(X) SELF X DUP32(X)
#define DUP34(X) SELF X DUP33(X)
#define DUP35(X) SELF X DUP34(X)
#define DUP36(X) SELF X DUP35(X)
#define DUP37(X) SELF X DUP36(X)
#define DUP38(X) SELF X DUP37(X)
#define DUP39(X) SELF X DUP38(X)
#define DUP40(X) SELF X DUP39(X)
#define DUP41(X) SELF X DUP40(X)
#define DUP42(X) SELF X DUP41(X)
#define DUP43(X) SELF X DUP42(X)
#define DUP44(X) SELF X DUP43(X)
#define DUP45(X) SELF X DUP44(X)
#define DUP46(X) SELF X DUP45(X)
#define DUP47(X) SELF X DUP46(X)
#define DUP48(X) SELF X DUP47(X)
#define DUP49(X) SELF X DUP48(X)
#define DUP50(X) SELF X DUP49(X)
#define DUP51(X) SELF X DUP50(X)
#define DUP52(X) SELF X DUP51(X)
#define DUP53(X) SELF X DUP52(X)
#define DUP54(X) SELF X DUP53(X)
#define DUP55(X) SELF X DUP54(X)
#define DUP56(X) SELF X DUP55(X)
#define DUP57(X) SELF X DUP56(X)
#define DUP58(X) SELF X DUP57(X)
#define DUP59(X) SELF X DUP58(X)
#define DUP60(X) SELF X DUP59(X)
#define DUP61(X) SELF X DUP60(X)
#define DUP62(X) SELF X DUP61(X)
#define DUP63(X) SELF X DUP62(X)
#define DUP64(X) SELF X DUP63(X)
#define DUP65(X) SELF X DUP64(X)
#define DUP66(X) SELF X DUP65(X)
#define DUP67(X) SELF X DUP66(X)
#define DUP68(X) SELF X DUP67(X)
#define DUP69(X) SELF X DUP68(X)
#define DUP70(X) SELF X DUP69(X)
#define DUP71(X) SELF X DUP70(X)
#define DUP72(X) SELF X DUP71(X)
#define DUP73(X) SELF X DUP72(X)
#define DUP74(X) SELF X DUP73(X)
#define DUP75(X) SELF X DUP74(X)
#define DUP76(X) SELF X DUP75(X)
#define DUP77(X) SELF X DUP76(X)
#define DUP78(X) SELF X DUP77(X)
#define DUP79(X) SELF X DUP78(X)
#define DUP80(X) SELF X DUP79(X)
#define DUP81(X) SELF X DUP80(X)
#define DUP82(X) SELF X DUP81(X)
#define DUP83(X) SELF X DUP82(X)
#define DUP84(X) SELF X DUP83(X)
#define DUP85(X) SELF X DUP84(X)
#define DUP86(X) SELF X DUP85(X)
#define DUP87(X) SELF X DUP86(X)
#define DUP88(X) SELF X DUP87(X)
#define DUP89(X) SELF X DUP88(X)
#define DUP90(X) SELF X DUP89(X)
#define DUP91(X) SELF X DUP90(X)
#define DUP92(X) SELF X DUP91(X)
#define DUP93(X) SELF X DUP92(X)
#define DUP94(X) SELF X DUP93(X)
#define DUP95(X) SELF X DUP94(X)
#define DUP96(X) SELF X DUP95(X)
#define DUP97(X) SELF X DUP96(X)
#define DUP98(X) SELF X DUP97(X)
#define DUP99(X) SELF X DUP98(X)

#define DUP_(n, X) DUP ## n (X)
#define DUP(n, X) DUP_(n, X)


// expand to the number of 100 minus n
#define COMP100(n)                                      \
  _SELECT100(DUP(n, (,)),                               \
             1, 2, 3, 4, 5, 6, 7, 8, 9,                 \
             10, 11, 12, 13, 14, 15, 16, 17, 18, 19,    \
             20, 21, 22, 23, 24, 25, 26, 27, 28, 29,    \
             30, 31, 32, 33, 34, 35, 36, 37, 38, 39,    \
             40, 41, 42, 43, 44, 45, 46, 47, 48, 49,    \
             50, 51, 52, 53, 54, 55, 56, 57, 58, 59,    \
             60, 61, 62, 63, 64, 65, 66, 67, 68, 69,    \
             70, 71, 72, 73, 74, 75, 76, 77, 78, 79,    \
             80, 81, 82, 83, 84, 85, 86, 87, 88, 89,    \
             90, 91, 92, 93, 94, 95, 96, 97, 98, 99)

#define LST_DO_0(...)
#define LST_DO_1(M, s, ...) PROC_ONE(M, 1, ##__VA_ARGS__)
#define LST_DO_2(M, s, ...) LST_DO_1(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 2, ##__VA_ARGS__)
#define LST_DO_3(M, s, ...) LST_DO_2(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 3, ##__VA_ARGS__)
#define LST_DO_4(M, s, ...) LST_DO_3(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 4, ##__VA_ARGS__)
#define LST_DO_5(M, s, ...) LST_DO_4(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 5, ##__VA_ARGS__)
#define LST_DO_6(M, s, ...) LST_DO_5(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 6, ##__VA_ARGS__)
#define LST_DO_7(M, s, ...) LST_DO_6(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 7, ##__VA_ARGS__)
#define LST_DO_8(M, s, ...) LST_DO_7(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 8, ##__VA_ARGS__)
#define LST_DO_9(M, s, ...) LST_DO_8(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 9, ##__VA_ARGS__)
#define LST_DO_10(M, s, ...) LST_DO_9(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 10, ##__VA_ARGS__)
#define LST_DO_11(M, s, ...) LST_DO_10(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 11, ##__VA_ARGS__)
#define LST_DO_12(M, s, ...) LST_DO_11(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 12, ##__VA_ARGS__)
#define LST_DO_13(M, s, ...) LST_DO_12(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 13, ##__VA_ARGS__)
#define LST_DO_14(M, s, ...) LST_DO_13(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 14, ##__VA_ARGS__)
#define LST_DO_15(M, s, ...) LST_DO_14(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 15, ##__VA_ARGS__)
#define LST_DO_16(M, s, ...) LST_DO_15(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 16, ##__VA_ARGS__)
#define LST_DO_17(M, s, ...) LST_DO_16(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 17, ##__VA_ARGS__)
#define LST_DO_18(M, s, ...) LST_DO_17(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 18, ##__VA_ARGS__)
#define LST_DO_19(M, s, ...) LST_DO_18(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 19, ##__VA_ARGS__)
#define LST_DO_20(M, s, ...) LST_DO_19(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 20, ##__VA_ARGS__)
#define LST_DO_21(M, s, ...) LST_DO_20(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 21, ##__VA_ARGS__)
#define LST_DO_22(M, s, ...) LST_DO_21(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 22, ##__VA_ARGS__)
#define LST_DO_23(M, s, ...) LST_DO_22(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 23, ##__VA_ARGS__)
#define LST_DO_24(M, s, ...) LST_DO_23(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 24, ##__VA_ARGS__)
#define LST_DO_25(M, s, ...) LST_DO_24(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 25, ##__VA_ARGS__)
#define LST_DO_26(M, s, ...) LST_DO_25(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 26, ##__VA_ARGS__)
#define LST_DO_27(M, s, ...) LST_DO_26(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 27, ##__VA_ARGS__)
#define LST_DO_28(M, s, ...) LST_DO_27(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 28, ##__VA_ARGS__)
#define LST_DO_29(M, s, ...) LST_DO_28(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 29, ##__VA_ARGS__)
#define LST_DO_30(M, s, ...) LST_DO_29(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 30, ##__VA_ARGS__)
#define LST_DO_31(M, s, ...) LST_DO_30(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 31, ##__VA_ARGS__)
#define LST_DO_32(M, s, ...) LST_DO_31(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 32, ##__VA_ARGS__)
#define LST_DO_33(M, s, ...) LST_DO_32(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 33, ##__VA_ARGS__)
#define LST_DO_34(M, s, ...) LST_DO_33(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 34, ##__VA_ARGS__)
#define LST_DO_35(M, s, ...) LST_DO_34(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 35, ##__VA_ARGS__)
#define LST_DO_36(M, s, ...) LST_DO_35(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 36, ##__VA_ARGS__)
#define LST_DO_37(M, s, ...) LST_DO_36(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 37, ##__VA_ARGS__)
#define LST_DO_38(M, s, ...) LST_DO_37(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 38, ##__VA_ARGS__)
#define LST_DO_39(M, s, ...) LST_DO_38(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 39, ##__VA_ARGS__)
#define LST_DO_40(M, s, ...) LST_DO_39(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 40, ##__VA_ARGS__)
#define LST_DO_41(M, s, ...) LST_DO_40(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 41, ##__VA_ARGS__)
#define LST_DO_42(M, s, ...) LST_DO_41(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 42, ##__VA_ARGS__)
#define LST_DO_43(M, s, ...) LST_DO_42(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 43, ##__VA_ARGS__)
#define LST_DO_44(M, s, ...) LST_DO_43(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 44, ##__VA_ARGS__)
#define LST_DO_45(M, s, ...) LST_DO_44(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 45, ##__VA_ARGS__)
#define LST_DO_46(M, s, ...) LST_DO_45(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 46, ##__VA_ARGS__)
#define LST_DO_47(M, s, ...) LST_DO_46(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 47, ##__VA_ARGS__)
#define LST_DO_48(M, s, ...) LST_DO_47(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 48, ##__VA_ARGS__)
#define LST_DO_49(M, s, ...) LST_DO_48(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 49, ##__VA_ARGS__)
#define LST_DO_50(M, s, ...) LST_DO_49(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 50, ##__VA_ARGS__)
#define LST_DO_51(M, s, ...) LST_DO_50(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 51, ##__VA_ARGS__)
#define LST_DO_52(M, s, ...) LST_DO_51(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 52, ##__VA_ARGS__)
#define LST_DO_53(M, s, ...) LST_DO_52(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 53, ##__VA_ARGS__)
#define LST_DO_54(M, s, ...) LST_DO_53(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 54, ##__VA_ARGS__)
#define LST_DO_55(M, s, ...) LST_DO_54(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 55, ##__VA_ARGS__)
#define LST_DO_56(M, s, ...) LST_DO_55(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 56, ##__VA_ARGS__)
#define LST_DO_57(M, s, ...) LST_DO_56(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 57, ##__VA_ARGS__)
#define LST_DO_58(M, s, ...) LST_DO_57(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 58, ##__VA_ARGS__)
#define LST_DO_59(M, s, ...) LST_DO_58(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 59, ##__VA_ARGS__)
#define LST_DO_60(M, s, ...) LST_DO_59(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 60, ##__VA_ARGS__)
#define LST_DO_61(M, s, ...) LST_DO_60(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 61, ##__VA_ARGS__)
#define LST_DO_62(M, s, ...) LST_DO_61(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 62, ##__VA_ARGS__)
#define LST_DO_63(M, s, ...) LST_DO_62(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 63, ##__VA_ARGS__)
#define LST_DO_64(M, s, ...) LST_DO_63(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 64, ##__VA_ARGS__)
#define LST_DO_65(M, s, ...) LST_DO_64(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 65, ##__VA_ARGS__)
#define LST_DO_66(M, s, ...) LST_DO_65(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 66, ##__VA_ARGS__)
#define LST_DO_67(M, s, ...) LST_DO_66(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 67, ##__VA_ARGS__)
#define LST_DO_68(M, s, ...) LST_DO_67(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 68, ##__VA_ARGS__)
#define LST_DO_69(M, s, ...) LST_DO_68(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 69, ##__VA_ARGS__)
#define LST_DO_70(M, s, ...) LST_DO_69(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 70, ##__VA_ARGS__)
#define LST_DO_71(M, s, ...) LST_DO_70(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 71, ##__VA_ARGS__)
#define LST_DO_72(M, s, ...) LST_DO_71(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 72, ##__VA_ARGS__)
#define LST_DO_73(M, s, ...) LST_DO_72(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 73, ##__VA_ARGS__)
#define LST_DO_74(M, s, ...) LST_DO_73(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 74, ##__VA_ARGS__)
#define LST_DO_75(M, s, ...) LST_DO_74(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 75, ##__VA_ARGS__)
#define LST_DO_76(M, s, ...) LST_DO_75(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 76, ##__VA_ARGS__)
#define LST_DO_77(M, s, ...) LST_DO_76(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 77, ##__VA_ARGS__)
#define LST_DO_78(M, s, ...) LST_DO_77(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 78, ##__VA_ARGS__)
#define LST_DO_79(M, s, ...) LST_DO_78(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 79, ##__VA_ARGS__)
#define LST_DO_80(M, s, ...) LST_DO_79(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 80, ##__VA_ARGS__)
#define LST_DO_81(M, s, ...) LST_DO_80(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 81, ##__VA_ARGS__)
#define LST_DO_82(M, s, ...) LST_DO_81(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 82, ##__VA_ARGS__)
#define LST_DO_83(M, s, ...) LST_DO_82(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 83, ##__VA_ARGS__)
#define LST_DO_84(M, s, ...) LST_DO_83(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 84, ##__VA_ARGS__)
#define LST_DO_85(M, s, ...) LST_DO_84(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 85, ##__VA_ARGS__)
#define LST_DO_86(M, s, ...) LST_DO_85(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 86, ##__VA_ARGS__)
#define LST_DO_87(M, s, ...) LST_DO_86(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 87, ##__VA_ARGS__)
#define LST_DO_88(M, s, ...) LST_DO_87(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 88, ##__VA_ARGS__)
#define LST_DO_89(M, s, ...) LST_DO_88(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 89, ##__VA_ARGS__)
#define LST_DO_90(M, s, ...) LST_DO_89(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 90, ##__VA_ARGS__)
#define LST_DO_91(M, s, ...) LST_DO_90(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 91, ##__VA_ARGS__)
#define LST_DO_92(M, s, ...) LST_DO_91(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 92, ##__VA_ARGS__)
#define LST_DO_93(M, s, ...) LST_DO_92(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 93, ##__VA_ARGS__)
#define LST_DO_94(M, s, ...) LST_DO_93(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 94, ##__VA_ARGS__)
#define LST_DO_95(M, s, ...) LST_DO_94(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 95, ##__VA_ARGS__)
#define LST_DO_96(M, s, ...) LST_DO_95(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 96, ##__VA_ARGS__)
#define LST_DO_97(M, s, ...) LST_DO_96(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 97, ##__VA_ARGS__)
#define LST_DO_98(M, s, ...) LST_DO_97(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 98, ##__VA_ARGS__)
#define LST_DO_99(M, s, ...) LST_DO_98(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 99, ##__VA_ARGS__)
#define LST_DO_100(M, s, ...) LST_DO_99(M, s, ##__VA_ARGS__)SELF s PROC_ONE(M, 100, ##__VA_ARGS__)

#define LST_DO__(N, M, s, ...) LST_DO_ ## N(M, s, ##__VA_ARGS__)
#define LST_DO_(...) LST_DO__(__VA_ARGS__)
#define LST_DO(M, s, ...) LST_DO_(ARGS_NUM(__VA_ARGS__), M, s, ##__VA_ARGS__)

// select nth argument
//
// SELECT(2, arg1, arg2, arg3) => arg2
#define SELECT(n, ...) SELECT100(DUP(COMP100(n), (,)), __VA_ARGS__)

#define PROC_ONE(M, ...) M(SELECT(__VA_ARGS__))

// map M to each of other arguments
//
// LST_DO_CODE(DECODE, arg1, arg2, arg3) => DECODE(arg1); DECODE(arg2); DEOCDE(arg3)
// LST_DO_CODE(CHECK, arg1, arg2) => CHECK(arg1); CHECK(arg2)
#define LST_DO_CODE(M, ...) LST_DO(M, (;), ## __VA_ARGS__)

#define ONE_TO_HUNDRED \
    1, 2, 3, 4, 5, 6, 7, 8, 9,                 \
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19,    \
    20, 21, 22, 23, 24, 25, 26, 27, 28, 29,    \
    30, 31, 32, 33, 34, 35, 36, 37, 38, 39,    \
    40, 41, 42, 43, 44, 45, 46, 47, 48, 49,    \
    50, 51, 52, 53, 54, 55, 56, 57, 58, 59,    \
    60, 61, 62, 63, 64, 65, 66, 67, 68, 69,    \
    70, 71, 72, 73, 74, 75, 76, 77, 78, 79,    \
    80, 81, 82, 83, 84, 85, 86, 87, 88, 89,    \
        90, 91, 92, 93, 94, 95, 96, 97, 98, 99,100

#define MSTR(X) #X

// THE EXCLUSIVE EXAMPLE
//
// if (FAILEDx(some_function)) {
//   blabalbal...
// }
//
#define FAILEDx(X) OB_FAIL(ret)) {} else if (OB_FAIL(X)

// select macro depend on parameter which have parent surround with.
//
//   #define MACRO_PAREN(x) some_code_if_has_paren
//   #define MACRO_NO_PAREN(x) some_code_if_no_paren
//
//   IF_PARENT(XXX, MACRO_PAREN, MACRO_NO_PAREN) ==> MACRO_NO_PAREN(XXX)
//   IF_PARENT((XXX), MACRO_PAREN, MACRO_NO_PAREN) ==> MACRO_PAREN(XXX)
//
#define OBMPAR IGNORE(
#define PAR(x) _SELF(
#define OBM_SELF(x) x

#define PAREN(x, M) CONCAT(OBM, PAR x) M x)

#define OBMNPNPAR SELF(IGNORE(
#define OBMNP_SELF(x) SELF
#define NPAR(x) _IGNORE(
#define OBMNP_IGNORE(...) IGNORE(

#define NO_PAREN(x, M) CONCAT(OBMNP, NPAR x)) M (x))

#define IF_PAREN(x, MP, MNP) PAREN(x, MP) NO_PAREN(x, MNP)

#ifndef MIN
#define MIN(x, y) ((x) < (y) ? (x) : (y))
#endif

#define MIN3(x, y, z) MIN(MIN(x, y), z)

#ifndef MAX
#define MAX(x, y) ((x) > (y) ? (x) : (y))
#endif

#define MAX3(x, y, z) MAX(MAX(x, y), z)
// Deferred expression and recursion
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__

#define EMPTY()
#define DEFER(id) id EMPTY()
#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)()
#define EXPAND(...) __VA_ARGS__

#define EVAL(...)  EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__)))
#define EVAL5(...) __VA_ARGS__

////////////////////////////////////////////////////////////////
/**
 * There are four kinds of FOREACH macros:
 * 1. FOREACH
 * 2. FOREACH_REF
 * 3. ARRAY_FOREACH
 * 4. DLIST_FOREACH @see ob_dlist.h
 *
 */
// container iterate macro, support container with begin(), end() interface.
// (e.g.: ObArray, ObSEArray, ObHashTable, stl::vector ...)
#define FOREACH_X(it, container, extra_condition) \
    for (__typeof__((container).begin()) it = (container).begin(); \
        (extra_condition) && (it != (container).end()); ++it)
#define FOREACH(it, container) FOREACH_X(it, (container), true)

// container iterate macro, support container with count(), at() interface.
// (e.g.: ObIArray)
#define __INNER_I_NAME__(it) __i__##it
#define __INNER_I__(it) (*reinterpret_cast<int64_t *>(&__INNER_I_NAME__(it)))
#define FOREACH_CNT_X(it, c, extra_condition) \
for (__typeof__((c).at(0)) *it = ((c).count() > 0 ? &(c).at(0) : NULL), *__INNER_I_NAME__(it) = NULL; \
    (extra_condition) && __INNER_I__(it) < (c).count(); \
    ++__INNER_I__(it), it = (__INNER_I__(it) < (c).count() ? &(c).at(__INNER_I__(it)) : NULL))
#define FOREACH_CNT(it, c) FOREACH_CNT_X(it, c, true)

// array iterate macro, in contrast to FOREACH_CNT, these macros can access index variable in the loop body
#define ARRAY_FOREACH_X(array, idx, cnt, extra_condition)              \
    for (int64_t (idx) = 0, (cnt) = (array).count(); (extra_condition) && (idx) != (cnt); ++(idx))
#define ARRAY_FOREACH_N(array, idx, cnt) ARRAY_FOREACH_X(array, idx, cnt, OB_SUCC(ret))
#define ARRAY_FOREACH_NORET(array, idx) ARRAY_FOREACH_X(array, idx, _NuM__ArrAy_, true)
#define ARRAY_FOREACH(array, idx) ARRAY_FOREACH_N(array, idx, _NuM__ArrAy_)
////////////////////////////////////////////////////////////////
/**
* Macros to help define enum and it string convert functions.
* Usage:
*   in .h file:
*
*      #define MY_ENUM_DEF(ACT) \
*         ACT(INVALID_MY_ENUM_VALUE, = 0) \
*         ACT(VALUE1,) \
*         ACT(VALUE2, = 1024) \
*         ACT(VALUE3,)
*
*     DECLARE_ENUM(ObMyEnum, my_enum, MY_ENUM_DEF)
*
* This delcare will will be expand to:
*
*   enum ObMyEnum {
*     VALUE1,
*     VALUE2 = 1024,
*     VALUE3,
*   };
*   const char *get_my_enum_string(const ObMyEnum v);
*   ObMyEnum get_my_enum_value(const char *str);
*   ObMyEnum get_my_enum_value(const common::ObString &str);
*
* get_my_enum_string() return NULL if %v not exist.
* get_my_enum_value() return 0 if %str not an valid enum string. So it's a good idea to
* define an invalid enum value of value 0 for error detection.
*
* And you need also define the functions in .cpp file:
*
*   in .cpp file:
*
*     define(ObMyEnum, my_enum, MY_ENUM_DEF)
*
*/
#define DEF_ENUM_VALUE(name, assign) name assign,
#define DEF_ENUM_CASE(name, ...) case name: return #name;
#define DEF_ENUM_STRCMP(name, ...) if (0 == str.case_compare(#name)) return name;
#define DECLARE_ENUM(type, func_name, def) \
    enum type \
    { \
      def(DEF_ENUM_VALUE) \
    }; \
    const char *get_##func_name##_string(const type v); \
    type get_##func_name##_value(const char *str); \
    type get_##func_name##_value(const common::ObString &str);

#define DEFINE_ENUM_FUNC(type, func_name, def)                          \
    const char *get_##func_name##_string(const type v)                  \
    {                                                                   \
      switch (v) {                                                      \
        def(DEF_ENUM_CASE)                                              \
        default:                                                        \
          LIB_LOG(WARN, "unknow " #type "value", "value", v);           \
          return NULL;                                                  \
      }                                                                 \
    }                                                                   \
    type get_##func_name##_value(const char *str)                       \
    {                                                                   \
      return get_##func_name##_value(common::ObString::make_string(str));\
    }                                                                   \
    type get_##func_name##_value(const common::ObString &str)           \
    {                                                                   \
      if (str.empty()) {                                                \
        LIB_LOG(WARN, "invalid argument, empty str");                   \
        return static_cast<type>(0);                                    \
      } else {                                                          \
       def(DEF_ENUM_STRCMP)                                             \
      }                                                                 \
      LIB_LOG(WARN, "unknow " #type "string", K(str));                  \
      return static_cast<type>(0);                                      \
    }

#ifdef __cplusplus
#define EXTERN_C_BEGIN  extern "C" {
#define EXTERN_C_END }
#else
#define EXTERN_C_BEGIN
#define EXTERN_C_END
#endif  // __cplusplus

////////////////////////////////////////////////////////////////
// OceanBase Idiom
#ifndef UNUSED
#define UNUSED(v) ((void)(v))
#endif

#define IGNORE_RETURN (void)

#define UNUSEDx(...) LST_DO_CODE(UNUSED, __VA_ARGS__)

#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
  TypeName(const TypeName&);               \
  void operator=(const TypeName&)

#define OB_INLINE inline __attribute__((always_inline))

#define CACHE_ALIGN_SIZE 64
#define CACHE_ALIGNED __attribute__((aligned(CACHE_ALIGN_SIZE)))

#define OB_LIKELY(x)       __builtin_expect(!!(x),1)
#define OB_UNLIKELY(x)     __builtin_expect(!!(x),0)

#define ARRAYSIZEOF(a) static_cast<int64_t>(sizeof(a)/sizeof(a[0]))
#define SIZEOF(x) static_cast<int64_t>(sizeof(x))

#define CONTAINER_OF(ptr, type, member) ({              \
      const typeof(((type *)0)->member) *m_ptr = ptr;   \
      (type *)((char *)m_ptr - __builtin_offsetof(type, member)); \
    }                                                   \
    )

#ifdef NDEBUG
// release mode
#define CHAR_CARRAY_INIT(a) a[0] = '\0'
#else
// debug mode
#define CHAR_CARRAY_INIT(a) memset((a), 0, sizeof(a))
#endif

#define OB_SUCC(statement) (OB_LIKELY(::oceanbase::common::OB_SUCCESS == (ret = (statement))))
#define OB_FAIL(statement) (OB_UNLIKELY(::oceanbase::common::OB_SUCCESS != (ret = (statement))))

#ifdef OB_PERF_MODE
#define OB_ISNULL(statement) ({UNUSED(statement); false; })
#else
#define OB_ISNULL(statement) (OB_UNLIKELY(NULL == (statement)))
#define OB_NOT_NULL(statement) (OB_LIKELY(NULL != (statement)))
#endif
#define IS_NOT_INIT (OB_UNLIKELY(!is_inited_))
#define IS_INIT (OB_LIKELY(is_inited_))

#define RETRY_FUNC(stop_flag, var, func, args...) \
  do {\
    if (OB_SUCC(ret)) \
    { \
      ret = OB_TIMEOUT; \
      while (OB_TIMEOUT == ret && ! (stop_flag)) \
      { \
        ret = (var).func(args); \
      } \
      if ((stop_flag)) \
      { \
        ret = OB_IN_STOP_STATE; \
      } \
    } \
  } while (0)


////////////////////////////////////////////////////////////////
// assert utilities
#define BACKTRACE(LEVEL, cond, _fmt_, args...) \
  do \
  { \
    if (cond) \
    { \
      _OB_LOG(LEVEL, _fmt_ " BackTrace Start: %s", ##args, oceanbase::common::lbt()); \
    } \
  } while (false)

#ifdef NDEBUG
#define OB_ASSERT(x) (void)(x)
#else
#define OB_ASSERT(x)                                    \
  do{                                                   \
    bool v=(x);                                         \
    if(OB_UNLIKELY(!(v))) {                             \
      _OB_LOG(ERROR, "assert fail, exp=%s", #x);        \
      BACKTRACE(ERROR, 1, "assert fail");               \
      assert(v);                                        \
    }                                                   \
  } while(false)
#endif


#define OB_ASSERT_MSG(x, msg...)                      \
  do{                                                 \
    bool v=(x);                                       \
    if(OB_UNLIKELY(!(v))) {                           \
      _OB_LOG(ERROR, "assert fail, exp=%s", #x);      \
      BACKTRACE(ERROR, 1, ##msg);                     \
      assert(v);                                      \
    }                                                 \
  } while(false)

#define ob_release_assert(x)                            \
  do{                                                   \
    bool v=(x);                                         \
    if(OB_UNLIKELY(!(v))) {                             \
      _OB_LOG(ERROR, "assert fail, exp=%s", #x);        \
      BACKTRACE(ERROR, 1, "assert fail");               \
      abort();                                          \
      exit(1);                                          \
    }                                                   \
  } while(false)

//#define ob_assert(x) OB_ASSERT(x)
#define ob_assert(x) ob_release_assert(x)
////////////////////////////////////////////////////////////////
// interval
#define REACH_TIME_INTERVAL(i) \
  ({ \
    bool bret = false; \
    static volatile int64_t last_time = 0; \
    int64_t cur_time = ::oceanbase::common::ObTimeUtility::current_time(); \
    int64_t old_time = last_time; \
    if ((i + last_time) < cur_time \
        && old_time == ATOMIC_CAS(&last_time, old_time, cur_time)) \
    { \
      bret = true; \
    } \
    bret; \
  })


// reach count per secound
#define REACH_COUNT_PER_SEC(i) \
  ({ \
    bool bool_ret = false; \
    static const uint64_t ONE_SECOND = 1 * 1000 *1000; \
    static types::uint128_t last; \
    const int64_t cur_time = ::oceanbase::common::ObTimeUtility::current_time(); \
    while(true) { \
      ::types::uint128_t tmp; \
      ::types::uint128_t next; \
      LOAD128(tmp, &last); \
      if (tmp.lo + ONE_SECOND > (uint64_t)cur_time) { \
        next.hi = tmp.hi + 1; \
        next.lo = tmp.lo; \
        if (next.hi > (uint64_t)i) { \
          bool_ret = true; \
        } \
      } else { \
        next.lo = (uint64_t)cur_time; \
        next.hi = 1; \
      } \
      if (CAS128(&last, tmp, next)) { \
        break; \
      } \
    } \
    bool_ret; \
  })
// exclusive first time
#define REACH_TIME_INTERVAL_RANGE(i, j) \
  ({ \
    bool bret = false; \
    static volatile int64_t last_time = ::oceanbase::common::ObTimeUtility::current_time(); \
    int64_t cur_time = ::oceanbase::common::ObTimeUtility::current_time(); \
    int64_t old_time = last_time; \
    if ((j + last_time) < cur_time) \
    { \
      (void)ATOMIC_CAS(&last_time, old_time, cur_time); \
    } \
    old_time = last_time; \
    if ((i + last_time) < cur_time \
        && old_time == ATOMIC_CAS(&last_time, old_time, cur_time)) \
    { \
      bret = true; \
    } \
    bret; \
  })

#define TC_REACH_TIME_INTERVAL(i) \
  ({ \
    bool bret = false; \
    static __thread int64_t last_time = 0; \
    int64_t cur_time = ::oceanbase::common::ObTimeUtility::current_time(); \
    if ((i + last_time) < cur_time) \
    { \
      last_time = cur_time; \
      bret = true; \
    } \
    bret; \
  })

#define REACH_COUNT_INTERVAL(i) \
  ({ \
    bool bret = false; \
    static volatile int64_t count = 0; \
    if (0 == (ATOMIC_AAF(&count, 1) % i)) \
    { \
      bret = true; \
    } \
    bret; \
  })

#define TC_REACH_COUNT_INTERVAL(i) \
  ({ \
    bool bret = false; \
    static __thread int64_t count = 0; \
    if (0 == (++count % i)) \
    { \
      bret = true; \
    } \
    bret; \
  })


#endif /* _OB_MACRO_UTILS_H_ */
