[FEAT MERGE]4_1_sql_feature
Co-authored-by: leslieyuchen <leslieyuchen@gmail.com> Co-authored-by: Charles0429 <xiezhenjiang@gmail.com> Co-authored-by: raywill <hustos@gmail.com>
This commit is contained in:
parent
3080f2b66f
commit
2d19a9d8f5
30
NOTICE
30
NOTICE
@ -224,33 +224,3 @@ All rights reserved.
|
||||
This source code is licensed under the BSD-style license found in the
|
||||
LICENSE file in the root directory of this source tree. An additional grant
|
||||
of patent rights can be found in the PATENTS file in the same directory
|
||||
|
||||
==============================regex==============================
|
||||
Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
|
||||
Development of this software was funded, in part, by Cray Research Inc.,
|
||||
UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
Corporation, none of whom are responsible for the results. The author
|
||||
thanks all of them.
|
||||
|
||||
Redistribution and use in source and binary forms -- with or without
|
||||
modification -- are permitted for any purpose, provided that
|
||||
redistributions in source form retain this entire copyright notice and
|
||||
indicate the origin and nature of any modifications.
|
||||
|
||||
I'd appreciate being given credit for this package in the documentation of
|
||||
software which uses it, but that is not a requirement.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Note that there are some incestuous relationships between this code and NFA
|
||||
arc maintenance, which perhaps ought to be cleaned up sometime.
|
||||
|
@ -241,7 +241,6 @@ install(FILES
|
||||
deps/oblib/src/lib/queue/ob_fixed_queue.h
|
||||
deps/oblib/src/lib/queue/ob_link.h
|
||||
deps/oblib/src/lib/random/ob_random.h
|
||||
deps/oblib/src/lib/regex/ob_regex.h
|
||||
deps/oblib/src/lib/resource/achunk_mgr.h
|
||||
deps/oblib/src/lib/resource/ob_cache_washer.h
|
||||
deps/oblib/src/lib/resource/ob_resource_mgr.h
|
||||
|
1
deps/easy/src/io/easy_connection.c
vendored
1
deps/easy/src/io/easy_connection.c
vendored
@ -1610,6 +1610,7 @@ void easy_connection_on_readable(struct ev_loop *loop, ev_io *w, int revents)
|
||||
easy_error_log("Failed to do response on client, conn(%p).", c);
|
||||
}
|
||||
}
|
||||
c->status = EASY_CONN_CLOSE_BY_PEER;
|
||||
} else {
|
||||
c->conn_has_error = 1;
|
||||
easy_info_log("Failed to read from connection(%p), n(%d).", c, n);
|
||||
|
1
deps/easy/src/io/easy_io_struct.h
vendored
1
deps/easy/src/io/easy_io_struct.h
vendored
@ -68,6 +68,7 @@ extern easy_atomic_t easy_debug_uuid;
|
||||
#define EASY_CONN_CONNECTING 1
|
||||
#define EASY_CONN_AUTO_CONN 2
|
||||
#define EASY_CONN_CLOSE 3
|
||||
#define EASY_CONN_CLOSE_BY_PEER 4
|
||||
|
||||
#define EASY_CLIENT_DEFAULT_TIMEOUT 4000
|
||||
#define EASY_FIRST_MSGLEN 1024
|
||||
|
1
deps/easy/src/util/easy_time.h
vendored
1
deps/easy/src/util/easy_time.h
vendored
@ -22,6 +22,7 @@ EASY_CPP_START
|
||||
|
||||
int easy_localtime(const time_t *t, struct tm *tp);
|
||||
int64_t easy_time_now();
|
||||
uint64_t get_cpufreq_khz();
|
||||
extern int64_t fast_current_time();
|
||||
|
||||
EASY_CPP_END
|
||||
|
1
deps/init/oceanbase.el7.aarch64.deps
vendored
1
deps/init/oceanbase.el7.aarch64.deps
vendored
@ -26,6 +26,7 @@ devdeps-zlib-static-1.2.7-132022100815.el7.aarch64.rpm
|
||||
devdeps-ncurses-static-6.2-72022100815.el7.aarch64.rpm
|
||||
devdeps-boost-1.74.0-22022110914.el7.aarch64.rpm
|
||||
devdeps-s2geometry-0.9.0-42022111116.el7.aarch64.rpm
|
||||
devdeps-icu-69.1-72022112416.el7.aarch64.rpm
|
||||
|
||||
[tools]
|
||||
obdevtools-binutils-2.30-12022100413.el7.aarch64.rpm
|
||||
|
1
deps/init/oceanbase.el7.x86_64.deps
vendored
1
deps/init/oceanbase.el7.x86_64.deps
vendored
@ -28,6 +28,7 @@ devdeps-zlib-static-1.2.7-132022100815.el7.x86_64.rpm
|
||||
devdeps-ncurses-static-6.2-72022100815.el7.x86_64.rpm
|
||||
devdeps-boost-1.74.0-22022110914.el7.x86_64.rpm
|
||||
devdeps-s2geometry-0.9.0-42022111116.el7.x86_64.rpm
|
||||
devdeps-icu-69.1-72022112416.el7.x86_64.rpm
|
||||
|
||||
[tools]
|
||||
obdevtools-binutils-2.30-12022100413.el7.x86_64.rpm
|
||||
|
1
deps/init/oceanbase.el8.aarch64.deps
vendored
1
deps/init/oceanbase.el8.aarch64.deps
vendored
@ -26,6 +26,7 @@ devdeps-zlib-static-1.2.7-132022100815.el8.aarch64.rpm
|
||||
devdeps-ncurses-static-6.2-72022100815.el8.aarch64.rpm
|
||||
devdeps-boost-1.74.0-22022110914.el8.aarch64.rpm
|
||||
devdeps-s2geometry-0.9.0-42022111116.el8.aarch64.rpm
|
||||
devdeps-icu-69.1-72022112416.el8.aarch64.rpm
|
||||
|
||||
[tools]
|
||||
obdevtools-binutils-2.30-12022100413.el8.aarch64.rpm
|
||||
|
1
deps/init/oceanbase.el8.x86_64.deps
vendored
1
deps/init/oceanbase.el8.x86_64.deps
vendored
@ -27,6 +27,7 @@ devdeps-zlib-static-1.2.7-132022100815.el8.x86_64.rpm
|
||||
devdeps-ncurses-static-6.2-72022100815.el8.x86_64.rpm
|
||||
devdeps-boost-1.74.0-22022110914.el8.x86_64.rpm
|
||||
devdeps-s2geometry-0.9.0-42022111116.el8.x86_64.rpm
|
||||
devdeps-icu-69.1-72022112416.el8.x86_64.rpm
|
||||
|
||||
[tools]
|
||||
obdevtools-binutils-2.30-12022100413.el8.x86_64.rpm
|
||||
|
4
deps/oblib/src/CMakeLists.txt
vendored
4
deps/oblib/src/CMakeLists.txt
vendored
@ -22,6 +22,7 @@ target_include_directories(
|
||||
${DEP_3RD_DIR}/usr/include/
|
||||
${DEP_3RD_DIR}/usr/local/include
|
||||
${DEP_DIR}/include/apr-1/
|
||||
${DEP_DIR}/include/icu/common
|
||||
)
|
||||
|
||||
if (OB_USE_CLANG)
|
||||
@ -125,6 +126,9 @@ target_link_libraries(oblib_base_base_base
|
||||
$<$<STREQUAL:"${ARCHITECTURE}","x86_64">:${DEP_DIR}/lib/libunwind.a>
|
||||
${DEP_DIR}/lib/libz.a
|
||||
${DEP_DIR}/lib/libs2.a
|
||||
${DEP_DIR}/lib/libicui18n.a
|
||||
${DEP_DIR}/lib/libicustubdata.a
|
||||
${DEP_DIR}/lib/libicuuc.a
|
||||
-L${DEP_DIR}/var/usr/lib64
|
||||
-L${DEP_DIR}/var/usr/lib
|
||||
-L${DEP_3RD_DIR}/usr/lib
|
||||
|
1
deps/oblib/src/common/ob_range.h
vendored
1
deps/oblib/src/common/ob_range.h
vendored
@ -15,7 +15,6 @@
|
||||
|
||||
#include "lib/ob_define.h"
|
||||
#include "lib/utility/utility.h"
|
||||
#include "lib/regex/ob_regex.h"
|
||||
#include "common/rowkey/ob_rowkey.h"
|
||||
#include "common/ob_string_buf.h"
|
||||
|
||||
|
3
deps/oblib/src/common/object/ob_obj_funcs.h
vendored
3
deps/oblib/src/common/object/ob_obj_funcs.h
vendored
@ -2017,8 +2017,7 @@ template <>
|
||||
ret = databuff_printf(buffer, length, pos, "%s", N_UPPERCASE_CUR_TIMESTAMP);
|
||||
break;
|
||||
default:
|
||||
_OB_LOG(WARN, "ext %ld should not be print as sql", obj.get_ext());
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
ret = databuff_printf(buffer, length, pos, "%s", "Extend Obj");
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
|
9
deps/oblib/src/common/object/ob_object.h
vendored
9
deps/oblib/src/common/object/ob_object.h
vendored
@ -633,12 +633,15 @@ struct ObObjPrintParams
|
||||
uint32_t print_flags_;
|
||||
struct {
|
||||
uint32_t need_cast_expr_:1;
|
||||
uint32_t is_show_create_view_:1;
|
||||
uint32_t print_origin_stmt_:1;
|
||||
uint32_t use_memcpy_:1;
|
||||
uint32_t skip_escape_:1;
|
||||
uint32_t beginning_space_:1;
|
||||
uint32_t binary_string_print_hex_:1;
|
||||
uint32_t reserved_:26;
|
||||
uint32_t print_with_cte_:1;
|
||||
uint32_t force_print_cte_:1;
|
||||
uint32_t need_print_converter_:1;
|
||||
uint32_t reserved_:23;
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -1424,7 +1427,7 @@ struct ObDefaultHash : public ObjHashBase
|
||||
|
||||
struct ObMurmurHash : public ObjHashBase
|
||||
{
|
||||
static uint64_t hash(const void *data, uint64_t len, uint64_t seed)
|
||||
OB_INLINE static uint64_t hash(const void *data, uint64_t len, uint64_t seed)
|
||||
{
|
||||
return murmurhash64A(data, static_cast<int32_t>(len), seed);
|
||||
}
|
||||
|
1
deps/oblib/src/common/rowkey/ob_rowkey.h
vendored
1
deps/oblib/src/common/rowkey/ob_rowkey.h
vendored
@ -17,7 +17,6 @@
|
||||
#include "lib/oblog/ob_log.h"
|
||||
#include "lib/ob_define.h"
|
||||
#include "lib/utility/utility.h"
|
||||
#include "lib/regex/ob_regex.h"
|
||||
#include "lib/checksum/ob_crc64.h"
|
||||
#include "lib/json/ob_yson.h"
|
||||
#include "common/ob_common_utility.h"
|
||||
|
37
deps/oblib/src/common/sql_mode/ob_sql_mode.h
vendored
37
deps/oblib/src/common/sql_mode/ob_sql_mode.h
vendored
@ -25,11 +25,11 @@ extern "C" {
|
||||
#define SMO_REAL_AS_FLOAT (1ULL) /* support */
|
||||
#define SMO_PIPES_AS_CONCAT (1ULL << 1) /* support */
|
||||
#define SMO_ANSI_QUOTES (1ULL << 2) /* support */
|
||||
#define SMO_IGNORE_SPACE (1ULL << 3) /* not support now */
|
||||
#define SMO_IGNORE_SPACE (1ULL << 3) /* support but not used */
|
||||
#define SMO_NOT_USED (1ULL << 4) /* not support now */
|
||||
#define SMO_ONLY_FULL_GROUP_BY (1ULL << 5) /* support */
|
||||
#define SMO_NO_UNSIGNED_SUBTRACTION (1ULL << 6) /* support */
|
||||
#define SMO_NO_DIR_IN_CREATE (1ULL << 7) /* not support */
|
||||
#define SMO_NO_DIR_IN_CREATE (1ULL << 7) /* support but not used */
|
||||
#define SMO_POSTGRESQL (1ULL << 8) /*not support*/
|
||||
#define SMO_ORACLE (1ULL << 9) /*not support*/
|
||||
#define SMO_MSSQL (1ULL << 10) /*not support*/
|
||||
@ -55,6 +55,7 @@ extern "C" {
|
||||
#define SMO_NO_ENGINE_SUBSTITUTION (1ULL << 30) /* support but not used */
|
||||
#define SMO_PAD_CHAR_TO_FULL_LENGTH (1ULL << 31) /* support */
|
||||
#define SMO_ERROR_ON_RESOLVE_CAST (1ULL << 32) /* ERROR_ON_RESOLVE_CAST */
|
||||
#define SMO_TIME_TRUNCATE_FRACTIONAL (1ULL << 33) /* TIME_TRUNCATE_FRACTIONAL */
|
||||
|
||||
#define STR_ALLOW_INVALID_DATES "ALLOW_INVALID_DATES"
|
||||
#define STR_ANSI_QUOTES "ANSI_QUOTES"
|
||||
@ -90,15 +91,29 @@ extern "C" {
|
||||
#define STR_POSTGRESQL "POSTGRESQL"
|
||||
#define STR_MYSQL323 "MYSQL323"
|
||||
#define STR_MYSQL40 "MYSQL40"
|
||||
#define STR_COMBINE_TRADITIONAL "STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION"
|
||||
#define STR_COMBINE_ANSI "REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE"
|
||||
#define STR_COMBINE_DB2 "PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS"
|
||||
#define STR_COMBINE_MAXDB "PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER"
|
||||
#define STR_COMBINE_MSSQL "PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS"
|
||||
#define STR_COMBINE_ORACLE "PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER"
|
||||
#define STR_COMBINE_POSTGRESQL "PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS"
|
||||
#define STR_COMBINE_MYSQL323 "HIGH_NOT_PRECEDENCE"
|
||||
#define STR_COMBINE_MYSQL40 "HIGH_NOT_PRECEDENCE"
|
||||
#define STR_TIME_TRUNCATE_FRACTIONAL "TIME_TRUNCATE_FRACTIONAL"
|
||||
|
||||
#define COMBINE_SMO_TRADITIONAL (SMO_STRICT_TRANS_TABLES | SMO_STRICT_ALL_TABLES | SMO_NO_ZERO_IN_DATE | \
|
||||
SMO_NO_ZERO_DATE | SMO_ERROR_FOR_DIVISION_BY_ZERO | SMO_NO_AUTO_CREATE_USER | \
|
||||
SMO_NO_ENGINE_SUBSTITUTION | SMO_TRADITIONAL)
|
||||
#define COMBINE_SMO_ANSI (SMO_REAL_AS_FLOAT | SMO_PIPES_AS_CONCAT | SMO_ANSI_QUOTES | SMO_IGNORE_SPACE | \
|
||||
SMO_ANSI)
|
||||
#define COMBINE_SMO_DB2 (SMO_PIPES_AS_CONCAT | SMO_ANSI_QUOTES | SMO_IGNORE_SPACE | SMO_NO_KEY_OPTIONS | \
|
||||
SMO_NO_TABLE_OPTIONS | SMO_NO_FIELD_OPTIONS | SMO_DB2)
|
||||
#define COMBINE_SMO_MAXDB (SMO_PIPES_AS_CONCAT | SMO_ANSI_QUOTES | SMO_IGNORE_SPACE | SMO_NO_KEY_OPTIONS | \
|
||||
SMO_NO_TABLE_OPTIONS | SMO_NO_FIELD_OPTIONS | SMO_NO_AUTO_CREATE_USER | \
|
||||
MODE_MAXDB)
|
||||
#define COMBINE_SMO_MSSQL (SMO_PIPES_AS_CONCAT | SMO_ANSI_QUOTES | SMO_IGNORE_SPACE | SMO_NO_KEY_OPTIONS | \
|
||||
SMO_NO_TABLE_OPTIONS | SMO_NO_FIELD_OPTIONS | \
|
||||
SMO_MSSQL)
|
||||
#define COMBINE_SMO_ORACLE (SMO_PIPES_AS_CONCAT | SMO_ANSI_QUOTES | SMO_IGNORE_SPACE | SMO_NO_KEY_OPTIONS | \
|
||||
SMO_NO_TABLE_OPTIONS | SMO_NO_FIELD_OPTIONS | SMO_NO_AUTO_CREATE_USER | \
|
||||
SMO_ORACLE)
|
||||
#define COMBINE_SMO_POSTGRESQL (SMO_PIPES_AS_CONCAT | SMO_ANSI_QUOTES | SMO_IGNORE_SPACE | SMO_NO_KEY_OPTIONS | \
|
||||
SMO_NO_TABLE_OPTIONS | SMO_NO_FIELD_OPTIONS | \
|
||||
SMO_POSTGRESQL)
|
||||
#define COMBINE_SMO_MYSQL323 (SMO_HIGH_NOT_PRECEDENCE | SMO_MYSQL323)
|
||||
#define COMBINE_SMO_MYSQL40 (SMO_HIGH_NOT_PRECEDENCE | SMO_MYSQL40)
|
||||
|
||||
#define ALL_SMO_COMPACT_MODE (SMO_POSTGRESQL | SMO_ORACLE | SMO_MSSQL | SMO_DB2)
|
||||
|
||||
|
@ -39,9 +39,17 @@ ObSqlModeMap SQL_MODE_MAP[] = {
|
||||
{SMO_ONLY_FULL_GROUP_BY, STR_ONLY_FULL_GROUP_BY},
|
||||
{SMO_NO_UNSIGNED_SUBTRACTION, STR_NO_UNSIGNED_SUBTRACTION},
|
||||
{SMO_NO_DIR_IN_CREATE, STR_NO_DIR_IN_CREATE},
|
||||
{SMO_POSTGRESQL, STR_POSTGRESQL},
|
||||
{SMO_ORACLE, STR_ORACLE},
|
||||
{SMO_MSSQL, STR_MSSQL},
|
||||
{SMO_DB2, STR_DB2},
|
||||
{MODE_MAXDB, STR_MAXDB},
|
||||
{SMO_NO_KEY_OPTIONS, STR_NO_KEY_OPTIONS},
|
||||
{SMO_NO_TABLE_OPTIONS, STR_NO_TABLE_OPTIONS},
|
||||
{SMO_NO_FIELD_OPTIONS, STR_NO_FIELD_OPTIONS},
|
||||
{SMO_MYSQL323, STR_MYSQL323},
|
||||
{SMO_MYSQL40, STR_MYSQL40},
|
||||
{SMO_ANSI, STR_ANSI},
|
||||
{SMO_NO_AUTO_VALUE_ON_ZERO, STR_NO_AUTO_VALUE_ON_ZERO},
|
||||
{SMO_NO_BACKSLASH_ESCAPES, STR_NO_BACKSLASH_ESCAPES},
|
||||
{SMO_STRICT_TRANS_TABLES, STR_STRICT_TRANS_TABLES},
|
||||
@ -50,15 +58,51 @@ ObSqlModeMap SQL_MODE_MAP[] = {
|
||||
{SMO_NO_ZERO_DATE, STR_NO_ZERO_DATE},
|
||||
{SMO_ALLOW_INVALID_DATES, STR_ALLOW_INVALID_DATES},
|
||||
{SMO_ERROR_FOR_DIVISION_BY_ZERO, STR_ERROR_FOR_DIVISION_BY_ZERO},
|
||||
{SMO_TRADITIONAL, STR_TRADITIONAL},
|
||||
{SMO_NO_AUTO_CREATE_USER, STR_NO_AUTO_CREATE_USER},
|
||||
{SMO_HIGH_NOT_PRECEDENCE, STR_HIGH_NOT_PRECEDENCE},
|
||||
{SMO_NO_ENGINE_SUBSTITUTION, STR_NO_ENGINE_SUBSTITUTION},
|
||||
{SMO_PAD_CHAR_TO_FULL_LENGTH, STR_PAD_CHAR_TO_FULL_LENGTH},
|
||||
{SMO_TRADITIONAL, STR_COMBINE_TRADITIONAL}, //Search in order, ensure that combine_str is in front
|
||||
{SMO_TRADITIONAL, STR_TRADITIONAL},
|
||||
{SMO_ANSI, STR_COMBINE_ANSI},
|
||||
{SMO_ANSI, STR_ANSI},
|
||||
{SMO_ERROR_ON_RESOLVE_CAST, STR_ERROR_ON_RESOLVE_CAST},
|
||||
{SMO_TIME_TRUNCATE_FRACTIONAL, STR_TIME_TRUNCATE_FRACTIONAL},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
ObSqlModeMap STR_TO_SQL_MODE_MAP[] = {
|
||||
{SMO_REAL_AS_FLOAT, STR_REAL_AS_FLOAT},
|
||||
{SMO_PIPES_AS_CONCAT, STR_PIPES_AS_CONCAT},
|
||||
{SMO_ANSI_QUOTES, STR_ANSI_QUOTES},
|
||||
{SMO_IGNORE_SPACE, STR_IGNORE_SPACE},
|
||||
{SMO_NOT_USED, STR_NOT_USED},
|
||||
{SMO_ONLY_FULL_GROUP_BY, STR_ONLY_FULL_GROUP_BY},
|
||||
{SMO_NO_UNSIGNED_SUBTRACTION, STR_NO_UNSIGNED_SUBTRACTION},
|
||||
{SMO_NO_DIR_IN_CREATE, STR_NO_DIR_IN_CREATE},
|
||||
{COMBINE_SMO_POSTGRESQL, STR_POSTGRESQL},
|
||||
{COMBINE_SMO_ORACLE, STR_ORACLE},
|
||||
{COMBINE_SMO_MSSQL, STR_MSSQL},
|
||||
{COMBINE_SMO_DB2, STR_DB2},
|
||||
{COMBINE_SMO_MAXDB, STR_MAXDB},
|
||||
{SMO_NO_KEY_OPTIONS, STR_NO_KEY_OPTIONS},
|
||||
{SMO_NO_TABLE_OPTIONS, STR_NO_TABLE_OPTIONS},
|
||||
{SMO_NO_FIELD_OPTIONS, STR_NO_FIELD_OPTIONS},
|
||||
{COMBINE_SMO_MYSQL323, STR_MYSQL323},
|
||||
{COMBINE_SMO_MYSQL40, STR_MYSQL40},
|
||||
{COMBINE_SMO_ANSI, STR_ANSI},
|
||||
{SMO_NO_AUTO_VALUE_ON_ZERO, STR_NO_AUTO_VALUE_ON_ZERO},
|
||||
{SMO_NO_BACKSLASH_ESCAPES, STR_NO_BACKSLASH_ESCAPES},
|
||||
{SMO_STRICT_TRANS_TABLES, STR_STRICT_TRANS_TABLES},
|
||||
{SMO_STRICT_ALL_TABLES, STR_STRICT_ALL_TABLES},
|
||||
{SMO_NO_ZERO_IN_DATE, STR_NO_ZERO_IN_DATE},
|
||||
{SMO_NO_ZERO_DATE, STR_NO_ZERO_DATE},
|
||||
{SMO_ALLOW_INVALID_DATES, STR_ALLOW_INVALID_DATES},
|
||||
{SMO_ERROR_FOR_DIVISION_BY_ZERO, STR_ERROR_FOR_DIVISION_BY_ZERO},
|
||||
{COMBINE_SMO_TRADITIONAL, STR_TRADITIONAL},
|
||||
{SMO_NO_AUTO_CREATE_USER, STR_NO_AUTO_CREATE_USER},
|
||||
{SMO_HIGH_NOT_PRECEDENCE, STR_HIGH_NOT_PRECEDENCE},
|
||||
{SMO_NO_ENGINE_SUBSTITUTION, STR_NO_ENGINE_SUBSTITUTION},
|
||||
{SMO_PAD_CHAR_TO_FULL_LENGTH, STR_PAD_CHAR_TO_FULL_LENGTH},
|
||||
{SMO_ERROR_ON_RESOLVE_CAST, STR_ERROR_ON_RESOLVE_CAST},
|
||||
{SMO_TIME_TRUNCATE_FRACTIONAL, STR_TIME_TRUNCATE_FRACTIONAL},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
@ -81,7 +125,20 @@ ObSQLMode SUPPORT_MODE = SMO_STRICT_ALL_TABLES
|
||||
| SMO_NO_AUTO_CREATE_USER
|
||||
| SMO_NO_ENGINE_SUBSTITUTION
|
||||
| SMO_NO_ZERO_DATE
|
||||
| SMO_ERROR_FOR_DIVISION_BY_ZERO;
|
||||
| SMO_ERROR_FOR_DIVISION_BY_ZERO
|
||||
| SMO_TIME_TRUNCATE_FRACTIONAL
|
||||
| SMO_NO_DIR_IN_CREATE
|
||||
| SMO_IGNORE_SPACE
|
||||
| SMO_REAL_AS_FLOAT
|
||||
| SMO_ANSI
|
||||
| SMO_TRADITIONAL
|
||||
| SMO_POSTGRESQL
|
||||
| SMO_ORACLE
|
||||
| SMO_MSSQL
|
||||
| SMO_DB2
|
||||
| MODE_MAXDB
|
||||
| SMO_MYSQL323
|
||||
| SMO_MYSQL40;
|
||||
|
||||
bool is_sql_mode_supported(ObSQLMode mode)
|
||||
{
|
||||
@ -107,21 +164,21 @@ int ob_str_to_sql_mode(const ObString &str, ObSQLMode &mode)
|
||||
NULL != value && OB_SUCC(ret);
|
||||
value = strtok_r(NULL, ", ", &saveptr)) {
|
||||
uint64_t i = 0;
|
||||
for (; NULL != SQL_MODE_MAP[i].str_val && OB_SUCC(ret); ++i) {
|
||||
for (; NULL != STR_TO_SQL_MODE_MAP[i].str_val && OB_SUCC(ret); ++i) {
|
||||
// there is no need to use ObCharset::strcmp, because all valid values are comprised of
|
||||
// ascii character, we can use C string functions instead.
|
||||
// besides, we are sure that these two strings are both '\0' terminated, so strcasecmp().
|
||||
if (0 == STRCASECMP(value, SQL_MODE_MAP[i].str_val)) {
|
||||
tmp_mode |= SQL_MODE_MAP[i].int_val;
|
||||
if (is_sql_mode_supported(SQL_MODE_MAP[i].int_val)) {
|
||||
if (0 == STRCASECMP(value, STR_TO_SQL_MODE_MAP[i].str_val)) {
|
||||
tmp_mode |= STR_TO_SQL_MODE_MAP[i].int_val;
|
||||
if (is_sql_mode_supported(STR_TO_SQL_MODE_MAP[i].int_val)) {
|
||||
} else {
|
||||
LOG_WARN("invalid sql_mode, not supported", KCSTRING(SQL_MODE_MAP[i].str_val));
|
||||
LOG_WARN("invalid sql_mode, not supported", KCSTRING(STR_TO_SQL_MODE_MAP[i].str_val));
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (OB_ISNULL(SQL_MODE_MAP[i].str_val) && OB_SUCC(ret)) {
|
||||
if (OB_ISNULL(STR_TO_SQL_MODE_MAP[i].str_val) && OB_SUCC(ret)) {
|
||||
ret = OB_ERR_WRONG_VALUE_FOR_VAR;
|
||||
LOG_WARN("failed to set sql_mode", KCSTRING(value), K(ret));
|
||||
}
|
||||
|
@ -104,6 +104,12 @@ inline bool is_only_full_group_by_on(ObSQLMode mode)
|
||||
{
|
||||
return (SMO_ONLY_FULL_GROUP_BY & mode) || lib::is_oracle_mode();
|
||||
}
|
||||
|
||||
inline bool is_time_truncate_fractional(ObSQLMode mode)
|
||||
{
|
||||
return (SMO_TIME_TRUNCATE_FRACTIONAL & mode);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
2
deps/oblib/src/lib/CMakeLists.txt
vendored
2
deps/oblib/src/lib/CMakeLists.txt
vendored
@ -1,7 +1,5 @@
|
||||
add_subdirectory(compress)
|
||||
add_subdirectory(restore)
|
||||
add_subdirectory(regex)
|
||||
target_compile_definitions(regex PRIVATE -DREGEX_STANDALONE -DREGEX_WCHAR)
|
||||
|
||||
ob_set_subtarget(oblib_lib ALONE
|
||||
timezone/ob_timezone_util.cpp
|
||||
|
1
deps/oblib/src/lib/allocator/ob_allocator.h
vendored
1
deps/oblib/src/lib/allocator/ob_allocator.h
vendored
@ -104,6 +104,7 @@ public:
|
||||
return *this;
|
||||
}
|
||||
const ObIAllocator *get_alloc() const { return alloc_;}
|
||||
ObIAllocator *get_alloc() { return alloc_;}
|
||||
static uint32_t alloc_offset_bits()
|
||||
{
|
||||
DISABLE_WARNING_GCC_PUSH
|
||||
|
3
deps/oblib/src/lib/allocator/ob_mod_define.h
vendored
3
deps/oblib/src/lib/allocator/ob_mod_define.h
vendored
@ -711,6 +711,7 @@ LABEL_ITEM_DEF(OB_SQL_PS_SQL_META, SqlPsSqlMeta)
|
||||
LABEL_ITEM_DEF(OB_SQL_PX_BLOOM_FILTER, SqlPxBloomFilte)
|
||||
LABEL_ITEM_DEF(OB_PS_SESSION_INFO_ARRAY, PsSessiInfoArra)
|
||||
LABEL_ITEM_DEF(OB_CONNECT_BY_PUMP, ConnectByPump)
|
||||
LABEL_ITEM_DEF(OB_SQL_PLAN, SqlPlanManger)
|
||||
|
||||
//mpimodules
|
||||
LABEL_ITEM_DEF(OB_MPI_INTERM_RESULT, MpiIntermResult)
|
||||
@ -1300,7 +1301,7 @@ struct InnerModIds
|
||||
#undef LABEL_ITEM_DEF
|
||||
};
|
||||
enum { LABEL_COUNT_LIMIT = InnerModIds::OB_MOD_END };
|
||||
STATIC_ASSERT(LABEL_COUNT_LIMIT == 1033, "forbidden to add new label!!!");
|
||||
STATIC_ASSERT(LABEL_COUNT_LIMIT == 1034, "forbidden to add new label!!!");
|
||||
};
|
||||
|
||||
#define ObNewModIds ObModIds
|
||||
|
4
deps/oblib/src/lib/charset/ob_charset.cpp
vendored
4
deps/oblib/src/lib/charset/ob_charset.cpp
vendored
@ -15,6 +15,7 @@
|
||||
#include "lib/utility/serialization.h"
|
||||
#include "lib/ob_define.h"
|
||||
#include "lib/worker.h"
|
||||
#include "common/ob_common_utility.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -2608,7 +2609,8 @@ inline bool ObCharset::is_argument_valid(const ObCharsetInfo *cs, const char *st
|
||||
OB_ISNULL(cs) ||
|
||||
OB_ISNULL(cs->cset)) {
|
||||
is_arg_valid = false;
|
||||
BACKTRACE(ERROR, true, "invalid argument. charset info = %p, str = %p, str_len = %ld", cs, str, str_len);
|
||||
const ObFatalErrExtraInfoGuard *extra_info = ObFatalErrExtraInfoGuard::get_thd_local_val_ptr();
|
||||
BACKTRACE(ERROR, true, "invalid argument. charset info = %p, str = %p, str_len = %ld, extra_info=(%s)", cs, str, str_len, (NULL == extra_info) ? NULL : to_cstring(*extra_info));
|
||||
}
|
||||
}
|
||||
return is_arg_valid;
|
||||
|
3
deps/oblib/src/lib/charset/ob_charset.h
vendored
3
deps/oblib/src/lib/charset/ob_charset.h
vendored
@ -128,7 +128,8 @@ Coercibility Meaning Example
|
||||
2 Implicit collation Column value, stored routine parameter or local variable
|
||||
3 System constant such as USER() and VERSION() return value, or system variable
|
||||
4 Coercible Literal string
|
||||
5 Ignorable NULL or an expression derived from NULL
|
||||
5 Numeric or temporal value
|
||||
6 Ignorable NULL or an expression derived from NULL
|
||||
|
||||
for reasons why, please refer to
|
||||
https://dev.mysql.com/doc/refman/8.0/en/charset-collation-coercibility.html
|
||||
|
@ -19490,22 +19490,19 @@ size_t ob_varlen_encoding_gb18030_for_memcmp(const struct ObCharsetInfo* cs,
|
||||
*is_valid_unicode = 1;
|
||||
ob_charset_assert(cs != NULL);
|
||||
sort_order = cs->sort_order;
|
||||
for (; dst < de && src < se && nweights; nweights--) {
|
||||
for (; *is_valid_unicode && dst < de && src < se && nweights; nweights--) {
|
||||
uint mblen = cs->cset->ismbchar(cs, (const char *)src, (const char *)se);
|
||||
uint weight = 0;
|
||||
if (mblen > 0) {
|
||||
weight = get_weight_for_mbchar<INSENSITIVE>(cs, src, mblen);
|
||||
} else {
|
||||
weight = get_weight_for_mbchar<INSENSITIVE>(cs, src, mblen);
|
||||
dst += code_to_gb18030_chs(dst, de - dst, weight);
|
||||
src += mblen;
|
||||
} else {
|
||||
*is_valid_unicode = 0;
|
||||
weight = sort_order ? sort_order[*src] : *src;
|
||||
++src;
|
||||
}
|
||||
if (weight == 0) {
|
||||
dst += code_to_gb18030_chs(dst, de - dst, weight);
|
||||
weight = 0x0000000000000001;
|
||||
}
|
||||
dst += code_to_gb18030_chs(dst, de - dst, weight);
|
||||
src += mblen;
|
||||
}
|
||||
++src;
|
||||
}
|
||||
}
|
||||
// adds 0x0000 0000 0000 0000, 0x0000 0000 0000 0000
|
||||
memset(dst, 0x00, 8);
|
||||
dst += 8;
|
||||
@ -19514,8 +19511,8 @@ size_t ob_varlen_encoding_gb18030_for_memcmp(const struct ObCharsetInfo* cs,
|
||||
uint16_t find_space_char_count_gb18030(const uchar* src, const uchar* se)
|
||||
{
|
||||
int space_cnt = 1;
|
||||
while (*(src+space_cnt) == 0x20 && (src+space_cnt)<se) space_cnt++;
|
||||
if (space_cnt+src<se) return space_cnt;
|
||||
while ((src + space_cnt) < se && *(src + space_cnt) == 0x20 ) space_cnt++;
|
||||
if ((src + space_cnt) < se) return space_cnt;
|
||||
else return 0;
|
||||
}
|
||||
size_t ob_varlen_encoding_gb18030_for_spacecmp(const struct ObCharsetInfo* cs,
|
||||
@ -19531,7 +19528,7 @@ size_t ob_varlen_encoding_gb18030_for_spacecmp(const struct ObCharsetInfo* cs,
|
||||
ob_charset_assert(cs != NULL);
|
||||
sort_order = cs->sort_order;
|
||||
uint16_t space_cnt = 0xFFFF;
|
||||
for (; dst < de && src < se && nweights; nweights--) {
|
||||
for (;*is_valid_unicode && dst < de && src < se && nweights; nweights--) {
|
||||
// for reslovable multiple bytes, only space's first byte is 0x20,
|
||||
// in gb18030 encoding scheme
|
||||
if (*src == 0x20) {
|
||||
@ -19557,12 +19554,13 @@ size_t ob_varlen_encoding_gb18030_for_spacecmp(const struct ObCharsetInfo* cs,
|
||||
uint weight = 0;
|
||||
if (mblen > 0) {
|
||||
weight = get_weight_for_mbchar<INSENSITIVE>(cs, src, mblen);
|
||||
dst += code_to_gb18030_chs(dst, de - dst, weight);
|
||||
src += mblen;
|
||||
} else {
|
||||
*is_valid_unicode = 0;
|
||||
weight = sort_order ? sort_order[*src] : *src;
|
||||
++src;
|
||||
}
|
||||
dst += code_to_gb18030_chs(dst, de - dst, weight);
|
||||
}
|
||||
// adds 0x20, 0x20
|
||||
memset(dst, 0x00, 8);
|
||||
|
@ -3539,7 +3539,7 @@ size_t ob_varlen_encoding_gbk_for_memcmp(const struct ObCharsetInfo* cs,
|
||||
const uchar *sort_order= cs->sort_order;
|
||||
*is_valid_unicode = 1;
|
||||
|
||||
for (; dst < de && src < se && nweights; nweights--)
|
||||
for (; *is_valid_unicode && dst < de && src < se && nweights; nweights--)
|
||||
{
|
||||
if (isgbkhead(*(src)) && (se)-(src)>1 && isgbktail(*((src)+1)))
|
||||
{
|
||||
@ -3591,7 +3591,7 @@ size_t ob_varlen_encoding_gbk_for_spacecmp(const struct ObCharsetInfo* cs,
|
||||
|
||||
// trim
|
||||
while (*(se-1) == 0x20 && se>src) se--;
|
||||
for (; dst < de && src < se && nweights; nweights--)
|
||||
for (;*is_valid_unicode && dst < de && src < se && nweights; nweights--)
|
||||
{
|
||||
int16_t space_cnt = 0;
|
||||
uint16_t e = 0;
|
||||
|
@ -1162,7 +1162,7 @@ static ObCollationHandler ob_collation_utf16_bin_handler =
|
||||
ob_strnncollsp_utf16_bin,
|
||||
ob_strnxfrm_unicode_full_bin,
|
||||
ob_strnxfrmlen_unicode_full_bin,
|
||||
ob_strnxfrm_unicode_full_bin_varlen,
|
||||
NULL,
|
||||
ob_like_range_generic,
|
||||
ob_wildcmp_utf16_bin,
|
||||
NULL,
|
||||
@ -1179,7 +1179,7 @@ static ObCollationHandler ob_collation_utf16_general_ci_handler =
|
||||
ob_strnncollsp_utf16,
|
||||
ob_strnxfrm_unicode,
|
||||
ob_strnxfrmlen_simple,
|
||||
ob_strnxfrm_unicode_varlen,
|
||||
NULL,/*ob_strnxfrm_unicode_varlen_utf16,*/
|
||||
ob_like_range_generic,
|
||||
ob_wildcmp_utf16_ci,
|
||||
NULL,
|
||||
|
@ -2321,7 +2321,7 @@ size_t ob_varlen_encoding_for_memcmp(const struct ObCharsetInfo* cs,
|
||||
wc = 0;
|
||||
ob_charset_assert(src);
|
||||
*is_valid_unicode = 1;
|
||||
for (; dst < de && nweights; nweights--)
|
||||
for (;*is_valid_unicode && src < se && dst < de && nweights; nweights--)
|
||||
{
|
||||
if ((res= cs->cset->mb_wc(cs, &wc, src, se)) <= 0) {
|
||||
if (src < se) {
|
||||
@ -2353,8 +2353,8 @@ size_t ob_varlen_encoding_for_memcmp(const struct ObCharsetInfo* cs,
|
||||
uint16_t find_space_char_count(const uchar* src, const uchar* se)
|
||||
{
|
||||
int space_cnt = 1;
|
||||
while (*(src+space_cnt) == 0x20 && (src+space_cnt)<se) space_cnt++;
|
||||
if (space_cnt+src<se) return space_cnt;
|
||||
while ((src + space_cnt) < se && *(src + space_cnt) == 0x20) space_cnt++;
|
||||
if ((src + space_cnt) < se) return space_cnt;
|
||||
else return 0;
|
||||
}
|
||||
size_t ob_varlen_encoding_for_spacecmp(const struct ObCharsetInfo* cs,
|
||||
@ -2372,7 +2372,7 @@ size_t ob_varlen_encoding_for_spacecmp(const struct ObCharsetInfo* cs,
|
||||
ob_charset_assert(src);
|
||||
*is_valid_unicode = 1;
|
||||
uint16_t space_cnt = 0xFFFF;
|
||||
for (; dst < de && nweights; nweights--)
|
||||
for (;*is_valid_unicode && src < se && dst < de && nweights; nweights--)
|
||||
{
|
||||
// for reslovable multiple bytes, only space's first byte is 0x20,
|
||||
// in utf8 encoding scheme.
|
||||
|
12
deps/oblib/src/lib/container/ob_bit_set.h
vendored
12
deps/oblib/src/lib/container/ob_bit_set.h
vendored
@ -444,6 +444,8 @@ public:
|
||||
ObBitSet(const ObBitSet &other);
|
||||
template <int64_t O_N, typename O_ALLOC, bool O_AUTO_FREE>
|
||||
ObBitSet &operator=(const ObBitSet<O_N, O_ALLOC, O_AUTO_FREE> &other);
|
||||
template <int64_t O_N, typename O_ALLOC, bool O_AUTO_FREE>
|
||||
int assign(const ObBitSet<O_N, O_ALLOC, O_AUTO_FREE> &other);
|
||||
bool operator==(const ObBitSet &other) const;
|
||||
bool equal(const ObBitSet &other) const;
|
||||
|
||||
@ -912,6 +914,16 @@ ObBitSet<N, BlockAllocatorT, auto_free> &ObBitSet<N, BlockAllocatorT, auto_free>
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <int64_t N, typename BlockAllocatorT, bool auto_free> template <int64_t O_N, typename O_ALLOC, bool O_AUTO_FREE>
|
||||
int ObBitSet<N, BlockAllocatorT, auto_free>::assign(const ObBitSet<O_N, O_ALLOC, O_AUTO_FREE> &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (static_cast<void *>(this) != &other) {
|
||||
ret = bitset_word_array_.assign(other.bitset_word_array_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <int64_t N, typename BlockAllocatorT, bool auto_free>
|
||||
bool ObBitSet<N, BlockAllocatorT, auto_free>::operator==(const ObBitSet &other) const
|
||||
{
|
||||
|
4
deps/oblib/src/lib/container/ob_heap.h
vendored
4
deps/oblib/src/lib/container/ob_heap.h
vendored
@ -195,8 +195,8 @@ int ObBinaryHeap<T, CompareFunctor, LOCAL_ARRAY_SIZE>::upheap(int64_t index)
|
||||
index = parent;
|
||||
}
|
||||
|
||||
array_.at(index) = tmp;
|
||||
if (OB_SUCC(cmp_.get_error_code())) {
|
||||
array_.at(index) = tmp;
|
||||
record_index(index);
|
||||
reset_root_cmp_cache();
|
||||
}
|
||||
@ -229,6 +229,7 @@ int ObBinaryHeap<T, CompareFunctor, LOCAL_ARRAY_SIZE>::downheap(int64_t index)
|
||||
index = picked_child;
|
||||
}
|
||||
|
||||
array_.at(index) = tmp;
|
||||
if (OB_SUCC(cmp_.get_error_code())) {
|
||||
if (index == get_root()) {
|
||||
// We did not change anything in the tree except for the value
|
||||
@ -240,7 +241,6 @@ int ObBinaryHeap<T, CompareFunctor, LOCAL_ARRAY_SIZE>::downheap(int64_t index)
|
||||
// the tree changed, reset cache
|
||||
reset_root_cmp_cache();
|
||||
}
|
||||
array_.at(index) = tmp;
|
||||
record_index(index);
|
||||
}
|
||||
return ret;
|
||||
|
4
deps/oblib/src/lib/number/ob_number_v2.h
vendored
4
deps/oblib/src/lib/number/ob_number_v2.h
vendored
@ -453,9 +453,9 @@ public:
|
||||
if (!is_zero()) {
|
||||
const int32_t exp_val = get_decode_exp(d_);
|
||||
if (exp_val >= 0) {
|
||||
ret_len += std::max(exp_val + 1, static_cast<int32_t>(d_.len_)) * MAX_STORE_LEN;
|
||||
ret_len += std::max(exp_val + 1, static_cast<int32_t>(d_.len_)) * DIGIT_LEN;
|
||||
} else {
|
||||
ret_len += (0 - exp_val + static_cast<int32_t>(d_.len_)) * MAX_STORE_LEN;
|
||||
ret_len += (0 - exp_val + static_cast<int32_t>(d_.len_)) * DIGIT_LEN;
|
||||
}
|
||||
}
|
||||
return ret_len;
|
||||
|
35
deps/oblib/src/lib/ob_define.h
vendored
35
deps/oblib/src/lib/ob_define.h
vendored
@ -85,6 +85,7 @@ const int64_t OB_MAX_CLIENT_INFO_LENGTH = 64;
|
||||
const int64_t OB_MAX_MOD_NAME_LENGTH = 48;
|
||||
const int64_t OB_MAX_ACT_NAME_LENGTH = 32;
|
||||
const int64_t OB_MAX_UUID_LENGTH = 16;
|
||||
const int64_t OB_MAX_UUID_STR_LENGTH = 36;
|
||||
const int64_t MAX_ZONE_LENGTH = 128;
|
||||
const int64_t MAX_REGION_LENGTH = 128;
|
||||
const int64_t MAX_GTS_NAME_LENGTH = 128;
|
||||
@ -156,6 +157,9 @@ const uint64_t SEARRAY_INIT_NUM = 4;
|
||||
const int64_t OB_DEFAULT_TABLE_DOP = 1;
|
||||
const int64_t OB_DEFAULT_META_OBJ_PERCENTAGE_LIMIT = 10;
|
||||
const uint64_t OB_DEFAULT_COLUMN_SRS_ID = 0xffffffffffffffe0;
|
||||
const int64_t OB_MAX_SPAN_LENGTH = 1024;
|
||||
const int64_t OB_MAX_SPAN_TAG_LENGTH = 8 * 1024L;
|
||||
const int64_t OB_MAX_REF_TYPE_LENGTH = 10;
|
||||
|
||||
// See ObDeviceHealthStatus for more information
|
||||
const int64_t OB_MAX_DEVICE_HEALTH_STATUS_STR_LENGTH = 20;
|
||||
@ -789,6 +793,7 @@ const int64_t SYS_MAX_ALLOCATE_MEMORY = 1L << 34;
|
||||
|
||||
// mem factor
|
||||
const double SQL_AUDIT_MEM_FACTOR = 0.1;
|
||||
const double SQL_PLAN_MEM_FACTOR = 0.1;
|
||||
const double MONITOR_MEM_FACTOR = 0.01;
|
||||
const double KVCACHE_FACTOR = TENANT_RESERVE_MEM_RATIO;
|
||||
|
||||
@ -1570,12 +1575,21 @@ const int64_t OB_MAX_NUMBER_PRECISION = 38; //Number in Oracle: p:[1, 3
|
||||
const int64_t OB_MAX_NUMBER_PRECISION_INNER = 40; //Number in Oracle: p can reach 40 if not define by user
|
||||
const int64_t OB_MIN_NUMBER_SCALE = -84; //Number in Oracle: s:[-84, 127]
|
||||
const int64_t OB_MAX_NUMBER_SCALE = 127; //Number in Oracle: s:[-84, 127]
|
||||
|
||||
// len_ = 2, se_ = 192: 2 digits(e.g: 111.111)
|
||||
const uint32_t NUM_DESC_2DIGITS_POSITIVE_DECIMAL = 0xc0000002;
|
||||
// len_ = 1, se_ = 191: 1 digit fragment(e.g 0.111)
|
||||
const uint32_t NUM_DESC_1DIGIT_POSITIVE_FRAGMENT = 0xbf000001;
|
||||
// len_ = 1, se_ = 192: 1 digit integer(e.g 111)
|
||||
const uint32_t NUM_DESC_1DIGIT_POSITIVE_INTEGER = 0xc0000001;
|
||||
// len_ = 2, se_ = 64: 2 digits(e.g: -111.111)
|
||||
const uint32_t NUM_DESC_2DIGITS_NEGATIVE_DECIMAL = 0x40000002;
|
||||
// len_ = 1, se_ = 65: 1 digit fragment(e.g -0.111)
|
||||
const uint32_t NUM_DESC_1DIGIT_NEGATIVE_FRAGMENT = 0x41000001;
|
||||
// len_ = 1, se_ = 64: 1 digit integer(e.g -111)
|
||||
const uint32_t NUM_DESC_1DIGIT_NEGATIVE_INTEGER = 0x40000001;
|
||||
|
||||
|
||||
const int64_t OB_DECIMAL_NOT_SPECIFIED = -1;
|
||||
const int64_t OB_MIN_NUMBER_FLOAT_PRECISION = 1; //Float in Oracle: p[1, 126]
|
||||
const int64_t OB_MAX_NUMBER_FLOAT_PRECISION = 126;
|
||||
@ -2072,6 +2086,12 @@ enum ObWFRemoveMode
|
||||
REMOVE_EXTRENUM = 2
|
||||
};
|
||||
|
||||
enum ObTraceGranularity
|
||||
{
|
||||
QUERY_LEVEL = 0,
|
||||
TRANS_LEVEL = 1
|
||||
};
|
||||
|
||||
} // end namespace common
|
||||
} // end namespace oceanbase
|
||||
|
||||
@ -2166,6 +2186,7 @@ struct ObNumberDesc
|
||||
explicit ObNumberDesc(const uint32_t desc): desc_(desc) {}
|
||||
explicit ObNumberDesc(const uint8_t len, uint8_t flag, uint8_t exp, uint8_t sign)
|
||||
: len_(len), reserved_(0), flag_(flag), exp_(exp), sign_(sign) {}
|
||||
|
||||
bool is_2d_positive_decimal()
|
||||
{
|
||||
return (desc_ == oceanbase::common::NUM_DESC_2DIGITS_POSITIVE_DECIMAL);
|
||||
@ -2178,6 +2199,20 @@ struct ObNumberDesc
|
||||
{
|
||||
return (desc_ == oceanbase::common::NUM_DESC_1DIGIT_POSITIVE_INTEGER);
|
||||
}
|
||||
|
||||
bool is_2d_negative_decimal()
|
||||
{
|
||||
return (desc_ == oceanbase::common::NUM_DESC_2DIGITS_NEGATIVE_DECIMAL);
|
||||
}
|
||||
bool is_1d_negative_fragment()
|
||||
{
|
||||
return (desc_ == oceanbase::common::NUM_DESC_1DIGIT_NEGATIVE_FRAGMENT);
|
||||
}
|
||||
bool is_1d_negative_integer()
|
||||
{
|
||||
return (desc_ == oceanbase::common::NUM_DESC_1DIGIT_NEGATIVE_INTEGER);
|
||||
}
|
||||
|
||||
union
|
||||
{
|
||||
uint32_t desc_;
|
||||
|
17
deps/oblib/src/lib/ob_name_def.h
vendored
17
deps/oblib/src/lib/ob_name_def.h
vendored
@ -219,6 +219,7 @@
|
||||
#define N_FROZEN_VERSION "frozen_version"
|
||||
#define N_VERSION "version"
|
||||
#define N_OB_VERSION "ob_version"
|
||||
#define N_ICU_VERSION "icu_version"
|
||||
#define N_CONNECTION_ID "connection_id"
|
||||
#define N_SESSIONTIMEZONE "sessiontimezone"
|
||||
#define N_DBTIMEZONE "dbtimezone"
|
||||
@ -319,6 +320,11 @@
|
||||
#define N_END_VAL "end_value"
|
||||
#define N_INCLUDE_START "include_start"
|
||||
#define N_INCLUDE_END "include_end"
|
||||
#define N_IS_STRICT_IN "is_strict_in"
|
||||
#define N_CONTAIN_QUESTIONMARK "contain_questionmark"
|
||||
#define N_OFFSETS "offsets"
|
||||
#define N_MISSING_OFFSETS "missing_offsets"
|
||||
#define N_IN_PARAMS "in_params"
|
||||
#define N_PATTERN_VAL "pattern"
|
||||
#define N_ESCAPE_VAL "escape"
|
||||
#define N_ALWAYS_TRUE "always_true"
|
||||
@ -489,6 +495,8 @@
|
||||
#define N_COALESCE "coalesce"
|
||||
#define N_NVL "nvl"
|
||||
#define N_NVL2 "nvl2"
|
||||
#define N_FORMAT_BYTES "format_bytes"
|
||||
#define N_FORMAT_PICO_TIME "format_pico_time"
|
||||
#define N_EXPR_TYPE "expr_type"
|
||||
#define N_DIM "dimension"
|
||||
#define N_CASE "case"
|
||||
@ -785,6 +793,9 @@
|
||||
#define N_UUID "uuid"
|
||||
#define N_UUID_SHORT "uuid_short"
|
||||
#define N_SYS_GUID "sys_guid"
|
||||
#define N_UUID_TO_BIN "uuid_to_bin"
|
||||
#define N_IS_UUID "is_uuid"
|
||||
#define N_BIN_TO_UUID "bin_to_uuid"
|
||||
#define N_SET_TO_STR "set_to_str"
|
||||
#define N_ENUM_TO_STR "enum_to_str"
|
||||
#define N_SET_TO_INNER_TYPE "set_to_inner_type"
|
||||
@ -803,6 +814,7 @@
|
||||
#define N_CHR "chr"
|
||||
#define N_EXP "exp"
|
||||
#define N_CALC_UROWID "calc_urowid"
|
||||
#define N_NAME_CONST "name_const"
|
||||
//for dll udf
|
||||
#define N_NORMAL_UDF "dll_normal_user_defined_function"
|
||||
#define N_AGG_UDF "dll_agg_user_defined_function"
|
||||
@ -824,6 +836,11 @@
|
||||
|
||||
#define N_AES_ENCRYPT "aes_encrypt"
|
||||
#define N_AES_DECRYPT "aes_decrypt"
|
||||
#define N_DECODE "decode"
|
||||
#define N_ENCODE "encode"
|
||||
#define N_DES_DECRYPT "des_decrypt"
|
||||
#define N_DES_ENCRYPT "des_encrypt"
|
||||
#define N_ENCRYPT "encrypt"
|
||||
|
||||
|
||||
#define N_UID "uid"
|
||||
|
10
deps/oblib/src/lib/regex/CMakeLists.txt
vendored
10
deps/oblib/src/lib/regex/CMakeLists.txt
vendored
@ -1,10 +0,0 @@
|
||||
# Define object library regex
|
||||
oblib_add_library(regex
|
||||
regex/regcomp.cpp
|
||||
regex/regexec.cpp
|
||||
regex/regerror.cpp
|
||||
regex/regfree.cpp
|
||||
regex/regalone.cpp
|
||||
ob_regex.cpp
|
||||
ob_regex.h)
|
||||
target_link_libraries(regex oblib_base)
|
110
deps/oblib/src/lib/regex/ob_regex.cpp
vendored
110
deps/oblib/src/lib/regex/ob_regex.cpp
vendored
@ -1,110 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX LIB
|
||||
#include <stdlib.h>
|
||||
#include "lib/oblog/ob_log.h"
|
||||
#include "lib/allocator/ob_malloc.h"
|
||||
#include "lib/regex/ob_regex.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
ObRegex::ObRegex()
|
||||
: init_(false),
|
||||
match_(NULL),
|
||||
reg_(),
|
||||
nmatch_(0)
|
||||
{
|
||||
}
|
||||
|
||||
ObRegex::~ObRegex()
|
||||
{
|
||||
if (true == init_) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
||||
int ObRegex::init(const char* pattern, int flags)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(true == init_)) {
|
||||
ret = OB_NOT_INIT;
|
||||
LOG_WARN("already inited", K(ret), K(this));
|
||||
} else if (OB_ISNULL(pattern)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param pattern", K(ret), KP(pattern));
|
||||
} else {
|
||||
int tmp_ret = regcomp(®_, pattern, flags);
|
||||
if (OB_UNLIKELY(0 != tmp_ret)) {
|
||||
ret = OB_ERR_REGEXP_ERROR;
|
||||
LOG_WARN("fail to regcomp", K(ret), K(tmp_ret));
|
||||
} else {
|
||||
nmatch_ = reg_.re_nsub + 1;
|
||||
ObMemAttr attr;
|
||||
attr.label_ = ObModIds::OB_REGEX;
|
||||
match_ = (regmatch_t*)ob_malloc(sizeof(regmatch_t) * nmatch_, attr);
|
||||
if (OB_ISNULL(match_)) {
|
||||
ret = OB_ERR_REGEXP_ERROR;
|
||||
LOG_WARN("fail to create the regmatch object", K(ret));
|
||||
regfree(®_);
|
||||
} else {
|
||||
init_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObRegex::match(const char* text, int flags, bool &is_match)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
is_match = false;
|
||||
if (OB_UNLIKELY(!init_)) {
|
||||
ret = OB_NOT_INIT;
|
||||
LOG_WARN("not inited", K(ret), K(this));
|
||||
} else if (OB_ISNULL(text)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid param text", K(ret), KP(text));
|
||||
} else {
|
||||
int tmp_ret = regexec(®_, text, nmatch_, match_, flags);
|
||||
if (REG_NOMATCH == tmp_ret) {
|
||||
is_match = false;
|
||||
} else if (0 == tmp_ret) {
|
||||
is_match = true;
|
||||
} else {
|
||||
ret = OB_ERR_REGEXP_ERROR;
|
||||
const static int64_t REG_ERR_MSG_BUF_LEN = 512;
|
||||
char reg_err_msg[REG_ERR_MSG_BUF_LEN];
|
||||
size_t err_msg_len = regerror(tmp_ret, ®_, reg_err_msg, REG_ERR_MSG_BUF_LEN);
|
||||
LOG_WARN("fail to run match func: regexec", K(ret),
|
||||
K(tmp_ret), K(err_msg_len), KCSTRING(reg_err_msg));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObRegex::destroy()
|
||||
{
|
||||
if (init_) {
|
||||
regfree(®_);
|
||||
if (NULL != match_) {
|
||||
ob_free(match_);
|
||||
match_ = NULL;
|
||||
}
|
||||
nmatch_ = 0;
|
||||
init_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
52
deps/oblib/src/lib/regex/ob_regex.h
vendored
52
deps/oblib/src/lib/regex/ob_regex.h
vendored
@ -1,52 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE 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 OCEANBASE_LIB_REGEX_OB_REGEX_
|
||||
#define OCEANBASE_LIB_REGEX_OB_REGEX_
|
||||
|
||||
#include <regex.h>
|
||||
#include "lib/ob_define.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace common
|
||||
{
|
||||
class ObRegex
|
||||
{
|
||||
public:
|
||||
ObRegex();
|
||||
virtual ~ObRegex();
|
||||
public:
|
||||
int init(const char* pattern, int flags);
|
||||
int match(const char* text, int flags, bool &is_match);
|
||||
void destroy();
|
||||
inline const regmatch_t* get_match() const
|
||||
{
|
||||
return match_;
|
||||
}
|
||||
inline int64_t get_match_count() const
|
||||
{
|
||||
return static_cast<int64_t>(nmatch_);
|
||||
}
|
||||
private:
|
||||
bool init_;
|
||||
regmatch_t* match_;
|
||||
regex_t reg_;
|
||||
size_t nmatch_;
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObRegex);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif //OCEANBASE_LIB_REGEX_OB_REGEX_
|
||||
|
84
deps/oblib/src/lib/regex/regex/COPYRIGHT
vendored
84
deps/oblib/src/lib/regex/regex/COPYRIGHT
vendored
@ -1,84 +0,0 @@
|
||||
This regular expression package was originally developed by Henry Spencer.
|
||||
It bears the following copyright notice:
|
||||
|
||||
**********************************************************************
|
||||
|
||||
Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
|
||||
Development of this software was funded, in part, by Cray Research Inc.,
|
||||
UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
Corporation, none of whom are responsible for the results. The author
|
||||
thanks all of them.
|
||||
|
||||
Redistribution and use in source and binary forms -- with or without
|
||||
modification -- are permitted for any purpose, provided that
|
||||
redistributions in source form retain this entire copyright notice and
|
||||
indicate the origin and nature of any modifications.
|
||||
|
||||
I'd appreciate being given credit for this package in the documentation
|
||||
of software which uses it, but that is not a requirement.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
**********************************************************************
|
||||
|
||||
Oceanbase adopted the code out of Tcl 8.4.1. Portions of regc_locale.c
|
||||
and re_syntax.n were developed by Tcl developers other than Henry; these
|
||||
files bear the Tcl copyright and license notice:
|
||||
|
||||
**********************************************************************
|
||||
|
||||
This software is copyrighted by the Regents of the University of
|
||||
California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState
|
||||
Corporation and other parties. The following terms apply to all files
|
||||
associated with the software unless explicitly disclaimed in
|
||||
individual files.
|
||||
|
||||
The authors hereby grant permission to use, copy, modify, distribute,
|
||||
and license this software and its documentation for any purpose, provided
|
||||
that existing copyright notices are retained in all copies and that this
|
||||
notice is included verbatim in any distributions. No written agreement,
|
||||
license, or royalty fee is required for any of the authorized uses.
|
||||
Modifications to this software may be copyrighted by their authors
|
||||
and need not follow the licensing terms described here, provided that
|
||||
the new terms are clearly indicated on the first page of each file where
|
||||
they apply.
|
||||
|
||||
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
||||
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
||||
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
||||
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
||||
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
||||
MODIFICATIONS.
|
||||
|
||||
GOVERNMENT USE: If you are acquiring this software on behalf of the
|
||||
U.S. government, the Government shall have only "Restricted Rights"
|
||||
in the software and related documentation as defined in the Federal
|
||||
Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you
|
||||
are acquiring the software on behalf of the Department of Defense, the
|
||||
software shall be classified as "Commercial Computer Software" and the
|
||||
Government shall have only "Restricted Rights" as defined in Clause
|
||||
252.227-7013 (c) (1) of DFARs. Notwithstanding the foregoing, the
|
||||
authors grant the U.S. Government and others acting in its behalf
|
||||
permission to use and distribute the software in accordance with the
|
||||
terms specified in this license.
|
||||
|
||||
**********************************************************************
|
||||
|
||||
Subsequent modifications to the code by the Oceanbase project follow
|
||||
the same license terms as the rest of Oceanbase.
|
55
deps/oblib/src/lib/regex/regex/README
vendored
55
deps/oblib/src/lib/regex/regex/README
vendored
@ -1,55 +0,0 @@
|
||||
|
||||
This is a port to make standalone available the Henry Spencer's Regex Library
|
||||
from Tcl 8.6a2.
|
||||
|
||||
In the hope that the Tcl developers take this port as the base for their RE
|
||||
module, great effort was paid to not update the *.c files, sadly it was not
|
||||
possible. Some *.h files suffered dirty updates for the same reasons.
|
||||
|
||||
To build and test
|
||||
make
|
||||
./regtest_hsrex.sh
|
||||
|
||||
To rebuild
|
||||
make clean
|
||||
make
|
||||
|
||||
To build against the other library uncomment the proper line in the file
|
||||
regtest_hsrex.sh and execute again.
|
||||
# Either this one
|
||||
$CC -I. -I$H/inc -L. -lhsrex -o $rgbin $rgsrc
|
||||
# or this one
|
||||
#$CC -I. -I$H/inc -L. -lhswrex -DREGEX_WCHAR -o $rgbin $rgsrc
|
||||
|
||||
You would like to test with debuging information. Uncomment the proper line in
|
||||
the Makefile and rebuild.
|
||||
# Either this one
|
||||
#CFLAGS = -DREGEX_STANDALONE -fPIC -DREG_DEBUG -g
|
||||
# Or this one
|
||||
CFLAGS = -DREGEX_STANDALONE -fPIC -D_NDEBUG -O3
|
||||
|
||||
Two libraries are provided, libhsrex.so and libhswrex.so. The first one is for
|
||||
ascii character code and the second one for wide characters. Both libraries
|
||||
were tested in Linux and Solaris. Compiling and runing in Window$ should be
|
||||
easy.
|
||||
|
||||
The following entry point where defined in each library:
|
||||
ob_re_comp() (ob_re_wcomp() for wide char) to compile a RE
|
||||
ob_re_exec() (ob_re_wexec() for wide char) to parse data against a compiled RE.
|
||||
ob_regfree() To dispose the memory of a compiled RE.
|
||||
ob_regerror() Translates error codes to ascii strings.
|
||||
|
||||
It is pretty easy to add support for a ob_regcomp() regexec() front end. That
|
||||
front end functions should take care of UTF-8 to wide charater conversion, for
|
||||
instance.
|
||||
|
||||
The regression test script regtest_hsrex.sh contains an example of how to use
|
||||
the libraries. It just test cases I was interested on. Adding more use cases to
|
||||
that script should be easy.
|
||||
|
||||
Send any comments to Walter Waldo <wawasa@gmail.com>
|
||||
|
||||
Enjoy it,
|
||||
|
||||
Walter Waldo.
|
||||
|
340
deps/oblib/src/lib/regex/regex/ob_regex.h
vendored
340
deps/oblib/src/lib/regex/regex/ob_regex.h
vendored
@ -1,340 +0,0 @@
|
||||
#ifndef OCEANBASE_LIB_REGEX_REGEX_OB_REGEX_
|
||||
#define OCEANBASE_LIB_REGEX_REGEX_OB_REGEX_ /* never again */
|
||||
/*
|
||||
* regular expressions
|
||||
*
|
||||
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
*
|
||||
* Development of this software was funded, in part, by Cray Research Inc.,
|
||||
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
* Corporation, none of whom are responsible for the results. The author
|
||||
* thanks all of them.
|
||||
*
|
||||
* Redistribution and use in source and binary forms -- with or without
|
||||
* modification -- are permitted for any purpose, provided that
|
||||
* redistributions in source form retain this entire copyright notice and
|
||||
* indicate the origin and nature of any modifications.
|
||||
*
|
||||
* I'd appreciate being given credit for this package in the documentation of
|
||||
* software which uses it, but that is not a requirement.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*
|
||||
* Prototypes etc. marked with "^" within comments get gathered up (and
|
||||
* possibly edited) by the regfwd program and inserted near the bottom of this
|
||||
* file.
|
||||
*
|
||||
* We offer the option of declaring one wide-character version of the RE
|
||||
* functions as well as the char versions. To do that, define __REG_WIDE_T to
|
||||
* the type of wide characters (unfortunately, there is no consensus that
|
||||
* wchar_t is suitable) and __REG_WIDE_COMPILE and __REG_WIDE_EXEC to the
|
||||
* names to be used for the compile and execute functions (suggestion:
|
||||
* re_Xcomp and re_Xexec, where X is a letter suggestive of the wide type,
|
||||
* e.g. re_ucomp and re_uexec for Unicode). For cranky old compilers, it may
|
||||
* be necessary to do something like:
|
||||
* #define __REG_WIDE_COMPILE(a,b,c,d) re_Xcomp(a,b,c,d)
|
||||
* #define __REG_WIDE_EXEC(a,b,c,d,e,f,g) re_Xexec(a,b,c,d,e,f,g)
|
||||
* rather than just #defining the names as parameterless macros.
|
||||
*
|
||||
* For some specialized purposes, it may be desirable to suppress the
|
||||
* declarations of the "front end" functions, ob_regcomp() and ob_regexec(), or of
|
||||
* the char versions of the compile and execute functions. To suppress the
|
||||
* front-end functions, define __REG_NOFRONT. To suppress the char versions,
|
||||
* define __REG_NOCHAR.
|
||||
*
|
||||
* The right place to do those defines (and some others you may want, see
|
||||
* below) would be <sys/types.h>. If you don't have control of that file, the
|
||||
* right place to add your own defines to this file is marked below. This is
|
||||
* normally done automatically, by the makefile and regmkhdr, based on the
|
||||
* contents of regcustom.h.
|
||||
*/
|
||||
|
||||
#include "common/ob_common_utility.h"
|
||||
|
||||
/*
|
||||
* voodoo for C++
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Add your own defines, if needed, here.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Location where a chunk of regcustom.h is automatically spliced into this
|
||||
* file (working from its prototype, regproto.h).
|
||||
*/
|
||||
|
||||
/* --- begin --- */
|
||||
/* ensure certain things don't sneak in from system headers */
|
||||
#ifdef __REG_WIDE_T
|
||||
#undef __REG_WIDE_T
|
||||
#endif
|
||||
#ifdef __REG_WIDE_COMPILE
|
||||
#undef __REG_WIDE_COMPILE
|
||||
#endif
|
||||
#ifdef __REG_WIDE_EXEC
|
||||
#undef __REG_WIDE_EXEC
|
||||
#endif
|
||||
#ifdef __REG_REGOFF_T
|
||||
#undef __REG_REGOFF_T
|
||||
#endif
|
||||
#ifdef __REG_VOID_T
|
||||
#undef __REG_VOID_T
|
||||
#endif
|
||||
#ifdef __REG_CONST
|
||||
#undef __REG_CONST
|
||||
#endif
|
||||
#ifdef __REG_NOFRONT
|
||||
#undef __REG_NOFRONT
|
||||
#endif
|
||||
#ifdef __REG_NOCHAR
|
||||
#undef __REG_NOCHAR
|
||||
#endif
|
||||
/* interface types */
|
||||
#define __REG_WIDE_T Ob_UniChar
|
||||
#define __REG_REGOFF_T long /* not really right, but good enough... */
|
||||
#define __REG_VOID_T void
|
||||
#define __REG_CONST const
|
||||
/* names and declarations */
|
||||
#define __REG_WIDE_COMPILE ObReComp
|
||||
#define __REG_WIDE_EXEC ObReExec
|
||||
#define __REG_NOFRONT /* don't want ob_regcomp() and ob_regexec() */
|
||||
#define __REG_NOCHAR /* or the char versions */
|
||||
#define ob_regfree ObReFree
|
||||
#define ob_regerror ObReError
|
||||
/* --- end --- */
|
||||
#ifdef REGEX_STANDALONE
|
||||
# undef ob_regfree
|
||||
# undef ob_regerror
|
||||
# define ob_regfree ob_re_free
|
||||
# define ob_regerror ob_re_error
|
||||
# undef __REG_WIDE_T
|
||||
# define __REG_WIDE_T wchar_t
|
||||
# undef __REG_WIDE_COMPILE
|
||||
# define __REG_WIDE_COMPILE ob_re_wcomp
|
||||
# undef __REG_WIDE_EXEC
|
||||
# define __REG_WIDE_EXEC ob_re_wexec
|
||||
# ifndef REGEX_WCHAR
|
||||
# undef __REG_NOCHAR
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* interface types etc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ob_regoff_t has to be large enough to hold either off_t or ssize_t, and must
|
||||
* be signed; it's only a guess that long is suitable, so we offer
|
||||
* <sys/types.h> an override.
|
||||
*/
|
||||
#ifdef __REG_REGOFF_T
|
||||
typedef __REG_REGOFF_T ob_regoff_t;
|
||||
#else
|
||||
typedef long ob_regoff_t;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* For benefit of old compilers, we offer <sys/types.h> the option of
|
||||
* overriding the `void' type used to declare nonexistent return types.
|
||||
*/
|
||||
#ifdef __REG_VOID_T
|
||||
typedef __REG_VOID_T re_void;
|
||||
#else
|
||||
typedef void re_void;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Also for benefit of old compilers, <sys/types.h> can supply a macro which
|
||||
* expands to a substitute for `const'.
|
||||
*/
|
||||
#ifndef __REG_CONST
|
||||
#define __REG_CONST const
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* other interface types
|
||||
*/
|
||||
|
||||
/* the biggie, a compiled RE (or rather, a front end to same) */
|
||||
typedef struct {
|
||||
int re_magic; /* magic number */
|
||||
size_t re_nsub; /* number of subexpressions */
|
||||
long re_info; /* information about RE */
|
||||
#define OB_REG_UBACKREF 000001
|
||||
#define OB_REG_ULOOKAHEAD 000002
|
||||
#define OB_REG_UBOUNDS 000004
|
||||
#define OB_REG_UBRACES 000010
|
||||
#define OB_REG_UBSALNUM 000020
|
||||
#define OB_REG_UPBOTCH 000040
|
||||
#define OB_REG_UBBS 000100
|
||||
#define OB_REG_UNONPOSIX 000200
|
||||
#define OB_REG_UUNSPEC 000400
|
||||
#define OB_REG_UUNPORT 001000
|
||||
#define OB_REG_ULOCALE 002000
|
||||
#define OB_REG_UEMPTYMATCH 004000
|
||||
#define OB_REG_UIMPOSSIBLE 010000
|
||||
#define OB_REG_USHORTEST 020000
|
||||
int re_csize; /* sizeof(character) */
|
||||
const wchar_t *re_endp; /* backward compatibility kludge */
|
||||
/* the rest is opaque pointers to hidden innards */
|
||||
char *re_guts; /* `char *' is more portable than `void *' */
|
||||
char *re_fns;
|
||||
} ob_regex_t;
|
||||
|
||||
/* result reporting (may acquire more fields later) */
|
||||
typedef struct {
|
||||
ob_regoff_t rm_so; /* start of substring */
|
||||
ob_regoff_t rm_eo; /* end of substring */
|
||||
} ob_regmatch_t;
|
||||
|
||||
/* supplementary control and reporting */
|
||||
typedef struct {
|
||||
ob_regmatch_t rm_extend; /* see REG_EXPECT */
|
||||
} ob_rm_detail_t;
|
||||
|
||||
/*
|
||||
* compilation
|
||||
^ #ifndef __REG_NOCHAR
|
||||
^ int ob_re_comp(ob_regex_t *, __REG_CONST char *, size_t, int);
|
||||
^ #endif
|
||||
^ #ifndef __REG_NOFRONT
|
||||
^ int ob_regcomp(ob_regex_t *, __REG_CONST char *, int);
|
||||
^ #endif
|
||||
^ #ifdef __REG_WIDE_T
|
||||
^ int __REG_WIDE_COMPILE(ob_regex_t *, __REG_CONST __REG_WIDE_T *, size_t, int);
|
||||
^ #endif
|
||||
*/
|
||||
#define OB_REG_BASIC 000000 /* BREs (convenience) */
|
||||
#define OB_REG_EXTENDED 000001 /* EREs */
|
||||
#define OB_REG_ADVF 000002 /* advanced features in EREs */
|
||||
#define OB_REG_ADVANCED 000003 /* AREs (which are also EREs) */
|
||||
#define OB_REG_QUOTE 000004 /* no special characters, none */
|
||||
#define OB_REG_NOSPEC REG_QUOTE /* historical synonym */
|
||||
#define OB_REG_ICASE 000010 /* ignore case */
|
||||
#define OB_REG_NOSUB 000020 /* don't care about subexpressions */
|
||||
#define OB_REG_EXPANDED 000040 /* expanded format, white space & comments */
|
||||
#define OB_REG_NLSTOP 000100 /* \n doesn't match . or [^ ] */
|
||||
#define OB_REG_NLANCH 000200 /* ^ matches after \n, $ before */
|
||||
#define OB_REG_NEWLINE 000300 /* newlines are line terminators */
|
||||
#define OB_REG_PEND 000400 /* ugh -- backward-compatibility hack */
|
||||
#define OB_REG_EXPECT 001000 /* report details on partial/limited matches */
|
||||
#define OB_REG_BOSONLY 002000 /* temporary kludge for BOS-only matches */
|
||||
#define OB_REG_DUMP 004000 /* none of your business :-) */
|
||||
#define OB_REG_FAKE 010000 /* none of your business :-) */
|
||||
#define OB_REG_PROGRESS 020000 /* none of your business :-) */
|
||||
#define OB_REG_ORACLE_MODE 040000/*distinguish is oracle or mysql call regexp*/
|
||||
|
||||
/*
|
||||
* execution
|
||||
^ #ifndef __REG_NOCHAR
|
||||
^ int ob_re_exec(ob_regex_t *, __REG_CONST char *, size_t,
|
||||
^ ob_rm_detail_t *, size_t, ob_regmatch_t [], int);
|
||||
^ #endif
|
||||
^ #ifndef __REG_NOFRONT
|
||||
^ int ob_regexec(ob_regex_t *, __REG_CONST char *, size_t, ob_regmatch_t [], int);
|
||||
^ #endif
|
||||
^ #ifdef __REG_WIDE_T
|
||||
^ int __REG_WIDE_EXEC(ob_regex_t *, __REG_CONST __REG_WIDE_T *, size_t,
|
||||
^ ob_rm_detail_t *, size_t, ob_regmatch_t [], int);
|
||||
^ #endif
|
||||
*/
|
||||
#define OB_REG_NOTBOL 0001 /* BOS is not BOL */
|
||||
#define OB_REG_NOTEOL 0002 /* EOS is not EOL */
|
||||
#define OB_REG_STARTEND 0004 /* backward compatibility kludge */
|
||||
#define OB_REG_FTRACE 0010 /* none of your business */
|
||||
#define OB_REG_MTRACE 0020 /* none of your business */
|
||||
#define OB_REG_SMALL 0040 /* none of your business */
|
||||
|
||||
/*
|
||||
* misc generics (may be more functions here eventually)
|
||||
^ re_void ob_regfree(ob_regex_t *);
|
||||
*/
|
||||
|
||||
/*
|
||||
* error reporting
|
||||
* Be careful if modifying the list of error codes -- the table used by
|
||||
* ob_regerror() is generated automatically from this file!
|
||||
*
|
||||
* Note that there is no wide-char variant of ob_regerror at this time; what kind
|
||||
* of character is used for error reports is independent of what kind is used
|
||||
* in matching.
|
||||
*
|
||||
^ extern size_t ob_regerror(int, __REG_CONST ob_regex_t *, char *, size_t);
|
||||
*/
|
||||
#define OB_REG_OKAY 0 /* no errors detected */
|
||||
#define OB_REG_NOMATCH 1 /* failed to match */
|
||||
#define OB_REG_BADPAT 2 /* invalid regexp */
|
||||
#define OB_REG_ECOLLATE 3 /* invalid collating element */
|
||||
#define OB_REG_ECTYPE 4 /* invalid character class */
|
||||
#define OB_REG_EESCAPE 5 /* invalid escape \ sequence */
|
||||
#define OB_REG_ESUBREG 6 /* invalid backreference number */
|
||||
#define OB_REG_EBRACK 7 /* brackets [] not balanced */
|
||||
#define OB_REG_EPAREN 8 /* parentheses () not balanced */
|
||||
#define OB_REG_EBRACE 9 /* braces {} not balanced */
|
||||
#define OB_REG_BADBR 10 /* invalid repetition count(s) */
|
||||
#define OB_REG_ERANGE 11 /* invalid character range */
|
||||
#define OB_REG_ESPACE 12 /* out of memory */
|
||||
#define OB_REG_BADRPT 13 /* quantifier operand invalid */
|
||||
#define OB_REG_ASSERT 15 /* "can't happen" -- you found a bug */
|
||||
#define OB_REG_INVARG 16 /* invalid argument to regex function */
|
||||
#define OB_REG_MIXED 17 /* character widths of regex and string differ */
|
||||
#define OB_REG_BADOPT 18 /* invalid embedded option */
|
||||
#define OB_REG_ETOOBIG 19 /* nfa has too many states */
|
||||
/* two specials for debugging and testing */
|
||||
#define OB_REG_ATOI 101 /* convert error-code name to number */
|
||||
#define OB_REG_ITOA 102 /* convert error-code number to name */
|
||||
|
||||
|
||||
/*
|
||||
* the prototypes, as possibly munched by regfwd
|
||||
*/
|
||||
/* =====^!^===== begin forwards =====^!^===== */
|
||||
/* automatically gathered by fwd; do not hand-edit */
|
||||
/* === regproto.h === */
|
||||
#ifndef __REG_NOCHAR
|
||||
int ob_re_comp(ob_regex_t *, __REG_CONST unsigned char *, size_t, int);
|
||||
#endif
|
||||
#ifndef __REG_NOFRONT
|
||||
int ob_regcomp(ob_regex_t *, __REG_CONST char *, int);
|
||||
#endif
|
||||
#ifdef __REG_WIDE_T
|
||||
MODULE_SCOPE int __REG_WIDE_COMPILE(ob_regex_t *, __REG_CONST __REG_WIDE_T *, size_t, int);
|
||||
#endif
|
||||
#ifndef __REG_NOCHAR
|
||||
int ob_re_exec(ob_regex_t *, __REG_CONST unsigned char *, size_t, ob_rm_detail_t *, size_t, ob_regmatch_t [], int);
|
||||
#endif
|
||||
#ifndef __REG_NOFRONT
|
||||
int ob_regexec(ob_regex_t *, __REG_CONST char *, size_t, ob_regmatch_t [], int);
|
||||
#endif
|
||||
#ifdef __REG_WIDE_T
|
||||
MODULE_SCOPE int __REG_WIDE_EXEC(ob_regex_t *, __REG_CONST __REG_WIDE_T *, size_t, ob_rm_detail_t *, size_t, ob_regmatch_t [], int);
|
||||
#endif
|
||||
MODULE_SCOPE re_void ob_regfree(ob_regex_t *);
|
||||
MODULE_SCOPE size_t ob_regerror(int, __REG_CONST ob_regex_t *, char *, size_t);
|
||||
/* automatically gathered by fwd; do not hand-edit */
|
||||
/* =====^!^===== end forwards =====^!^===== */
|
||||
|
||||
/*
|
||||
* more C++ voodoo
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
265
deps/oblib/src/lib/regex/regex/regalone.cpp
vendored
265
deps/oblib/src/lib/regex/regex/regalone.cpp
vendored
@ -1,265 +0,0 @@
|
||||
#ifdef REGEX_WCHAR
|
||||
|
||||
#include "regcustom.h"
|
||||
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Ob_DStringInit --
|
||||
*
|
||||
* Initializes a dynamic string, discarding any previous contents of the
|
||||
* string Ob_DStringFree should have been called already if the dynamic
|
||||
* string was previously in use).
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The dynamic string is initialized to be empty.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Ob_DStringInit(
|
||||
Ob_DString *dsPtr) /* Pointer to structure for dynamic string. */
|
||||
{
|
||||
dsPtr->string = dsPtr->staticSpace;
|
||||
dsPtr->length = 0;
|
||||
dsPtr->spaceAvl = OB_DSTRING_STATIC_SIZE;
|
||||
dsPtr->staticSpace[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Ob_DStringSetLength --
|
||||
*
|
||||
* Change the length of a dynamic string. This can cause the string to
|
||||
* either grow or shrink, depending on the value of length.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The length of dsPtr is changed to length and a null byte is stored at
|
||||
* that position in the string. If length is larger than the space
|
||||
* allocated for dsPtr, then a panic occurs.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Ob_DStringSetLength(
|
||||
Ob_DString *dsPtr, /* Structure describing dynamic string. */
|
||||
int length) /* New length for dynamic string. */
|
||||
{
|
||||
int newsize;
|
||||
|
||||
if (length < 0) {
|
||||
length = 0;
|
||||
}
|
||||
if (length >= dsPtr->spaceAvl) {
|
||||
/*
|
||||
* There are two interesting cases here. In the first case, the user
|
||||
* may be trying to allocate a large buffer of a specific size. It
|
||||
* would be wasteful to overallocate that buffer, so we just allocate
|
||||
* enough for the requested size plus the trailing null byte. In the
|
||||
* second case, we are growing the buffer incrementally, so we need
|
||||
* behavior similar to Ob_DStringAppend. The requested length will
|
||||
* usually be a small delta above the current spaceAvl, so we'll end
|
||||
* up doubling the old size. This won't grow the buffer quite as
|
||||
* quickly, but it should be close enough.
|
||||
*/
|
||||
|
||||
newsize = dsPtr->spaceAvl * 2;
|
||||
if (length < newsize) {
|
||||
dsPtr->spaceAvl = newsize;
|
||||
} else {
|
||||
dsPtr->spaceAvl = length + 1;
|
||||
}
|
||||
if (dsPtr->string == dsPtr->staticSpace) {
|
||||
char *newString = (char *) ckalloc((unsigned) dsPtr->spaceAvl);
|
||||
|
||||
memcpy(newString, dsPtr->string, (size_t) dsPtr->length);
|
||||
dsPtr->string = newString;
|
||||
} else {
|
||||
dsPtr->string = (char *) ckrealloc((void *) dsPtr->string,
|
||||
(size_t) dsPtr->spaceAvl);
|
||||
}
|
||||
}
|
||||
dsPtr->length = length;
|
||||
dsPtr->string[length] = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
*
|
||||
* Ob_DStringFree --
|
||||
*
|
||||
* Frees up any memory allocated for the dynamic string and reinitializes
|
||||
* the string to an empty state.
|
||||
*
|
||||
* Results:
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* The previous contents of the dynamic string are lost, and the new
|
||||
* value is an empty string.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
void
|
||||
Ob_DStringFree(
|
||||
Ob_DString *dsPtr) /* Structure describing dynamic string. */
|
||||
{
|
||||
if (dsPtr->string != dsPtr->staticSpace) {
|
||||
ckfree(dsPtr->string);
|
||||
}
|
||||
dsPtr->string = dsPtr->staticSpace;
|
||||
dsPtr->length = 0;
|
||||
dsPtr->spaceAvl = OB_DSTRING_STATIC_SIZE;
|
||||
dsPtr->staticSpace[0] = '\0';
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Unicode characters less than this value are represented by themselves in
|
||||
* UTF-8 strings.
|
||||
*/
|
||||
|
||||
#define UNICODE_SELF 0x80
|
||||
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* Ob_UniCharToUtf --
|
||||
*
|
||||
* Store the given Ob_UniChar as a sequence of UTF-8 bytes in the
|
||||
* provided buffer. Equivalent to Plan 9 runetochar().
|
||||
*
|
||||
* Results:
|
||||
* The return values is the number of bytes in the buffer that were
|
||||
* consumed.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
INLINE int Ob_UniCharToUtf(
|
||||
int ch, /* The Ob_UniChar to be stored in the
|
||||
* buffer. */
|
||||
char *buf) /* Buffer in which the UTF-8 representation of
|
||||
* the Ob_UniChar is stored. Buffer must be
|
||||
* large enough to hold the UTF-8 character
|
||||
* (at most Ob_UTF_MAX bytes). */
|
||||
{
|
||||
if ((ch > 0) && (ch < UNICODE_SELF)) {
|
||||
buf[0] = (char) ch;
|
||||
return 1;
|
||||
}
|
||||
if (ch >= 0) {
|
||||
if (ch <= 0x7FF) {
|
||||
buf[1] = (char) ((ch | 0x80) & 0xBF);
|
||||
buf[0] = (char) ((ch >> 6) | 0xC0);
|
||||
return 2;
|
||||
}
|
||||
if (ch <= 0xFFFF) {
|
||||
three:
|
||||
buf[2] = (char) ((ch | 0x80) & 0xBF);
|
||||
buf[1] = (char) (((ch >> 6) | 0x80) & 0xBF);
|
||||
buf[0] = (char) ((ch >> 12) | 0xE0);
|
||||
return 3;
|
||||
}
|
||||
|
||||
#if Ob_UTF_MAX > 3
|
||||
if (ch <= 0x1FFFFF) {
|
||||
buf[3] = (char) ((ch | 0x80) & 0xBF);
|
||||
buf[2] = (char) (((ch >> 6) | 0x80) & 0xBF);
|
||||
buf[1] = (char) (((ch >> 12) | 0x80) & 0xBF);
|
||||
buf[0] = (char) ((ch >> 18) | 0xF0);
|
||||
return 4;
|
||||
}
|
||||
if (ch <= 0x3FFFFFF) {
|
||||
buf[4] = (char) ((ch | 0x80) & 0xBF);
|
||||
buf[3] = (char) (((ch >> 6) | 0x80) & 0xBF);
|
||||
buf[2] = (char) (((ch >> 12) | 0x80) & 0xBF);
|
||||
buf[1] = (char) (((ch >> 18) | 0x80) & 0xBF);
|
||||
buf[0] = (char) ((ch >> 24) | 0xF8);
|
||||
return 5;
|
||||
}
|
||||
if (ch <= 0x7FFFFFFF) {
|
||||
buf[5] = (char) ((ch | 0x80) & 0xBF);
|
||||
buf[4] = (char) (((ch >> 6) | 0x80) & 0xBF);
|
||||
buf[3] = (char) (((ch >> 12) | 0x80) & 0xBF);
|
||||
buf[2] = (char) (((ch >> 18) | 0x80) & 0xBF);
|
||||
buf[1] = (char) (((ch >> 24) | 0x80) & 0xBF);
|
||||
buf[0] = (char) ((ch >> 30) | 0xFC);
|
||||
return 6;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
ch = 0xFFFD;
|
||||
goto three;
|
||||
}
|
||||
|
||||
/*
|
||||
*---------------------------------------------------------------------------
|
||||
*
|
||||
* Ob_UniCharToUtfDString --
|
||||
*
|
||||
* Convert the given Unicode string to UTF-8.
|
||||
*
|
||||
* Results:
|
||||
* The return value is a pointer to the UTF-8 representation of the
|
||||
* Unicode string. Storage for the return value is appended to the end of
|
||||
* dsPtr.
|
||||
*
|
||||
* Side effects:
|
||||
* None.
|
||||
*
|
||||
*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
char * Ob_UniCharToUtfDString(
|
||||
const Ob_UniChar *uniStr, /* Unicode string to convert to UTF-8. */
|
||||
int uniLength, /* Length of Unicode string in Ob_UniChars
|
||||
* (must be >= 0). */
|
||||
Ob_DString *dsPtr) /* UTF-8 representation of string is appended
|
||||
* to this previously initialized DString. */
|
||||
{
|
||||
const Ob_UniChar *w, *wEnd;
|
||||
char *p, *string;
|
||||
int oldLength;
|
||||
|
||||
/*
|
||||
* UTF-8 string length in bytes will be <= Unicode string length *
|
||||
* Ob_UTF_MAX.
|
||||
*/
|
||||
|
||||
oldLength = Ob_DStringLength(dsPtr);
|
||||
Ob_DStringSetLength(dsPtr, (oldLength + uniLength + 1) * Ob_UTF_MAX);
|
||||
string = Ob_DStringValue(dsPtr) + oldLength;
|
||||
|
||||
p = string;
|
||||
wEnd = uniStr + uniLength;
|
||||
for (w = uniStr; w < wEnd; ) {
|
||||
p += Ob_UniCharToUtf(*w, p);
|
||||
w++;
|
||||
}
|
||||
Ob_DStringSetLength(dsPtr, oldLength + (p - string));
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
#endif /* REGEX_WCHAR */
|
246
deps/oblib/src/lib/regex/regex/regalone.h
vendored
246
deps/oblib/src/lib/regex/regex/regalone.h
vendored
@ -1,246 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef REGEX_STANDALONE
|
||||
# define REGEX_STANDALONE
|
||||
#endif
|
||||
|
||||
#ifdef REGEX_WCHAR
|
||||
# include <wctype.h>
|
||||
# include <wchar.h>
|
||||
typedef wchar_t chr;
|
||||
typedef chr Ob_UniChar;
|
||||
#else
|
||||
# include <ctype.h>
|
||||
typedef unsigned char chr;
|
||||
typedef wchar_t Ob_UniChar;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* In The standalone version we are more concerned with performance,
|
||||
* so an automatic var is our best choice.
|
||||
*/
|
||||
#define AllocVars(vPtr) \
|
||||
struct vars regex_autovar; \
|
||||
register struct vars *vPtr = ®ex_autovar;
|
||||
|
||||
#define MALLOC(n) calloc(1,n)
|
||||
#define FREE(p) free(VS(p))
|
||||
#define REALLOC(p,n) realloc(VS(p),n)
|
||||
#define ckalloc(n) calloc(1,n)
|
||||
#define ckrealloc(p,n) realloc(p,n)
|
||||
#define ckfree(p) free(p)
|
||||
|
||||
#ifdef REGEX_WCHAR
|
||||
# define Ob_UniCharToLower(c) towlower(c)
|
||||
# define Ob_UniCharToUpper(c) towupper(c)
|
||||
# define Ob_UniCharToTitle(c) towupper(c)
|
||||
# define Ob_UniCharIsAlpha(c) iswalpha(c)
|
||||
# define Ob_UniCharIsAlnum(c) iswalnum(c)
|
||||
# define Ob_UniCharIsDigit(c) iswdigit(c)
|
||||
# define Ob_UniCharIsSpace(c) iswspace(c)
|
||||
#else
|
||||
# define Ob_DStringInit(ds)
|
||||
# define Ob_UniCharToUtfDString(s,l,ds) (s)
|
||||
# define Ob_DStringFree(ds)
|
||||
# define Ob_UniCharToLower(c) tolower(c)
|
||||
# define Ob_UniCharToUpper(c) toupper(c)
|
||||
# define Ob_UniCharToTitle(c) toupper(c)
|
||||
# define Ob_UniCharIsAlpha(c) isalpha(c)
|
||||
# define Ob_UniCharIsAlnum(c) isalnum(c)
|
||||
# define Ob_UniCharIsDigit(c) isdigit(c)
|
||||
# define Ob_UniCharIsSpace(c) isspace(c)
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The maximum number of bytes that are necessary to represent a single
|
||||
* Unicode character in UTF-8. The valid values should be 3 or 6 (or perhaps 1
|
||||
* if we want to support a non-unicode enabled core). If 3, then Ob_UniChar
|
||||
* must be 2-bytes in size (UCS-2) (the default). If 6, then Ob_UniChar must
|
||||
* be 4-bytes in size (UCS-4). At this time UCS-2 mode is the default and
|
||||
* recommended mode. UCS-4 is experimental and not recommended. It works for
|
||||
* the core, but most extensions expect UCS-2.
|
||||
*/
|
||||
|
||||
#ifndef Ob_UTF_MAX
|
||||
#define Ob_UTF_MAX 3
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* The structure defined below is used to hold dynamic strings. The only
|
||||
* fields that clients should use are string and length, accessible via the
|
||||
* macros Ob_DStringValue and Ob_DStringLength.
|
||||
*/
|
||||
|
||||
#define OB_DSTRING_STATIC_SIZE 200
|
||||
typedef struct Ob_DString {
|
||||
char *string; /* Points to beginning of string: either
|
||||
* staticSpace below or a malloced array. */
|
||||
int length; /* Number of non-NULL characters in the
|
||||
* string. */
|
||||
int spaceAvl; /* Total number of bytes available for the
|
||||
* string and its terminating NULL char. */
|
||||
char staticSpace[OB_DSTRING_STATIC_SIZE];
|
||||
/* Space to use in common case where string is
|
||||
* small. */
|
||||
} Ob_DString;
|
||||
|
||||
#define Ob_DStringLength(dsPtr) ((dsPtr)->length)
|
||||
#define Ob_DStringValue(dsPtr) ((dsPtr)->string)
|
||||
|
||||
|
||||
/*
|
||||
* The macro below is used to modify a "char" value (e.g. by casting it to an
|
||||
* unsigned character) so that it can be used safely with macros such as
|
||||
* isspace.
|
||||
*/
|
||||
|
||||
#define UCHAR(c) ((unsigned char) (c))
|
||||
|
||||
|
||||
/*
|
||||
* Used to tag functions that are only to be visible within the module being
|
||||
* built and not outside it (where this is supported by the linker).
|
||||
*/
|
||||
#ifndef MODULE_SCOPE
|
||||
# ifdef __cplusplus
|
||||
# define MODULE_SCOPE extern "C"
|
||||
#else
|
||||
# define MODULE_SCOPE extern
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Macros used to declare a function to be exported by a DLL. Used by Windows,
|
||||
* maps to no-op declarations on non-Windows systems. The default build on
|
||||
* windows is for a DLL, which causes the DLLIMPORT and DLLEXPORT macros to be
|
||||
* nonempty. To build a static library, the macro STATIC_BUILD should be
|
||||
* defined.
|
||||
*
|
||||
* Note: when building static but linking dynamically to MSVCRT we must still
|
||||
* correctly decorate the C library imported function. Use CRTIMPORT
|
||||
* for this purpose. _DLL is defined by the compiler when linking to
|
||||
* MSVCRT.
|
||||
*/
|
||||
|
||||
#if (defined(__WIN32__) && (defined(_MSC_VER) || (__BORLANDC__ >= 0x0550) || defined(__LCC__) || defined(__WATCOMC__) || (defined(__GNUC__) && defined(__declspec))))
|
||||
# define HAVE_DECLSPEC 1
|
||||
# ifdef STATIC_BUILD
|
||||
# define DLLIMPORT
|
||||
# define DLLEXPORT
|
||||
# ifdef _DLL
|
||||
# define CRTIMPORT __declspec(dllimport)
|
||||
# else
|
||||
# define CRTIMPORT
|
||||
# endif
|
||||
# else
|
||||
# define DLLIMPORT __declspec(dllimport)
|
||||
# define DLLEXPORT __declspec(dllexport)
|
||||
# define CRTIMPORT __declspec(dllimport)
|
||||
# endif
|
||||
#else
|
||||
# define DLLIMPORT
|
||||
# if defined(__GNUC__) && __GNUC__ > 3
|
||||
# define DLLEXPORT __attribute__ ((visibility("default")))
|
||||
# else
|
||||
# define DLLEXPORT
|
||||
# endif
|
||||
# define CRTIMPORT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* These macros are used to control whether functions are being declared for
|
||||
* import or export. If a function is being declared while it is being built
|
||||
* to be included in a shared library, then it should have the DLLEXPORT
|
||||
* storage class. If is being declared for use by a module that is going to
|
||||
* link against the shared library, then it should have the DLLIMPORT storage
|
||||
* class. If the symbol is beind declared for a static build or for use from a
|
||||
* stub library, then the storage class should be empty.
|
||||
*
|
||||
* The convention is that a macro called BUILD_xxxx, where xxxx is the name of
|
||||
* a library we are building, is set on the compile line for sources that are
|
||||
* to be placed in the library. When this macro is set, the storage class will
|
||||
* be set to DLLEXPORT. At the end of the header file, the storage class will
|
||||
* be reset to DLLIMPORT.
|
||||
*/
|
||||
|
||||
#undef Ob_STORAGE_CLASS
|
||||
#ifdef BUILD_Ob
|
||||
# define Ob_STORAGE_CLASS DLLEXPORT
|
||||
#else
|
||||
# ifdef USE_Ob_STUBS
|
||||
# define Ob_STORAGE_CLASS
|
||||
# else
|
||||
# define Ob_STORAGE_CLASS DLLIMPORT
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Definitions that allow this header file to be used either with or without
|
||||
* ANSI C features like function prototypes.
|
||||
*/
|
||||
|
||||
#undef _ANSI_ARGS_
|
||||
#ifndef INLINE
|
||||
# define INLINE
|
||||
#endif
|
||||
|
||||
#ifndef NO_CONST
|
||||
# define CONST1 const
|
||||
#else
|
||||
# define CONST1
|
||||
#endif
|
||||
|
||||
#ifndef NO_PROTOTYPES
|
||||
# define _ANSI_ARGS_(x) x
|
||||
#else
|
||||
# define _ANSI_ARGS_(x) ()
|
||||
#endif
|
||||
|
||||
#ifdef USE_NON_CONST
|
||||
# ifdef USE_COMPAT_CONST
|
||||
# error define at most one of USE_NON_CONST and USE_COMPAT_CONST
|
||||
# endif
|
||||
# define CONST84
|
||||
# define CONST84_RETURN
|
||||
#else
|
||||
# ifdef USE_COMPAT_CONST
|
||||
# define CONST84
|
||||
# define CONST84_RETURN CONST1
|
||||
# else
|
||||
# define CONST84 CONST1
|
||||
# define CONST84_RETURN CONST1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef CONST86
|
||||
# define CONST86 CONST1
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Make sure EXTERN isn't defined elsewhere
|
||||
*/
|
||||
|
||||
#ifdef EXTERN
|
||||
# undef EXTERN
|
||||
#endif /* EXTERN */
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define EXTERN extern "C" Ob_STORAGE_CLASS
|
||||
#else
|
||||
# define EXTERN extern Ob_STORAGE_CLASS
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef REGEX_WCHAR
|
||||
EXTERN void Ob_DStringFree (Ob_DString * dsPtr);
|
||||
EXTERN void Ob_DStringInit (Ob_DString * dsPtr);
|
||||
EXTERN char * Ob_UniCharToUtfDString (CONST1 Ob_UniChar * uniStr,
|
||||
int uniLength, Ob_DString * dsPtr);
|
||||
EXTERN void Ob_DStringSetLength (Ob_DString * dsPtr,
|
||||
int length);
|
||||
#endif /* REGEX_WCHAR */
|
856
deps/oblib/src/lib/regex/regex/regc_color.cpp
vendored
856
deps/oblib/src/lib/regex/regex/regc_color.cpp
vendored
@ -1,856 +0,0 @@
|
||||
/*
|
||||
* colorings of characters
|
||||
* This file is #included by regcomp.c.
|
||||
*
|
||||
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
*
|
||||
* Development of this software was funded, in part, by Cray Research Inc.,
|
||||
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
* Corporation, none of whom are responsible for the results. The author
|
||||
* thanks all of them.
|
||||
*
|
||||
* Redistribution and use in source and binary forms -- with or without
|
||||
* modification -- are permitted for any purpose, provided that
|
||||
* redistributions in source form retain this entire copyright notice and
|
||||
* indicate the origin and nature of any modifications.
|
||||
*
|
||||
* I'd appreciate being given credit for this package in the documentation of
|
||||
* software which uses it, but that is not a requirement.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Note that there are some incestuous relationships between this code and NFA
|
||||
* arc maintenance, which perhaps ought to be cleaned up sometime.
|
||||
*/
|
||||
|
||||
#define CISERR() VISERR(cm->v)
|
||||
#define CERR(e) VERR(cm->v, (e))
|
||||
|
||||
/*
|
||||
- initcm - set up new colormap
|
||||
^ static void initcm(struct vars *, struct colormap *);
|
||||
*/
|
||||
static void
|
||||
initcm(
|
||||
struct vars *v,
|
||||
struct colormap *cm)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
union tree *t;
|
||||
union tree *nextt;
|
||||
struct colordesc *cd;
|
||||
|
||||
cm->magic = CMMAGIC;
|
||||
cm->v = v;
|
||||
|
||||
cm->ncds = NINLINECDS;
|
||||
cm->cd = cm->cdspace;
|
||||
cm->max = 0;
|
||||
cm->free = 0;
|
||||
|
||||
cd = cm->cd; /* cm->cd[WHITE] */
|
||||
cd->sub = NOSUB;
|
||||
cd->arcs = NULL;
|
||||
cd->flags = 0;
|
||||
cd->nchrs = CHR_MAX - CHR_MIN + 1;
|
||||
|
||||
/*
|
||||
* Upper levels of tree.
|
||||
*/
|
||||
|
||||
for (t=&cm->tree[0], j=NBYTS-1 ; j>0 ; t=nextt, j--) {
|
||||
nextt = t + 1;
|
||||
for (i=BYTTAB-1 ; i>=0 ; i--) {
|
||||
t->tptr[i] = nextt;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Bottom level is solid white.
|
||||
*/
|
||||
|
||||
t = &cm->tree[NBYTS-1];
|
||||
for (i=BYTTAB-1 ; i>=0 ; i--) {
|
||||
t->tcolor[i] = WHITE;
|
||||
}
|
||||
cd->block = t;
|
||||
}
|
||||
|
||||
/*
|
||||
- freecm - free dynamically-allocated things in a colormap
|
||||
^ static void freecm(struct colormap *);
|
||||
*/
|
||||
static void
|
||||
freecm(
|
||||
struct colormap *cm)
|
||||
{
|
||||
size_t i;
|
||||
union tree *cb;
|
||||
|
||||
cm->magic = 0;
|
||||
if (NBYTS > 1) {
|
||||
cmtreefree(cm, cm->tree, 0);
|
||||
}
|
||||
for (i=1 ; i<=cm->max ; i++) { /* skip WHITE */
|
||||
if (!UNUSEDCOLOR(&cm->cd[i])) {
|
||||
cb = cm->cd[i].block;
|
||||
if (cb != NULL) {
|
||||
FREE(cb);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cm->cd != cm->cdspace) {
|
||||
FREE(cm->cd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- cmtreefree - free a non-terminal part of a colormap tree
|
||||
^ static void cmtreefree(struct colormap *, union tree *, int);
|
||||
*/
|
||||
static void
|
||||
cmtreefree(
|
||||
struct colormap *cm,
|
||||
union tree *tree,
|
||||
int level) /* level number (top == 0) of this block */
|
||||
{
|
||||
int i;
|
||||
union tree *t;
|
||||
union tree *fillt = &cm->tree[level+1];
|
||||
union tree *cb;
|
||||
|
||||
assert(level < NBYTS-1); /* this level has pointers */
|
||||
for (i=BYTTAB-1 ; i>=0 ; i--) {
|
||||
t = tree->tptr[i];
|
||||
assert(t != NULL);
|
||||
if (t != fillt) {
|
||||
if (level < NBYTS-2) { /* more pointer blocks below */
|
||||
cmtreefree(cm, t, level+1);
|
||||
FREE(t);
|
||||
} else { /* color block below */
|
||||
cb = cm->cd[t->tcolor[0]].block;
|
||||
if (t != cb) { /* not a solid block */
|
||||
FREE(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- setcolor - set the color of a character in a colormap
|
||||
^ static color setcolor(struct colormap *, pchr, pcolor);
|
||||
*/
|
||||
static color /* previous color */
|
||||
setcolor(
|
||||
struct colormap *cm,
|
||||
pchr c,
|
||||
pcolor co)
|
||||
{
|
||||
uchr uc = c;
|
||||
int shift;
|
||||
int level;
|
||||
int b;
|
||||
int bottom;
|
||||
union tree *t;
|
||||
union tree *newt;
|
||||
union tree *fillt;
|
||||
union tree *lastt;
|
||||
union tree *cb;
|
||||
color prev;
|
||||
|
||||
assert(cm->magic == CMMAGIC);
|
||||
if (CISERR() || co == COLORLESS) {
|
||||
return COLORLESS;
|
||||
}
|
||||
|
||||
t = cm->tree;
|
||||
for (level=0, shift=BYTBITS*(NBYTS-1) ; shift>0; level++, shift-=BYTBITS){
|
||||
b = (uc >> shift) & BYTMASK;
|
||||
lastt = t;
|
||||
t = lastt->tptr[b];
|
||||
assert(t != NULL);
|
||||
fillt = &cm->tree[level+1];
|
||||
bottom = (shift <= BYTBITS) ? 1 : 0;
|
||||
cb = (bottom) ? cm->cd[t->tcolor[0]].block : fillt;
|
||||
if (t == fillt || t == cb) { /* must allocate a new block */
|
||||
newt = (union tree *) MALLOC((bottom) ?
|
||||
sizeof(struct colors) : sizeof(struct ptrs));
|
||||
if (newt == NULL) {
|
||||
CERR(OB_REG_ESPACE);
|
||||
return COLORLESS;
|
||||
}
|
||||
if (bottom) {
|
||||
memcpy(newt->tcolor, t->tcolor, BYTTAB*sizeof(color));
|
||||
} else {
|
||||
memcpy(newt->tptr, t->tptr, BYTTAB*sizeof(union tree *));
|
||||
}
|
||||
t = newt;
|
||||
lastt->tptr[b] = t;
|
||||
}
|
||||
}
|
||||
|
||||
b = uc & BYTMASK;
|
||||
prev = t->tcolor[b];
|
||||
t->tcolor[b] = (color) co;
|
||||
return prev;
|
||||
}
|
||||
|
||||
/*
|
||||
- maxcolor - report largest color number in use
|
||||
^ static color maxcolor(struct colormap *);
|
||||
*/
|
||||
static color
|
||||
maxcolor(
|
||||
struct colormap *cm)
|
||||
{
|
||||
if (CISERR()) {
|
||||
return COLORLESS;
|
||||
}
|
||||
|
||||
return (color) cm->max;
|
||||
}
|
||||
|
||||
/*
|
||||
- newcolor - find a new color (must be subject of setcolor at once)
|
||||
* Beware: may relocate the colordescs.
|
||||
^ static color newcolor(struct colormap *);
|
||||
*/
|
||||
static color /* COLORLESS for error */
|
||||
newcolor(
|
||||
struct colormap *cm)
|
||||
{
|
||||
struct colordesc *cd;
|
||||
size_t n;
|
||||
|
||||
if (CISERR()) {
|
||||
return COLORLESS;
|
||||
}
|
||||
|
||||
if (cm->free != 0) {
|
||||
assert(cm->free > 0);
|
||||
assert((size_t) cm->free < cm->ncds);
|
||||
cd = &cm->cd[cm->free];
|
||||
assert(UNUSEDCOLOR(cd));
|
||||
assert(cd->arcs == NULL);
|
||||
cm->free = cd->sub;
|
||||
} else if (cm->max < cm->ncds - 1) {
|
||||
cm->max++;
|
||||
cd = &cm->cd[cm->max];
|
||||
} else {
|
||||
struct colordesc *newCd;
|
||||
|
||||
/*
|
||||
* Oops, must allocate more.
|
||||
*/
|
||||
|
||||
n = cm->ncds * 2;
|
||||
if (cm->cd == cm->cdspace) {
|
||||
newCd = (struct colordesc *) MALLOC(n * sizeof(struct colordesc));
|
||||
if (newCd != NULL) {
|
||||
memcpy(newCd, cm->cdspace,
|
||||
cm->ncds * sizeof(struct colordesc));
|
||||
}
|
||||
} else {
|
||||
newCd = (struct colordesc *)
|
||||
REALLOC(cm->cd, n * sizeof(struct colordesc));
|
||||
}
|
||||
if (newCd == NULL) {
|
||||
CERR(OB_REG_ESPACE);
|
||||
return COLORLESS;
|
||||
}
|
||||
cm->cd = newCd;
|
||||
cm->ncds = n;
|
||||
assert(cm->max < cm->ncds - 1);
|
||||
cm->max++;
|
||||
cd = &cm->cd[cm->max];
|
||||
}
|
||||
|
||||
cd->nchrs = 0;
|
||||
cd->sub = NOSUB;
|
||||
cd->arcs = NULL;
|
||||
cd->flags = 0;
|
||||
cd->block = NULL;
|
||||
|
||||
return (color) (cd - cm->cd);
|
||||
}
|
||||
|
||||
/*
|
||||
- freecolor - free a color (must have no arcs or subcolor)
|
||||
^ static void freecolor(struct colormap *, pcolor);
|
||||
*/
|
||||
static void
|
||||
freecolor(
|
||||
struct colormap *cm,
|
||||
pcolor co)
|
||||
{
|
||||
assert(co >= 0);
|
||||
struct colordesc *cd = &cm->cd[co];
|
||||
color pco, nco; /* for freelist scan */
|
||||
|
||||
assert(co >= 0);
|
||||
if (co == WHITE) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(cd->arcs == NULL);
|
||||
assert(cd->sub == NOSUB);
|
||||
assert(cd->nchrs == 0);
|
||||
cd->flags = FREECOL;
|
||||
if (cd->block != NULL) {
|
||||
FREE(cd->block);
|
||||
cd->block = NULL; /* just paranoia */
|
||||
}
|
||||
|
||||
if ((size_t) co == cm->max) {
|
||||
while (cm->max > WHITE && UNUSEDCOLOR(&cm->cd[cm->max])) {
|
||||
cm->max--;
|
||||
}
|
||||
assert(cm->free >= 0);
|
||||
while ((size_t) cm->free > cm->max) {
|
||||
cm->free = cm->cd[cm->free].sub;
|
||||
}
|
||||
if (cm->free > 0) {
|
||||
assert(cm->free < cm->max);
|
||||
pco = cm->free;
|
||||
nco = cm->cd[pco].sub;
|
||||
while (nco > 0) {
|
||||
if ((size_t) nco > cm->max) {
|
||||
/*
|
||||
* Take this one out of freelist.
|
||||
*/
|
||||
|
||||
nco = cm->cd[nco].sub;
|
||||
cm->cd[pco].sub = nco;
|
||||
} else {
|
||||
assert(nco < cm->max);
|
||||
pco = nco;
|
||||
nco = cm->cd[pco].sub;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
cd->sub = cm->free;
|
||||
cm->free = (color) (cd - cm->cd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- pseudocolor - allocate a false color, to be managed by other means
|
||||
^ static color pseudocolor(struct colormap *);
|
||||
*/
|
||||
static color
|
||||
pseudocolor(
|
||||
struct colormap *cm)
|
||||
{
|
||||
color co;
|
||||
|
||||
co = newcolor(cm);
|
||||
if (CISERR()) {
|
||||
return COLORLESS;
|
||||
}
|
||||
assert(co >= 0);
|
||||
cm->cd[co].nchrs = 1;
|
||||
cm->cd[co].flags = PSEUDO;
|
||||
return co;
|
||||
}
|
||||
|
||||
/*
|
||||
- subcolor - allocate a new subcolor (if necessary) to this chr
|
||||
^ static color subcolor(struct colormap *, pchr c);
|
||||
*/
|
||||
static color
|
||||
subcolor(
|
||||
struct colormap *cm,
|
||||
pchr c)
|
||||
{
|
||||
color co; /* current color of c */
|
||||
color sco; /* new subcolor */
|
||||
assert(c >= 0);
|
||||
co = GETCOLOR(cm, c);
|
||||
sco = newsub(cm, co);
|
||||
if (CISERR()) {
|
||||
return COLORLESS;
|
||||
}
|
||||
assert(sco != COLORLESS);
|
||||
|
||||
if (co == sco) { /* already in an open subcolor */
|
||||
return co; /* rest is redundant */
|
||||
}
|
||||
assert(co >= 0 && sco >= 0);
|
||||
cm->cd[co].nchrs--;
|
||||
cm->cd[sco].nchrs++;
|
||||
setcolor(cm, c, sco);
|
||||
return sco;
|
||||
}
|
||||
|
||||
/*
|
||||
- newsub - allocate a new subcolor (if necessary) for a color
|
||||
^ static color newsub(struct colormap *, pcolor);
|
||||
*/
|
||||
static color
|
||||
newsub(
|
||||
struct colormap *cm,
|
||||
pcolor co)
|
||||
{
|
||||
color sco; /* new subcolor */
|
||||
assert(co >= 0);
|
||||
sco = cm->cd[co].sub;
|
||||
if (sco == NOSUB) { /* color has no open subcolor */
|
||||
if (cm->cd[co].nchrs == 1) { /* optimization */
|
||||
return co;
|
||||
}
|
||||
sco = newcolor(cm); /* must create subcolor */
|
||||
if (sco == COLORLESS) {
|
||||
assert(CISERR());
|
||||
return COLORLESS;
|
||||
}
|
||||
assert(co >= 0 && sco >= 0);
|
||||
cm->cd[co].sub = sco;
|
||||
cm->cd[sco].sub = sco; /* open subcolor points to self */
|
||||
}
|
||||
assert(sco != NOSUB);
|
||||
|
||||
return sco;
|
||||
}
|
||||
|
||||
/*
|
||||
- subrange - allocate new subcolors to this range of chrs, fill in arcs
|
||||
^ static void subrange(struct vars *, pchr, pchr, struct state *,
|
||||
^ struct state *);
|
||||
*/
|
||||
static void
|
||||
subrange(
|
||||
struct vars *v,
|
||||
pchr from,
|
||||
pchr to,
|
||||
struct state *lp,
|
||||
struct state *rp)
|
||||
{
|
||||
uchr uf;
|
||||
int i;
|
||||
|
||||
assert(from <= to);
|
||||
|
||||
/*
|
||||
* First, align "from" on a tree-block boundary
|
||||
*/
|
||||
|
||||
uf = (uchr) from;
|
||||
i = (int) (((uf + BYTTAB - 1) & (uchr) ~BYTMASK) - uf);
|
||||
for (; from<=to && i>0; i--, from++) {
|
||||
newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
|
||||
}
|
||||
if (from > to) { /* didn't reach a boundary */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deal with whole blocks.
|
||||
*/
|
||||
|
||||
for (; to-from>=BYTTAB ; from+=BYTTAB) {
|
||||
subblock(v, from, lp, rp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up any remaining partial table.
|
||||
*/
|
||||
|
||||
for (; from<=to ; from++) {
|
||||
newarc(v->nfa, PLAIN, subcolor(v->cm, from), lp, rp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- subblock - allocate new subcolors for one tree block of chrs, fill in arcs
|
||||
^ static void subblock(struct vars *, pchr, struct state *, struct state *);
|
||||
*/
|
||||
static void
|
||||
subblock(
|
||||
struct vars *v,
|
||||
pchr start, /* first of BYTTAB chrs */
|
||||
struct state *lp,
|
||||
struct state *rp)
|
||||
{
|
||||
uchr uc = start;
|
||||
struct colormap *cm = v->cm;
|
||||
int shift;
|
||||
int level;
|
||||
int i;
|
||||
int b;
|
||||
union tree *t;
|
||||
union tree *cb;
|
||||
union tree *fillt;
|
||||
union tree *lastt;
|
||||
int previ;
|
||||
int ndone;
|
||||
color co;
|
||||
color sco;
|
||||
|
||||
assert((uc % BYTTAB) == 0);
|
||||
|
||||
/*
|
||||
* Find its color block, making new pointer blocks as needed.
|
||||
*/
|
||||
|
||||
t = cm->tree;
|
||||
fillt = NULL;
|
||||
for (level=0, shift=BYTBITS*(NBYTS-1); shift>0; level++, shift-=BYTBITS) {
|
||||
b = (uc >> shift) & BYTMASK;
|
||||
lastt = t;
|
||||
t = lastt->tptr[b];
|
||||
assert(t != NULL);
|
||||
fillt = &cm->tree[level+1];
|
||||
if (t == fillt && shift > BYTBITS) { /* need new ptr block */
|
||||
t = (union tree *) MALLOC(sizeof(struct ptrs));
|
||||
if (t == NULL) {
|
||||
CERR(OB_REG_ESPACE);
|
||||
return;
|
||||
}
|
||||
memcpy(t->tptr, fillt->tptr, BYTTAB*sizeof(union tree *));
|
||||
lastt->tptr[b] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Special cases: fill block or solid block.
|
||||
*/
|
||||
co = t->tcolor[0];
|
||||
assert(co >= 0);
|
||||
cb = cm->cd[co].block;
|
||||
if (t == fillt || t == cb) {
|
||||
/*
|
||||
* Either way, we want a subcolor solid block.
|
||||
*/
|
||||
|
||||
sco = newsub(cm, co);
|
||||
assert(sco >= 0);
|
||||
t = cm->cd[sco].block;
|
||||
if (t == NULL) { /* must set it up */
|
||||
t = (union tree *) MALLOC(sizeof(struct colors));
|
||||
if (t == NULL) {
|
||||
CERR(OB_REG_ESPACE);
|
||||
return;
|
||||
}
|
||||
for (i=0 ; i<BYTTAB ; i++) {
|
||||
t->tcolor[i] = sco;
|
||||
}
|
||||
cm->cd[sco].block = t;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find loop must have run at least once.
|
||||
*/
|
||||
|
||||
lastt->tptr[b] = t;
|
||||
newarc(v->nfa, PLAIN, sco, lp, rp);
|
||||
assert(sco >= 0 && co >= 0);
|
||||
cm->cd[co].nchrs -= BYTTAB;
|
||||
cm->cd[sco].nchrs += BYTTAB;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* General case, a mixed block to be altered.
|
||||
*/
|
||||
|
||||
i = 0;
|
||||
while (i < BYTTAB) {
|
||||
co = t->tcolor[i];
|
||||
sco = newsub(cm, co);
|
||||
newarc(v->nfa, PLAIN, sco, lp, rp);
|
||||
previ = i;
|
||||
do {
|
||||
t->tcolor[i++] = sco;
|
||||
} while (i < BYTTAB && t->tcolor[i] == co);
|
||||
ndone = i - previ;
|
||||
assert(sco >= 0 && co >= 0);
|
||||
cm->cd[co].nchrs -= ndone;
|
||||
cm->cd[sco].nchrs += ndone;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- okcolors - promote subcolors to full colors
|
||||
^ static void okcolors(struct nfa *, struct colormap *);
|
||||
*/
|
||||
static void
|
||||
okcolors(
|
||||
struct nfa *nfa,
|
||||
struct colormap *cm)
|
||||
{
|
||||
struct colordesc *cd;
|
||||
struct colordesc *end = CDEND(cm);
|
||||
struct colordesc *scd;
|
||||
struct arc *a;
|
||||
color co;
|
||||
color sco;
|
||||
|
||||
for (cd=cm->cd, co=0 ; cd<end ; cd++, co++) {
|
||||
sco = cd->sub;
|
||||
if (UNUSEDCOLOR(cd) || sco == NOSUB) {
|
||||
/*
|
||||
* Has no subcolor, no further action.
|
||||
*/
|
||||
} else if (sco == co) {
|
||||
/*
|
||||
* Is subcolor, let parent deal with it.
|
||||
*/
|
||||
} else if (cd->nchrs == 0) {
|
||||
/*
|
||||
* Parent empty, its arcs change color to subcolor.
|
||||
*/
|
||||
assert(sco >= 0);
|
||||
cd->sub = NOSUB;
|
||||
scd = &cm->cd[sco];
|
||||
assert(scd->nchrs > 0);
|
||||
assert(scd->sub == sco);
|
||||
scd->sub = NOSUB;
|
||||
while ((a = cd->arcs) != NULL) {
|
||||
assert(a->co == co);
|
||||
uncolorchain(cm, a);
|
||||
a->co = sco;
|
||||
colorchain(cm, a);
|
||||
}
|
||||
freecolor(cm, co);
|
||||
} else {
|
||||
/*
|
||||
* Parent's arcs must gain parallel subcolor arcs.
|
||||
*/
|
||||
assert(sco >= 0);
|
||||
cd->sub = NOSUB;
|
||||
scd = &cm->cd[sco];
|
||||
assert(scd->nchrs > 0);
|
||||
assert(scd->sub == sco);
|
||||
scd->sub = NOSUB;
|
||||
for (a=cd->arcs ; a!=NULL ; a=a->colorchain) {
|
||||
assert(a->co == co);
|
||||
newarc(nfa, a->type, sco, a->from, a->to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- colorchain - add this arc to the color chain of its color
|
||||
^ static void colorchain(struct colormap *, struct arc *);
|
||||
*/
|
||||
static void
|
||||
colorchain(
|
||||
struct colormap *cm,
|
||||
struct arc *a)
|
||||
{
|
||||
struct colordesc *cd = &cm->cd[a->co];
|
||||
|
||||
if (cd->arcs != NULL) {
|
||||
cd->arcs->colorchainRev = a;
|
||||
}
|
||||
a->colorchain = cd->arcs;
|
||||
a->colorchainRev = NULL;
|
||||
cd->arcs = a;
|
||||
}
|
||||
|
||||
/*
|
||||
- uncolorchain - delete this arc from the color chain of its color
|
||||
^ static void uncolorchain(struct colormap *, struct arc *);
|
||||
*/
|
||||
static void
|
||||
uncolorchain(
|
||||
struct colormap *cm,
|
||||
struct arc *a)
|
||||
{
|
||||
struct colordesc *cd = &cm->cd[a->co];
|
||||
struct arc *aa = a->colorchainRev;
|
||||
|
||||
if (aa == NULL) {
|
||||
assert(cd->arcs == a);
|
||||
cd->arcs = a->colorchain;
|
||||
} else {
|
||||
assert(aa->colorchain == a);
|
||||
aa->colorchain = a->colorchain;
|
||||
}
|
||||
if (a->colorchain != NULL) {
|
||||
a->colorchain->colorchainRev = aa;
|
||||
}
|
||||
a->colorchain = NULL; /* paranoia */
|
||||
a->colorchainRev = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
- rainbow - add arcs of all full colors (but one) between specified states
|
||||
^ static void rainbow(struct nfa *, struct colormap *, int, pcolor,
|
||||
^ struct state *, struct state *);
|
||||
*/
|
||||
static void
|
||||
rainbow(
|
||||
struct nfa *nfa,
|
||||
struct colormap *cm,
|
||||
int type,
|
||||
pcolor but, /* COLORLESS if no exceptions */
|
||||
struct state *from,
|
||||
struct state *to)
|
||||
{
|
||||
struct colordesc *cd;
|
||||
struct colordesc *end = CDEND(cm);
|
||||
color co;
|
||||
|
||||
for (cd=cm->cd, co=0 ; cd<end && !CISERR(); cd++, co++) {
|
||||
if (!UNUSEDCOLOR(cd) && (cd->sub != co) && (co != but)
|
||||
&& !(cd->flags&PSEUDO)) {
|
||||
newarc(nfa, type, co, from, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- colorcomplement - add arcs of complementary colors
|
||||
* The calling sequence ought to be reconciled with cloneouts().
|
||||
^ static void colorcomplement(struct nfa *, struct colormap *, int,
|
||||
^ struct state *, struct state *, struct state *);
|
||||
*/
|
||||
static void
|
||||
colorcomplement(
|
||||
struct nfa *nfa,
|
||||
struct colormap *cm,
|
||||
int type,
|
||||
struct state *of, /* complements of this guy's PLAIN outarcs */
|
||||
struct state *from,
|
||||
struct state *to)
|
||||
{
|
||||
struct colordesc *cd;
|
||||
struct colordesc *end = CDEND(cm);
|
||||
color co;
|
||||
|
||||
assert(of != from);
|
||||
for (cd=cm->cd, co=0 ; cd<end && !CISERR() ; cd++, co++) {
|
||||
if (!UNUSEDCOLOR(cd) && !(cd->flags&PSEUDO)) {
|
||||
if (findarc(of, PLAIN, co) == NULL) {
|
||||
newarc(nfa, type, co, from, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OB_REG_DEBUG
|
||||
/*
|
||||
^ #ifdef OB_REG_DEBUG
|
||||
*/
|
||||
|
||||
/*
|
||||
- dumpcolors - debugging output
|
||||
^ static void dumpcolors(struct colormap *, FILE *);
|
||||
*/
|
||||
static void
|
||||
dumpcolors(
|
||||
struct colormap *cm,
|
||||
FILE *f)
|
||||
{
|
||||
struct colordesc *cd;
|
||||
struct colordesc *end;
|
||||
color co;
|
||||
chr c;
|
||||
char *has;
|
||||
|
||||
fprintf(f, "max %ld\n", (long) cm->max);
|
||||
if (NBYTS > 1) {
|
||||
fillcheck(cm, cm->tree, 0, f);
|
||||
}
|
||||
end = CDEND(cm);
|
||||
for (cd=cm->cd+1, co=1 ; cd<end ; cd++, co++) { /* skip 0 */
|
||||
if (!UNUSEDCOLOR(cd)) {
|
||||
assert(cd->nchrs > 0);
|
||||
has = (cd->block != NULL) ? "#" : "";
|
||||
if (cd->flags&PSEUDO) {
|
||||
fprintf(f, "#%2ld%s(ps): ", (long) co, has);
|
||||
} else {
|
||||
fprintf(f, "#%2ld%s(%2d): ", (long) co, has, cd->nchrs);
|
||||
}
|
||||
|
||||
/*
|
||||
* It's hard to do this more efficiently.
|
||||
*/
|
||||
|
||||
for (c=CHR_MIN ; c<CHR_MAX ; c++) {
|
||||
if (GETCOLOR(cm, c) == co) {
|
||||
dumpchr(c, f);
|
||||
}
|
||||
}
|
||||
assert(c == CHR_MAX);
|
||||
if (GETCOLOR(cm, c) == co) {
|
||||
dumpchr(c, f);
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- fillcheck - check proper filling of a tree
|
||||
^ static void fillcheck(struct colormap *, union tree *, int, FILE *);
|
||||
*/
|
||||
static void
|
||||
fillcheck(
|
||||
struct colormap *cm,
|
||||
union tree *tree,
|
||||
int level, /* level number (top == 0) of this block */
|
||||
FILE *f)
|
||||
{
|
||||
int i;
|
||||
union tree *t;
|
||||
union tree *fillt = &cm->tree[level+1];
|
||||
|
||||
assert(level < NBYTS-1); /* this level has pointers */
|
||||
for (i=BYTTAB-1 ; i>=0 ; i--) {
|
||||
t = tree->tptr[i];
|
||||
if (t == NULL) {
|
||||
fprintf(f, "NULL found in filled tree!\n");
|
||||
} else if (t == fillt) {
|
||||
/* empty body */
|
||||
} else if (level < NBYTS-2) { /* more pointer blocks below */
|
||||
fillcheck(cm, t, level+1, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- dumpchr - print a chr
|
||||
* Kind of char-centric but works well enough for debug use.
|
||||
^ static void dumpchr(pchr, FILE *);
|
||||
*/
|
||||
static void
|
||||
dumpchr(
|
||||
pchr c,
|
||||
FILE *f)
|
||||
{
|
||||
if (c == '\\') {
|
||||
fprintf(f, "\\\\");
|
||||
} else if (c > ' ' && c <= '~') {
|
||||
putc((char) c, f);
|
||||
} else {
|
||||
fprintf(f, "\\u%04lx", (long) c);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
^ #endif
|
||||
*/
|
||||
#endif /* ifdef OB_REG_DEBUG */
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
146
deps/oblib/src/lib/regex/regex/regc_cvec.cpp
vendored
146
deps/oblib/src/lib/regex/regex/regc_cvec.cpp
vendored
@ -1,146 +0,0 @@
|
||||
/*
|
||||
* Utility functions for handling cvecs
|
||||
* This file is #included by regcomp.c.
|
||||
*
|
||||
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
*
|
||||
* Development of this software was funded, in part, by Cray Research Inc.,
|
||||
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
* Corporation, none of whom are responsible for the results. The author
|
||||
* thanks all of them.
|
||||
*
|
||||
* Redistribution and use in source and binary forms -- with or without
|
||||
* modification -- are permitted for any purpose, provided that
|
||||
* redistributions in source form retain this entire copyright notice and
|
||||
* indicate the origin and nature of any modifications.
|
||||
*
|
||||
* I'd appreciate being given credit for this package in the documentation of
|
||||
* software which uses it, but that is not a requirement.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Notes:
|
||||
* Only (selected) functions in _this_ file should treat chr* as non-constant.
|
||||
*/
|
||||
|
||||
/*
|
||||
- newcvec - allocate a new cvec
|
||||
^ static struct cvec *newcvec(int, int);
|
||||
*/
|
||||
static struct cvec *
|
||||
newcvec(
|
||||
int nchrs, /* to hold this many chrs... */
|
||||
int nranges) /* ... and this many ranges... */
|
||||
{
|
||||
size_t nc = (size_t)nchrs + (size_t)nranges*2;
|
||||
size_t n = sizeof(struct cvec) + nc*sizeof(chr);
|
||||
struct cvec *cv = (struct cvec *) MALLOC(n);
|
||||
|
||||
if (cv == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
cv->chrspace = nchrs;
|
||||
cv->chrs = (chr *)(((char *)cv)+sizeof(struct cvec));
|
||||
cv->ranges = cv->chrs + nchrs;
|
||||
cv->rangespace = nranges;
|
||||
return clearcvec(cv);
|
||||
}
|
||||
|
||||
/*
|
||||
- clearcvec - clear a possibly-new cvec
|
||||
* Returns pointer as convenience.
|
||||
^ static struct cvec *clearcvec(struct cvec *);
|
||||
*/
|
||||
static struct cvec *
|
||||
clearcvec(
|
||||
struct cvec *cv) /* character vector */
|
||||
{
|
||||
assert(cv != NULL);
|
||||
cv->nchrs = 0;
|
||||
cv->nranges = 0;
|
||||
return cv;
|
||||
}
|
||||
|
||||
/*
|
||||
- addchr - add a chr to a cvec
|
||||
^ static void addchr(struct cvec *, pchr);
|
||||
*/
|
||||
static void
|
||||
addchr(
|
||||
struct cvec *cv, /* character vector */
|
||||
pchr c) /* character to add */
|
||||
{
|
||||
cv->chrs[cv->nchrs++] = (chr)c;
|
||||
}
|
||||
|
||||
/*
|
||||
- addrange - add a range to a cvec
|
||||
^ static void addrange(struct cvec *, pchr, pchr);
|
||||
*/
|
||||
static void
|
||||
addrange(
|
||||
struct cvec *cv, /* character vector */
|
||||
pchr from, /* first character of range */
|
||||
pchr to) /* last character of range */
|
||||
{
|
||||
assert(cv->nranges < cv->rangespace);
|
||||
cv->ranges[cv->nranges*2] = (chr)from;
|
||||
cv->ranges[cv->nranges*2 + 1] = (chr)to;
|
||||
cv->nranges++;
|
||||
}
|
||||
|
||||
/*
|
||||
- getcvec - get a cvec, remembering it as v->cv
|
||||
^ static struct cvec *getcvec(struct vars *, int, int);
|
||||
*/
|
||||
static struct cvec *
|
||||
getcvec(
|
||||
struct vars *v, /* context */
|
||||
int nchrs, /* to hold this many chrs... */
|
||||
int nranges) /* ... and this many ranges... */
|
||||
{
|
||||
if ((v->cv != NULL) && (nchrs <= v->cv->chrspace) &&
|
||||
(nranges <= v->cv->rangespace)) {
|
||||
return clearcvec(v->cv);
|
||||
}
|
||||
|
||||
if (v->cv != NULL) {
|
||||
freecvec(v->cv);
|
||||
}
|
||||
v->cv = newcvec(nchrs, nranges);
|
||||
if (v->cv == NULL) {
|
||||
ERR(OB_REG_ESPACE);
|
||||
}
|
||||
|
||||
return v->cv;
|
||||
}
|
||||
|
||||
/*
|
||||
- freecvec - free a cvec
|
||||
^ static void freecvec(struct cvec *);
|
||||
*/
|
||||
static void
|
||||
freecvec(
|
||||
struct cvec *cv) /* character vector */
|
||||
{
|
||||
FREE(cv);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
1185
deps/oblib/src/lib/regex/regex/regc_lex.cpp
vendored
1185
deps/oblib/src/lib/regex/regex/regc_lex.cpp
vendored
File diff suppressed because it is too large
Load Diff
1146
deps/oblib/src/lib/regex/regex/regc_locale.cpp
vendored
1146
deps/oblib/src/lib/regex/regex/regc_locale.cpp
vendored
File diff suppressed because it is too large
Load Diff
1877
deps/oblib/src/lib/regex/regex/regc_nfa.cpp
vendored
1877
deps/oblib/src/lib/regex/regex/regc_nfa.cpp
vendored
File diff suppressed because it is too large
Load Diff
2182
deps/oblib/src/lib/regex/regex/regcomp.cpp
vendored
2182
deps/oblib/src/lib/regex/regex/regcomp.cpp
vendored
File diff suppressed because it is too large
Load Diff
185
deps/oblib/src/lib/regex/regex/regcustom.h
vendored
185
deps/oblib/src/lib/regex/regex/regcustom.h
vendored
@ -1,185 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
*
|
||||
* Development of this software was funded, in part, by Cray Research Inc.,
|
||||
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
* Corporation, none of whom are responsible for the results. The author
|
||||
* thanks all of them.
|
||||
*
|
||||
* Redistribution and use in source and binary forms - with or without
|
||||
* modification - are permitted for any purpose, provided that redistributions
|
||||
* in source form retain this entire copyright notice and indicate the origin
|
||||
* and nature of any modifications.
|
||||
*
|
||||
* I'd appreciate being given credit for this package in the documentation of
|
||||
* software which uses it, but that is not a requirement.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Headers if any.
|
||||
*/
|
||||
|
||||
#ifdef REGEX_STANDALONE
|
||||
# include "regalone.h"
|
||||
//#else
|
||||
//# include "obInt.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Overrides for regguts.h definitions, if any.
|
||||
*/
|
||||
|
||||
#define FUNCPTR(name, args) (*name)args
|
||||
#ifndef REGEX_STANDALONE
|
||||
#define MALLOC(n) ckalloc(n)
|
||||
#define FREE(p) ckfree(VS(p))
|
||||
#define REALLOC(p,n) ckrealloc(VS(p),n)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Do not insert extras between the "begin" and "end" lines - this chunk is
|
||||
* automatically extracted to be fitted into regex.h.
|
||||
*/
|
||||
|
||||
/* --- begin --- */
|
||||
/* Ensure certain things don't sneak in from system headers. */
|
||||
#ifdef __REG_WIDE_T
|
||||
#undef __REG_WIDE_T
|
||||
#endif
|
||||
#ifdef __REG_WIDE_COMPILE
|
||||
#undef __REG_WIDE_COMPILE
|
||||
#endif
|
||||
#ifdef __REG_WIDE_EXEC
|
||||
#undef __REG_WIDE_EXEC
|
||||
#endif
|
||||
#ifdef __REG_REGOFF_T
|
||||
#undef __REG_REGOFF_T
|
||||
#endif
|
||||
#ifdef __REG_VOID_T
|
||||
#undef __REG_VOID_T
|
||||
#endif
|
||||
#ifdef __REG_CONST
|
||||
#undef __REG_CONST
|
||||
#endif
|
||||
#ifdef __REG_NOFRONT
|
||||
#undef __REG_NOFRONT
|
||||
#endif
|
||||
#ifdef __REG_NOCHAR
|
||||
#undef __REG_NOCHAR
|
||||
#endif
|
||||
/* Interface types */
|
||||
#define __REG_WIDE_T Ob_UniChar
|
||||
#define __REG_REGOFF_T long /* Not really right, but good enough... */
|
||||
#define __REG_VOID_T void
|
||||
#define __REG_CONST const
|
||||
/* Names and declarations */
|
||||
#define __REG_WIDE_COMPILE ObReComp
|
||||
#define __REG_WIDE_EXEC ObReExec
|
||||
#define __REG_NOFRONT /* Don't want ob_regcomp() and ob_regexec() */
|
||||
#define __REG_NOCHAR /* Or the char versions */
|
||||
#define ob_regfree ObReFree
|
||||
#define ob_regerror ObReError
|
||||
/* --- end --- */
|
||||
|
||||
/*
|
||||
* Internal character type and related.
|
||||
*/
|
||||
|
||||
#ifndef REGEX_STANDALONE
|
||||
typedef Ob_UniChar chr; /* The type itself. */
|
||||
#endif
|
||||
typedef int pchr; /* What it promotes to. */
|
||||
typedef unsigned uchr; /* Unsigned type that will hold a chr. */
|
||||
typedef int celt; /* Type to hold chr, or NOCELT */
|
||||
#define NOCELT (-1) /* Celt value which is not valid chr */
|
||||
#define CHR(c) (UCHAR(c)) /* Turn char literal into chr literal */
|
||||
#define DIGITVAL(c) ((c)-'0') /* Turn chr digit into its value */
|
||||
#if OB_UTF_MAX > 3
|
||||
#define CHRBITS 32 /* Bits in a chr; must not use sizeof */
|
||||
#define CHR_MIN 0x00000000 /* Smallest and largest chr; the value */
|
||||
#define CHR_MAX 0xffffffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */
|
||||
#elif defined(REGEX_STANDALONE) && ! defined(REGEX_WCHAR)
|
||||
# define CHRBITS 8
|
||||
# define CHR_MIN 0x00
|
||||
# define CHR_MAX 0xff
|
||||
#else
|
||||
#define CHRBITS 16 /* Bits in a chr; must not use sizeof */
|
||||
#define CHR_MIN 0x0000 /* Smallest and largest chr; the value */
|
||||
#define CHR_MAX 0xffff /* CHR_MAX-CHR_MIN+1 should fit in uchr */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Functions operating on chr.
|
||||
*/
|
||||
|
||||
#define iscalnum(x) Ob_UniCharIsAlnum(x)
|
||||
#define iscalpha(x) Ob_UniCharIsAlpha(x)
|
||||
#define iscdigit(x) Ob_UniCharIsDigit(x)
|
||||
#define iscspace(x) Ob_UniCharIsSpace(x)
|
||||
|
||||
/*
|
||||
* Name the external functions.
|
||||
*/
|
||||
|
||||
#ifdef REGEX_STANDALONE
|
||||
# ifdef REGEX_WCHAR
|
||||
# define compile ob_re_wcomp
|
||||
# define exec ob_re_wexec
|
||||
# define __REG_NOCHAR
|
||||
# else
|
||||
# define compile ob_re_comp
|
||||
# define exec ob_re_exec
|
||||
# undef __REG_NOCHAR
|
||||
# endif
|
||||
#else
|
||||
#define compile ObReComp
|
||||
#define exec ObReExec
|
||||
#endif
|
||||
|
||||
/*
|
||||
& Enable/disable debugging code (by whether OB_REG_DEBUG is defined or not).
|
||||
*/
|
||||
|
||||
#if 0 /* No debug unless requested by makefile. */
|
||||
#define OB_REG_DEBUG /* */
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef REGEX_STANDALONE
|
||||
/*
|
||||
* Method of allocating a local workspace. We used a thread-specific data
|
||||
* space to store this because the regular expression engine is never
|
||||
* reentered from the same thread; it doesn't make any callbacks.
|
||||
*/
|
||||
#define AllocVars(vPtr) \
|
||||
static Ob_ThreadDataKey varsKey; \
|
||||
register struct vars *vPtr = (struct vars *) \
|
||||
Ob_GetThreadData(&varsKey, sizeof(struct vars))
|
||||
#elif 0
|
||||
/*
|
||||
* This strategy for allocating workspace is "more proper" in some sense, but
|
||||
* quite a bit slower. Using TSD (as above) leads to code that is quite a bit
|
||||
* faster in practice (measured!)
|
||||
*/
|
||||
#define AllocVars(vPtr) \
|
||||
register struct vars *vPtr = (struct vars *) MALLOC(sizeof(struct vars))
|
||||
#define FreeVars(vPtr) \
|
||||
FREE(vPtr)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* And pick up the standard header.
|
||||
*/
|
||||
|
||||
#include "ob_regex.h"
|
818
deps/oblib/src/lib/regex/regex/rege_dfa.cpp
vendored
818
deps/oblib/src/lib/regex/regex/rege_dfa.cpp
vendored
@ -1,818 +0,0 @@
|
||||
/*
|
||||
* DFA routines
|
||||
* This file is #included by regexec.c.
|
||||
*
|
||||
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
*
|
||||
* Development of this software was funded, in part, by Cray Research Inc.,
|
||||
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
* Corporation, none of whom are responsible for the results. The author
|
||||
* thanks all of them.
|
||||
*
|
||||
* Redistribution and use in source and binary forms -- with or without
|
||||
* modification -- are permitted for any purpose, provided that
|
||||
* redistributions in source form retain this entire copyright notice and
|
||||
* indicate the origin and nature of any modifications.
|
||||
*
|
||||
* I'd appreciate being given credit for this package in the documentation
|
||||
* of software which uses it, but that is not a requirement.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
- longest - longest-preferred matching engine
|
||||
^ static chr *longest(struct vars *, struct dfa *, chr *, chr *, int *);
|
||||
*/
|
||||
static chr * /* endpoint, or NULL */
|
||||
longest(
|
||||
struct vars *v, /* used only for debug and exec flags */
|
||||
struct dfa *d,
|
||||
chr *start, /* where the match should start */
|
||||
chr *stop, /* match must end at or before here */
|
||||
int *hitstopp) /* record whether hit v->stop, if non-NULL */
|
||||
{
|
||||
chr *cp;
|
||||
chr *realstop = (stop == v->stop) ? stop : stop + 1;
|
||||
color co;
|
||||
struct sset *css;
|
||||
struct sset *ss;
|
||||
chr *post;
|
||||
int i;
|
||||
struct colormap *cm = d->cm;
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
*/
|
||||
|
||||
css = initialize(v, d, start);
|
||||
cp = start;
|
||||
if (hitstopp != NULL) {
|
||||
*hitstopp = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup.
|
||||
*/
|
||||
|
||||
FDEBUG(("+++ startup +++\n"));
|
||||
if (cp == v->start) {
|
||||
co = d->cnfa->bos[(v->eflags&OB_REG_NOTBOL) ? 0 : 1];
|
||||
FDEBUG(("color %ld\n", (long)co));
|
||||
} else {
|
||||
co = GETCOLOR(cm, *(cp - 1));
|
||||
FDEBUG(("char %c, color %ld\n", (char)*(cp-1), (long)co));
|
||||
}
|
||||
css = miss(v, d, css, co, cp, start);
|
||||
if (css == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
css->lastseen = cp;
|
||||
|
||||
/*
|
||||
* Main loop.
|
||||
*/
|
||||
|
||||
if (v->eflags&OB_REG_FTRACE) {
|
||||
while (cp < realstop) {
|
||||
FDEBUG(("+++ at c%d +++\n", css - d->ssets));
|
||||
co = GETCOLOR(cm, *cp);
|
||||
FDEBUG(("char %c, color %ld\n", (char)*cp, (long)co));
|
||||
ss = css->outs[co];
|
||||
if (ss == NULL) {
|
||||
ss = miss(v, d, css, co, cp+1, start);
|
||||
if (ss == NULL) {
|
||||
break; /* NOTE BREAK OUT */
|
||||
}
|
||||
}
|
||||
cp++;
|
||||
ss->lastseen = cp;
|
||||
css = ss;
|
||||
}
|
||||
} else {
|
||||
while (cp < realstop) {
|
||||
co = GETCOLOR(cm, *cp);
|
||||
ss = css->outs[co];
|
||||
if (ss == NULL) {
|
||||
ss = miss(v, d, css, co, cp+1, start);
|
||||
if (ss == NULL) {
|
||||
break; /* NOTE BREAK OUT */
|
||||
}
|
||||
}
|
||||
cp++;
|
||||
ss->lastseen = cp;
|
||||
css = ss;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown.
|
||||
*/
|
||||
|
||||
FDEBUG(("+++ shutdown at c%d +++\n", css - d->ssets));
|
||||
if (cp == v->stop && stop == v->stop) {
|
||||
if (hitstopp != NULL) {
|
||||
*hitstopp = 1;
|
||||
}
|
||||
co = d->cnfa->eos[(v->eflags&OB_REG_NOTEOL) ? 0 : 1];
|
||||
FDEBUG(("color %ld\n", (long)co));
|
||||
ss = miss(v, d, css, co, cp, start);
|
||||
|
||||
/*
|
||||
* Special case: match ended at eol?
|
||||
*/
|
||||
|
||||
if (ss != NULL && (ss->flags&POSTSTATE)) {
|
||||
return cp;
|
||||
} else if (ss != NULL) {
|
||||
ss->lastseen = cp; /* to be tidy */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Find last match, if any.
|
||||
*/
|
||||
|
||||
post = d->lastpost;
|
||||
for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) {
|
||||
if ((ss->flags&POSTSTATE) && (post != ss->lastseen) &&
|
||||
(post == NULL || post < ss->lastseen)) {
|
||||
post = ss->lastseen;
|
||||
}
|
||||
}
|
||||
if (post != NULL) { /* found one */
|
||||
return post - 1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
- shortest - shortest-preferred matching engine
|
||||
^ static chr *shortest(struct vars *, struct dfa *, chr *, chr *, chr *,
|
||||
^ chr **, int *);
|
||||
*/
|
||||
static chr * /* endpoint, or NULL */
|
||||
shortest(
|
||||
struct vars *v,
|
||||
struct dfa *d,
|
||||
chr *start, /* where the match should start */
|
||||
chr *min, /* match must end at or after here */
|
||||
chr *max, /* match must end at or before here */
|
||||
chr **coldp, /* store coldstart pointer here, if nonNULL */
|
||||
int *hitstopp) /* record whether hit v->stop, if non-NULL */
|
||||
{
|
||||
chr *cp;
|
||||
chr *realmin = (min == v->stop) ? min : min + 1;
|
||||
chr *realmax = (max == v->stop) ? max : max + 1;
|
||||
color co;
|
||||
struct sset *css;
|
||||
struct sset *ss;
|
||||
struct colormap *cm = d->cm;
|
||||
|
||||
/*
|
||||
* Initialize.
|
||||
*/
|
||||
|
||||
css = initialize(v, d, start);
|
||||
cp = start;
|
||||
if (hitstopp != NULL) {
|
||||
*hitstopp = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Startup.
|
||||
*/
|
||||
|
||||
FDEBUG(("--- startup ---\n"));
|
||||
if (cp == v->start) {
|
||||
co = d->cnfa->bos[(v->eflags&OB_REG_NOTBOL) ? 0 : 1];
|
||||
FDEBUG(("color %ld\n", (long)co));
|
||||
} else {
|
||||
co = GETCOLOR(cm, *(cp - 1));
|
||||
FDEBUG(("char %c, color %ld\n", (char)*(cp-1), (long)co));
|
||||
}
|
||||
css = miss(v, d, css, co, cp, start);
|
||||
if (css == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
css->lastseen = cp;
|
||||
ss = css;
|
||||
|
||||
/*
|
||||
* Main loop.
|
||||
*/
|
||||
|
||||
if (v->eflags&OB_REG_FTRACE) {
|
||||
while (cp < realmax) {
|
||||
FDEBUG(("--- at c%d ---\n", css - d->ssets));
|
||||
co = GETCOLOR(cm, *cp);
|
||||
FDEBUG(("char %c, color %ld\n", (char)*cp, (long)co));
|
||||
ss = css->outs[co];
|
||||
if (ss == NULL) {
|
||||
ss = miss(v, d, css, co, cp+1, start);
|
||||
if (ss == NULL) {
|
||||
break; /* NOTE BREAK OUT */
|
||||
}
|
||||
}
|
||||
cp++;
|
||||
ss->lastseen = cp;
|
||||
css = ss;
|
||||
if ((ss->flags&POSTSTATE) && cp >= realmin) {
|
||||
break; /* NOTE BREAK OUT */
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (cp < realmax) {
|
||||
co = GETCOLOR(cm, *cp);
|
||||
ss = css->outs[co];
|
||||
if (ss == NULL) {
|
||||
ss = miss(v, d, css, co, cp+1, start);
|
||||
if (ss == NULL) {
|
||||
break; /* NOTE BREAK OUT */
|
||||
}
|
||||
}
|
||||
cp++;
|
||||
ss->lastseen = cp;
|
||||
css = ss;
|
||||
if ((ss->flags&POSTSTATE) && cp >= realmin) {
|
||||
break; /* NOTE BREAK OUT */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ss == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (coldp != NULL) { /* report last no-progress state set, if any */
|
||||
*coldp = lastcold(v, d);
|
||||
}
|
||||
|
||||
if ((ss->flags&POSTSTATE) && cp > min) {
|
||||
assert(cp >= realmin);
|
||||
cp--;
|
||||
} else if (cp == v->stop && max == v->stop) {
|
||||
co = d->cnfa->eos[(v->eflags&OB_REG_NOTEOL) ? 0 : 1];
|
||||
FDEBUG(("color %ld\n", (long)co));
|
||||
ss = miss(v, d, css, co, cp, start);
|
||||
|
||||
/*
|
||||
* Match might have ended at eol.
|
||||
*/
|
||||
|
||||
if ((ss == NULL || !(ss->flags&POSTSTATE)) && hitstopp != NULL) {
|
||||
*hitstopp = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (ss == NULL || !(ss->flags&POSTSTATE)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return cp;
|
||||
}
|
||||
|
||||
/*
|
||||
- lastcold - determine last point at which no progress had been made
|
||||
^ static chr *lastcold(struct vars *, struct dfa *);
|
||||
*/
|
||||
static chr * /* endpoint, or NULL */
|
||||
lastcold(
|
||||
struct vars *v,
|
||||
struct dfa *d)
|
||||
{
|
||||
struct sset *ss;
|
||||
chr *nopr;
|
||||
int i;
|
||||
|
||||
nopr = d->lastnopr;
|
||||
if (nopr == NULL) {
|
||||
nopr = v->start;
|
||||
}
|
||||
for (ss = d->ssets, i = d->nssused; i > 0; ss++, i--) {
|
||||
if ((ss->flags&NOPROGRESS) && nopr < ss->lastseen) {
|
||||
nopr = ss->lastseen;
|
||||
}
|
||||
}
|
||||
return nopr;
|
||||
}
|
||||
|
||||
/*
|
||||
- newdfa - set up a fresh DFA
|
||||
^ static struct dfa *newdfa(struct vars *, struct cnfa *,
|
||||
^ struct colormap *, struct smalldfa *);
|
||||
*/
|
||||
static struct dfa *
|
||||
newdfa(
|
||||
struct vars *v,
|
||||
struct cnfa *cnfa,
|
||||
struct colormap *cm,
|
||||
struct smalldfa *small) /* preallocated space, may be NULL */
|
||||
{
|
||||
struct dfa *d = NULL;
|
||||
size_t nss = cnfa->nstates * 2;
|
||||
int wordsper = (cnfa->nstates + UBITS - 1) / UBITS;
|
||||
struct smalldfa *smallwas = small;
|
||||
|
||||
assert(cnfa != NULL && cnfa->nstates != 0);
|
||||
|
||||
if (nss <= FEWSTATES && cnfa->ncolors <= FEWCOLORS) {
|
||||
assert(wordsper == 1);
|
||||
if (small == NULL) {
|
||||
small = (struct smalldfa *) MALLOC(sizeof(struct smalldfa));
|
||||
if (small == NULL) {
|
||||
ERR(OB_REG_ESPACE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
d = &small->dfa;
|
||||
d->ssets = small->ssets;
|
||||
d->statesarea = small->statesarea;
|
||||
d->work = &d->statesarea[nss];
|
||||
d->outsarea = small->outsarea;
|
||||
d->incarea = small->incarea;
|
||||
d->cptsmalloced = 0;
|
||||
d->mallocarea = (smallwas == NULL) ? (char *)small : NULL;
|
||||
} else {
|
||||
d = (struct dfa *)MALLOC(sizeof(struct dfa));
|
||||
if (d == NULL) {
|
||||
ERR(OB_REG_ESPACE);
|
||||
return NULL;
|
||||
}
|
||||
d->ssets = (struct sset *)MALLOC(nss * sizeof(struct sset));
|
||||
d->statesarea = (unsigned *)
|
||||
MALLOC((nss+WORK) * wordsper * sizeof(unsigned));
|
||||
d->work = &d->statesarea[nss * wordsper];
|
||||
d->outsarea = (struct sset **)
|
||||
MALLOC(nss * cnfa->ncolors * sizeof(struct sset *));
|
||||
d->incarea = (struct arcp *)
|
||||
MALLOC(nss * cnfa->ncolors * sizeof(struct arcp));
|
||||
d->cptsmalloced = 1;
|
||||
d->mallocarea = (char *)d;
|
||||
if (d->ssets == NULL || d->statesarea == NULL ||
|
||||
d->outsarea == NULL || d->incarea == NULL) {
|
||||
freedfa(d);
|
||||
ERR(OB_REG_ESPACE);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
d->nssets = (v->eflags&OB_REG_SMALL) ? 7 : nss;
|
||||
d->nssused = 0;
|
||||
d->nstates = cnfa->nstates;
|
||||
d->ncolors = cnfa->ncolors;
|
||||
d->wordsper = wordsper;
|
||||
d->cnfa = cnfa;
|
||||
d->cm = cm;
|
||||
d->lastpost = NULL;
|
||||
d->lastnopr = NULL;
|
||||
d->search = d->ssets;
|
||||
|
||||
/*
|
||||
* Initialization of sset fields is done as needed.
|
||||
*/
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
/*
|
||||
- freedfa - free a DFA
|
||||
^ static void freedfa(struct dfa *);
|
||||
*/
|
||||
static void
|
||||
freedfa(
|
||||
struct dfa *d)
|
||||
{
|
||||
if (d != NULL) {
|
||||
if (d->cptsmalloced) {
|
||||
if (d->ssets != NULL) {
|
||||
FREE(d->ssets);
|
||||
}
|
||||
if (d->statesarea != NULL) {
|
||||
FREE(d->statesarea);
|
||||
}
|
||||
if (d->outsarea != NULL) {
|
||||
FREE(d->outsarea);
|
||||
}
|
||||
if (d->incarea != NULL) {
|
||||
FREE(d->incarea);
|
||||
}
|
||||
}
|
||||
|
||||
if (d->mallocarea != NULL) {
|
||||
FREE(d->mallocarea);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
- hash - construct a hash code for a bitvector
|
||||
* There are probably better ways, but they're more expensive.
|
||||
^ static unsigned hash(unsigned *, int);
|
||||
*/
|
||||
static unsigned
|
||||
hash(
|
||||
unsigned *uv,
|
||||
int n)
|
||||
{
|
||||
int i;
|
||||
unsigned h;
|
||||
|
||||
h = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
h ^= uv[i];
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/*
|
||||
- initialize - hand-craft a cache entry for startup, otherwise get ready
|
||||
^ static struct sset *initialize(struct vars *, struct dfa *, chr *);
|
||||
*/
|
||||
static struct sset *
|
||||
initialize(
|
||||
struct vars *v, /* used only for debug flags */
|
||||
struct dfa *d,
|
||||
chr *start)
|
||||
{
|
||||
struct sset *ss;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Is previous one still there?
|
||||
*/
|
||||
|
||||
if (d->nssused > 0 && (d->ssets[0].flags&STARTER)) {
|
||||
ss = &d->ssets[0];
|
||||
} else { /* no, must (re)build it */
|
||||
ss = getvacant(v, d, start, start);
|
||||
for (i = 0; i < d->wordsper; i++) {
|
||||
ss->states[i] = 0;
|
||||
}
|
||||
BSET(ss->states, d->cnfa->pre);
|
||||
ss->hash = HASH(ss->states, d->wordsper);
|
||||
assert(d->cnfa->pre != d->cnfa->post);
|
||||
ss->flags = STARTER|LOCKED|NOPROGRESS;
|
||||
|
||||
/*
|
||||
* lastseen dealt with below
|
||||
*/
|
||||
}
|
||||
|
||||
for (i = 0; i < d->nssused; i++) {
|
||||
d->ssets[i].lastseen = NULL;
|
||||
}
|
||||
ss->lastseen = start; /* maybe untrue, but harmless */
|
||||
d->lastpost = NULL;
|
||||
d->lastnopr = NULL;
|
||||
return ss;
|
||||
}
|
||||
|
||||
/*
|
||||
- miss - handle a cache miss
|
||||
^ static struct sset *miss(struct vars *, struct dfa *, struct sset *,
|
||||
^ pcolor, chr *, chr *);
|
||||
*/
|
||||
static struct sset * /* NULL if goes to empty set */
|
||||
miss(
|
||||
struct vars *v, /* used only for debug flags */
|
||||
struct dfa *d,
|
||||
struct sset *css,
|
||||
pcolor co,
|
||||
chr *cp, /* next chr */
|
||||
chr *start) /* where the attempt got started */
|
||||
{
|
||||
struct cnfa *cnfa = d->cnfa;
|
||||
int i;
|
||||
unsigned h;
|
||||
struct carc *ca;
|
||||
struct sset *p;
|
||||
int ispost;
|
||||
int noprogress;
|
||||
int gotstate;
|
||||
int dolacons;
|
||||
int sawlacons;
|
||||
|
||||
/*
|
||||
* For convenience, we can be called even if it might not be a miss.
|
||||
*/
|
||||
|
||||
if (css->outs[co] != NULL) {
|
||||
FDEBUG(("hit\n"));
|
||||
return css->outs[co];
|
||||
}
|
||||
FDEBUG(("miss\n"));
|
||||
|
||||
/*
|
||||
* First, what set of states would we end up in?
|
||||
*/
|
||||
|
||||
for (i = 0; i < d->wordsper; i++) {
|
||||
d->work[i] = 0;
|
||||
}
|
||||
ispost = 0;
|
||||
noprogress = 1;
|
||||
gotstate = 0;
|
||||
for (i = 0; i < d->nstates; i++) {
|
||||
if (ISBSET(css->states, i)) {
|
||||
for (ca = cnfa->states[i]+1; ca->co != COLORLESS; ca++) {
|
||||
if (ca->co == co) {
|
||||
BSET(d->work, ca->to);
|
||||
gotstate = 1;
|
||||
if (ca->to == cnfa->post) {
|
||||
ispost = 1;
|
||||
}
|
||||
if (!cnfa->states[ca->to]->co) {
|
||||
noprogress = 0;
|
||||
}
|
||||
FDEBUG(("%d -> %d\n", i, ca->to));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dolacons = (gotstate) ? (cnfa->flags&HASLACONS) : 0;
|
||||
sawlacons = 0;
|
||||
while (dolacons) { /* transitive closure */
|
||||
dolacons = 0;
|
||||
for (i = 0; i < d->nstates; i++) {
|
||||
if (ISBSET(d->work, i)) {
|
||||
for (ca = cnfa->states[i]+1; ca->co != COLORLESS; ca++) {
|
||||
if (ca->co <= cnfa->ncolors) {
|
||||
continue; /* NOTE CONTINUE */
|
||||
}
|
||||
sawlacons = 1;
|
||||
if (ISBSET(d->work, ca->to)) {
|
||||
continue; /* NOTE CONTINUE */
|
||||
}
|
||||
if (!lacon(v, cnfa, cp, ca->co)) {
|
||||
continue; /* NOTE CONTINUE */
|
||||
}
|
||||
BSET(d->work, ca->to);
|
||||
dolacons = 1;
|
||||
if (ca->to == cnfa->post) {
|
||||
ispost = 1;
|
||||
}
|
||||
if (!cnfa->states[ca->to]->co) {
|
||||
noprogress = 0;
|
||||
}
|
||||
FDEBUG(("%d :> %d\n", i, ca->to));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!gotstate) {
|
||||
return NULL;
|
||||
}
|
||||
h = HASH(d->work, d->wordsper);
|
||||
|
||||
/*
|
||||
* Next, is that in the cache?
|
||||
*/
|
||||
|
||||
for (p = d->ssets, i = d->nssused; i > 0; p++, i--) {
|
||||
if (HIT(h, d->work, p, d->wordsper)) {
|
||||
FDEBUG(("cached c%d\n", p - d->ssets));
|
||||
break; /* NOTE BREAK OUT */
|
||||
}
|
||||
}
|
||||
if (i == 0) { /* nope, need a new cache entry */
|
||||
p = getvacant(v, d, cp, start);
|
||||
assert(p != css);
|
||||
for (i = 0; i < d->wordsper; i++) {
|
||||
p->states[i] = d->work[i];
|
||||
}
|
||||
p->hash = h;
|
||||
p->flags = (ispost) ? POSTSTATE : 0;
|
||||
if (noprogress) {
|
||||
p->flags |= NOPROGRESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* lastseen to be dealt with by caller
|
||||
*/
|
||||
}
|
||||
|
||||
if (!sawlacons) { /* lookahead conds. always cache miss */
|
||||
FDEBUG(("c%d[%d]->c%d\n", css - d->ssets, co, p - d->ssets));
|
||||
css->outs[co] = p;
|
||||
css->inchain[co] = p->ins;
|
||||
p->ins.ss = css;
|
||||
p->ins.co = (color)co;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
- lacon - lookahead-constraint checker for miss()
|
||||
^ static int lacon(struct vars *, struct cnfa *, chr *, pcolor);
|
||||
*/
|
||||
static int /* predicate: constraint satisfied? */
|
||||
lacon(
|
||||
struct vars *v,
|
||||
struct cnfa *pcnfa, /* parent cnfa */
|
||||
chr *cp,
|
||||
pcolor co) /* "color" of the lookahead constraint */
|
||||
{
|
||||
int n;
|
||||
struct subre *sub;
|
||||
struct dfa *d;
|
||||
struct smalldfa sd;
|
||||
chr *end;
|
||||
|
||||
n = co - pcnfa->ncolors;
|
||||
assert(n < v->g->nlacons && v->g->lacons != NULL);
|
||||
FDEBUG(("=== testing lacon %d\n", n));
|
||||
sub = &v->g->lacons[n];
|
||||
d = newdfa(v, &sub->cnfa, &v->g->cmap, &sd);
|
||||
if (d == NULL) {
|
||||
ERR(OB_REG_ESPACE);
|
||||
return 0;
|
||||
}
|
||||
end = longest(v, d, cp, v->stop, (int *)NULL);
|
||||
freedfa(d);
|
||||
FDEBUG(("=== lacon %d match %d\n", n, (end != NULL)));
|
||||
return (sub->subno) ? (end != NULL) : (end == NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
- getvacant - get a vacant state set
|
||||
* This routine clears out the inarcs and outarcs, but does not otherwise
|
||||
* clear the innards of the state set -- that's up to the caller.
|
||||
^ static struct sset *getvacant(struct vars *, struct dfa *, chr *, chr *);
|
||||
*/
|
||||
static struct sset *
|
||||
getvacant(
|
||||
struct vars *v, /* used only for debug flags */
|
||||
struct dfa *d,
|
||||
chr *cp,
|
||||
chr *start)
|
||||
{
|
||||
int i;
|
||||
struct sset *ss;
|
||||
struct sset *p;
|
||||
struct arcp ap;
|
||||
struct arcp lastap = {NULL, 0}; /* silence gcc 4 warning */
|
||||
color co;
|
||||
|
||||
ss = pickss(v, d, cp, start);
|
||||
assert(!(ss->flags&LOCKED));
|
||||
|
||||
/*
|
||||
* Clear out its inarcs, including self-referential ones.
|
||||
*/
|
||||
|
||||
ap = ss->ins;
|
||||
while ((p = ap.ss) != NULL) {
|
||||
co = ap.co;
|
||||
FDEBUG(("zapping c%d's %ld outarc\n", p - d->ssets, (long)co));
|
||||
p->outs[co] = NULL;
|
||||
ap = p->inchain[co];
|
||||
p->inchain[co].ss = NULL; /* paranoia */
|
||||
}
|
||||
ss->ins.ss = NULL;
|
||||
|
||||
/*
|
||||
* Take it off the inarc chains of the ssets reached by its outarcs.
|
||||
*/
|
||||
|
||||
for (i = 0; i < d->ncolors; i++) {
|
||||
p = ss->outs[i];
|
||||
assert(p != ss); /* not self-referential */
|
||||
if (p == NULL) {
|
||||
continue; /* NOTE CONTINUE */
|
||||
}
|
||||
FDEBUG(("del outarc %d from c%d's in chn\n", i, p - d->ssets));
|
||||
if (p->ins.ss == ss && p->ins.co == i) {
|
||||
p->ins = ss->inchain[i];
|
||||
} else {
|
||||
assert(p->ins.ss != NULL);
|
||||
for (ap = p->ins; ap.ss != NULL &&
|
||||
!(ap.ss == ss && ap.co == i);
|
||||
ap = ap.ss->inchain[ap.co]) {
|
||||
lastap = ap;
|
||||
}
|
||||
assert(ap.ss != NULL);
|
||||
lastap.ss->inchain[lastap.co] = ss->inchain[i];
|
||||
}
|
||||
ss->outs[i] = NULL;
|
||||
ss->inchain[i].ss = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If ss was a success state, may need to remember location.
|
||||
*/
|
||||
|
||||
if ((ss->flags&POSTSTATE) && ss->lastseen != d->lastpost &&
|
||||
(d->lastpost == NULL || d->lastpost < ss->lastseen)) {
|
||||
d->lastpost = ss->lastseen;
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise for a no-progress state.
|
||||
*/
|
||||
|
||||
if ((ss->flags&NOPROGRESS) && ss->lastseen != d->lastnopr &&
|
||||
(d->lastnopr == NULL || d->lastnopr < ss->lastseen)) {
|
||||
d->lastnopr = ss->lastseen;
|
||||
}
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
/*
|
||||
- pickss - pick the next stateset to be used
|
||||
^ static struct sset *pickss(struct vars *, struct dfa *, chr *, chr *);
|
||||
*/
|
||||
static struct sset *
|
||||
pickss(
|
||||
struct vars *v, /* used only for debug flags */
|
||||
struct dfa *d,
|
||||
chr *cp,
|
||||
chr *start)
|
||||
{
|
||||
int i;
|
||||
struct sset *ss;
|
||||
struct sset *end;
|
||||
chr *ancient;
|
||||
|
||||
/*
|
||||
* Shortcut for cases where cache isn't full.
|
||||
*/
|
||||
|
||||
if (d->nssused < d->nssets) {
|
||||
i = d->nssused;
|
||||
d->nssused++;
|
||||
ss = &d->ssets[i];
|
||||
FDEBUG(("new c%d\n", i));
|
||||
|
||||
/*
|
||||
* Set up innards.
|
||||
*/
|
||||
|
||||
ss->states = &d->statesarea[i * d->wordsper];
|
||||
ss->flags = 0;
|
||||
ss->ins.ss = NULL;
|
||||
ss->ins.co = WHITE; /* give it some value */
|
||||
ss->outs = &d->outsarea[i * d->ncolors];
|
||||
ss->inchain = &d->incarea[i * d->ncolors];
|
||||
for (i = 0; i < d->ncolors; i++) {
|
||||
ss->outs[i] = NULL;
|
||||
ss->inchain[i].ss = NULL;
|
||||
}
|
||||
return ss;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for oldest, or old enough anyway.
|
||||
*/
|
||||
|
||||
if (cp - start > d->nssets*2/3) { /* oldest 33% are expendable */
|
||||
ancient = cp - d->nssets*2/3;
|
||||
} else {
|
||||
ancient = start;
|
||||
}
|
||||
for (ss = d->search, end = &d->ssets[d->nssets]; ss < end; ss++) {
|
||||
if ((ss->lastseen == NULL || ss->lastseen < ancient)
|
||||
&& !(ss->flags&LOCKED)) {
|
||||
d->search = ss + 1;
|
||||
FDEBUG(("replacing c%d\n", ss - d->ssets));
|
||||
return ss;
|
||||
}
|
||||
}
|
||||
for (ss = d->ssets, end = d->search; ss < end; ss++) {
|
||||
if ((ss->lastseen == NULL || ss->lastseen < ancient)
|
||||
&& !(ss->flags&LOCKED)) {
|
||||
d->search = ss + 1;
|
||||
FDEBUG(("replacing c%d\n", ss - d->ssets));
|
||||
return ss;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Nobody's old enough?!? -- something's really wrong.
|
||||
*/
|
||||
|
||||
FDEBUG(("can't find victim to replace!\n"));
|
||||
assert(NOTREACHED);
|
||||
ERR(OB_REG_ASSERT);
|
||||
return d->ssets;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
131
deps/oblib/src/lib/regex/regex/regerror.cpp
vendored
131
deps/oblib/src/lib/regex/regex/regerror.cpp
vendored
@ -1,131 +0,0 @@
|
||||
/*
|
||||
* ob_regerror - error-code expansion
|
||||
*
|
||||
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
*
|
||||
* Development of this software was funded, in part, by Cray Research Inc.,
|
||||
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
* Corporation, none of whom are responsible for the results. The author
|
||||
* thanks all of them.
|
||||
*
|
||||
* Redistribution and use in source and binary forms -- with or without
|
||||
* modification -- are permitted for any purpose, provided that
|
||||
* redistributions in source form retain this entire copyright notice and
|
||||
* indicate the origin and nature of any modifications.
|
||||
*
|
||||
* I'd appreciate being given credit for this package in the documentation of
|
||||
* software which uses it, but that is not a requirement.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "regguts.h"
|
||||
|
||||
/*
|
||||
* Unknown-error explanation.
|
||||
*/
|
||||
|
||||
static char unk[] = "*** unknown regex error code 0x%x ***";
|
||||
|
||||
/*
|
||||
* Struct to map among codes, code names, and explanations.
|
||||
*/
|
||||
|
||||
static struct rerr {
|
||||
int code;
|
||||
const char *name;
|
||||
const char *explain;
|
||||
} rerrs[] = {
|
||||
/* The actual table is built from regex.h */
|
||||
#include "regerrs.h"
|
||||
{ -1, "", "oops" }, /* explanation special-cased in code */
|
||||
};
|
||||
|
||||
/*
|
||||
- ob_regerror - the interface to error numbers
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
size_t /* Actual space needed (including NUL) */
|
||||
ob_regerror(
|
||||
int code, /* Error code, or REG_ATOI or REG_ITOA */
|
||||
const ob_regex_t *preg, /* Associated ob_regex_t (unused at present) */
|
||||
char *errbuf, /* Result buffer (unless errbuf_size==0) */
|
||||
size_t errbuf_size) /* Available space in errbuf, can be 0 */
|
||||
{
|
||||
struct rerr *r;
|
||||
const char *msg;
|
||||
char convbuf[sizeof(unk)+50]; /* 50 = plenty for int */
|
||||
size_t len;
|
||||
int icode;
|
||||
|
||||
if (preg != NULL) {}
|
||||
switch (code) {
|
||||
case OB_REG_ATOI: /* Convert name to number */
|
||||
for (r = rerrs; r->code >= 0; r++) {
|
||||
if (strcmp(r->name, errbuf) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sprintf(convbuf, "%d", r->code); /* -1 for unknown */
|
||||
msg = convbuf;
|
||||
break;
|
||||
case OB_REG_ITOA: /* Convert number to name */
|
||||
icode = atoi(errbuf); /* Not our problem if this fails */
|
||||
for (r = rerrs; r->code >= 0; r++) {
|
||||
if (r->code == icode) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r->code >= 0) {
|
||||
msg = r->name;
|
||||
} else { /* Unknown; tell him the number */
|
||||
sprintf(convbuf, "REG_%u", (unsigned)icode);
|
||||
msg = convbuf;
|
||||
}
|
||||
break;
|
||||
default: /* A real, normal error code */
|
||||
for (r = rerrs; r->code >= 0; r++) {
|
||||
if (r->code == code) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r->code >= 0) {
|
||||
msg = r->explain;
|
||||
} else { /* Unknown; say so */
|
||||
sprintf(convbuf, unk, code);
|
||||
msg = convbuf;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
len = strlen(msg) + 1; /* Space needed, including NUL */
|
||||
if (errbuf_size > 0) {
|
||||
if (errbuf_size > len) {
|
||||
strncpy(errbuf, msg, len);
|
||||
errbuf[len] = '\0';
|
||||
} else { /* Truncate to fit */
|
||||
strncpy(errbuf, msg, errbuf_size-1);
|
||||
errbuf[errbuf_size-1] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
19
deps/oblib/src/lib/regex/regex/regerrs.h
vendored
19
deps/oblib/src/lib/regex/regex/regerrs.h
vendored
@ -1,19 +0,0 @@
|
||||
{ OB_REG_OKAY, "OB_REG_OKAY", "no errors detected" },
|
||||
{ OB_REG_NOMATCH, "OB_REG_NOMATCH", "failed to match" },
|
||||
{ OB_REG_BADPAT, "OB_REG_BADPAT", "invalid regexp (reg version 0.8)" },
|
||||
{ OB_REG_ECOLLATE, "OB_REG_ECOLLATE", "invalid collating element" },
|
||||
{ OB_REG_ECTYPE, "OB_REG_ECTYPE", "invalid character class" },
|
||||
{ OB_REG_EESCAPE, "OB_REG_EESCAPE", "invalid escape \\ sequence" },
|
||||
{ OB_REG_ESUBREG, "OB_REG_ESUBREG", "invalid backreference number" },
|
||||
{ OB_REG_EBRACK, "OB_REG_EBRACK", "brackets [] not balanced" },
|
||||
{ OB_REG_EPAREN, "OB_REG_EPAREN", "parentheses () not balanced" },
|
||||
{ OB_REG_EBRACE, "OB_REG_EBRACE", "braces {} not balanced" },
|
||||
{ OB_REG_BADBR, "OB_REG_BADBR", "invalid repetition count(s)" },
|
||||
{ OB_REG_ERANGE, "OB_REG_ERANGE", "invalid character range" },
|
||||
{ OB_REG_ESPACE, "OB_REG_ESPACE", "out of memory" },
|
||||
{ OB_REG_BADRPT, "OB_REG_BADRPT", "quantifier operand invalid" },
|
||||
{ OB_REG_ASSERT, "OB_REG_ASSERT", "\"can't happen\" -- you found a bug" },
|
||||
{ OB_REG_INVARG, "OB_REG_INVARG", "invalid argument to regex function" },
|
||||
{ OB_REG_MIXED, "OB_REG_MIXED", "character widths of regex and string differ" },
|
||||
{ OB_REG_BADOPT, "OB_REG_BADOPT", "invalid embedded option" },
|
||||
{ OB_REG_ETOOBIG, "OB_REG_ETOOBIG", "nfa has too many states" },
|
1233
deps/oblib/src/lib/regex/regex/regexec.cpp
vendored
1233
deps/oblib/src/lib/regex/regex/regexec.cpp
vendored
File diff suppressed because it is too large
Load Diff
60
deps/oblib/src/lib/regex/regex/regfree.cpp
vendored
60
deps/oblib/src/lib/regex/regex/regfree.cpp
vendored
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* ob_regfree - free an RE
|
||||
*
|
||||
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
*
|
||||
* Development of this software was funded, in part, by Cray Research Inc.,
|
||||
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
* Corporation, none of whom are responsible for the results. The author
|
||||
* thanks all of them.
|
||||
*
|
||||
* Redistribution and use in source and binary forms -- with or without
|
||||
* modification -- are permitted for any purpose, provided that
|
||||
* redistributions in source form retain this entire copyright notice and
|
||||
* indicate the origin and nature of any modifications.
|
||||
*
|
||||
* I'd appreciate being given credit for this package in the documentation of
|
||||
* software which uses it, but that is not a requirement.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* You might think that this could be incorporated into regcomp.c, and that
|
||||
* would be a reasonable idea... except that this is a generic function (with
|
||||
* a generic name), applicable to all compiled REs regardless of the size of
|
||||
* their characters, whereas the stuff in regcomp.c gets compiled once per
|
||||
* character size.
|
||||
*/
|
||||
|
||||
#include "regguts.h"
|
||||
|
||||
/*
|
||||
- ob_regfree - free an RE (generic function, punts to RE-specific function)
|
||||
*
|
||||
* Ignoring invocation with NULL is a convenience.
|
||||
*/
|
||||
void
|
||||
ob_regfree(
|
||||
ob_regex_t *re)
|
||||
{
|
||||
if (re == NULL) {
|
||||
return;
|
||||
}
|
||||
(*((struct fns *)re->re_fns)->free)(re);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
428
deps/oblib/src/lib/regex/regex/regguts.h
vendored
428
deps/oblib/src/lib/regex/regex/regguts.h
vendored
@ -1,428 +0,0 @@
|
||||
/*
|
||||
* Internal interface definitions, etc., for the reg package
|
||||
*
|
||||
* Copyright (c) 1998, 1999 Henry Spencer. All rights reserved.
|
||||
*
|
||||
* Development of this software was funded, in part, by Cray Research Inc.,
|
||||
* UUNET Communications Services Inc., Sun Microsystems Inc., and Scriptics
|
||||
* Corporation, none of whom are responsible for the results. The author
|
||||
* thanks all of them.
|
||||
*
|
||||
* Redistribution and use in source and binary forms -- with or without
|
||||
* modification -- are permitted for any purpose, provided that
|
||||
* redistributions in source form retain this entire copyright notice and
|
||||
* indicate the origin and nature of any modifications.
|
||||
*
|
||||
* I'd appreciate being given credit for this package in the documentation of
|
||||
* software which uses it, but that is not a requirement.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* HENRY SPENCER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Environmental customization. It should not (I hope) be necessary to alter
|
||||
* the file you are now reading -- regcustom.h should handle it all, given
|
||||
* care here and elsewhere.
|
||||
*/
|
||||
#include "regcustom.h"
|
||||
|
||||
/*
|
||||
* Things that regcustom.h might override.
|
||||
*/
|
||||
|
||||
/* standard header files (NULL is a reasonable indicator for them) */
|
||||
#ifndef NULL
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
/* assertions */
|
||||
#ifndef assert
|
||||
#ifndef OB_REG_DEBUG
|
||||
#ifndef NDEBUG
|
||||
#define NDEBUG /* no assertions */
|
||||
#endif
|
||||
#endif /* !OB_REG_DEBUG */
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
/* voids */
|
||||
#ifndef VOID
|
||||
#define VOID void /* for function return values */
|
||||
#endif
|
||||
#ifndef DISCARD
|
||||
#define DISCARD void /* for throwing values away */
|
||||
#endif
|
||||
#ifndef PVOID
|
||||
#define PVOID void * /* generic pointer */
|
||||
#endif
|
||||
#ifndef VS
|
||||
#define VS(x) ((void*)(x)) /* cast something to generic ptr */
|
||||
#endif
|
||||
#ifndef NOPARMS
|
||||
#define NOPARMS void /* for empty parm lists */
|
||||
#endif
|
||||
|
||||
/* const */
|
||||
#ifndef CONST1
|
||||
#define CONST1 const /* for old compilers, might be empty */
|
||||
#endif
|
||||
|
||||
/* function-pointer declarator */
|
||||
#ifndef FUNCPTR
|
||||
#if __STDC__ >= 1
|
||||
#define FUNCPTR(name, args) (*name)args
|
||||
#else
|
||||
#define FUNCPTR(name, args) (*name)()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* memory allocation */
|
||||
#ifndef MALLOC
|
||||
#define MALLOC(n) malloc(n)
|
||||
#endif
|
||||
#ifndef REALLOC
|
||||
#define REALLOC(p, n) realloc(VS(p), n)
|
||||
#endif
|
||||
#ifndef FREE
|
||||
#define FREE(p) free(VS(p))
|
||||
#endif
|
||||
|
||||
/* want size of a char in bits, and max value in bounded quantifiers */
|
||||
#ifndef CHAR_BIT
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#ifndef _POSIX2_RE_DUP_MAX
|
||||
#define _POSIX2_RE_DUP_MAX 255 /* normally from <limits.h> */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* misc
|
||||
*/
|
||||
|
||||
#define NOTREACHED 0
|
||||
#define xxx 1
|
||||
|
||||
#define DUPMAX _POSIX2_RE_DUP_MAX
|
||||
#define INFINITY_1 (DUPMAX+1)
|
||||
|
||||
#define REMAGIC 0xfed7 /* magic number for main struct */
|
||||
|
||||
/*
|
||||
* debugging facilities
|
||||
*/
|
||||
#ifdef OB_REG_DEBUG
|
||||
/* FDEBUG does finite-state tracing */
|
||||
#define FDEBUG(arglist) { if (v->eflags&OB_REG_FTRACE) printf arglist; }
|
||||
/* MDEBUG does higher-level tracing */
|
||||
#define MDEBUG(arglist) { if (v->eflags&OB_REG_MTRACE) printf arglist; }
|
||||
#else
|
||||
#define FDEBUG(arglist) {}
|
||||
#define MDEBUG(arglist) {}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* bitmap manipulation
|
||||
*/
|
||||
#define UBITS (CHAR_BIT * sizeof(unsigned))
|
||||
#define BSET(uv, sn) ((uv)[(sn)/UBITS] |= (unsigned)1 << ((sn)%UBITS))
|
||||
#define ISBSET(uv, sn) ((uv)[(sn)/UBITS] & ((unsigned)1 << ((sn)%UBITS)))
|
||||
|
||||
/*
|
||||
* We dissect a chr into byts for colormap table indexing. Here we define a
|
||||
* byt, which will be the same as a byte on most machines... The exact size of
|
||||
* a byt is not critical, but about 8 bits is good, and extraction of 8-bit
|
||||
* chunks is sometimes especially fast.
|
||||
*/
|
||||
|
||||
#ifndef BYTBITS
|
||||
#define BYTBITS 8 /* bits in a byt */
|
||||
#endif
|
||||
#define BYTTAB (1<<BYTBITS) /* size of table with one entry per byt value */
|
||||
#define BYTMASK (BYTTAB-1) /* bit mask for byt */
|
||||
#define NBYTS ((CHRBITS+BYTBITS-1)/BYTBITS)
|
||||
/* the definition of GETCOLOR(), below, assumes NBYTS <= 4 */
|
||||
|
||||
/*
|
||||
* As soon as possible, we map chrs into equivalence classes -- "colors" --
|
||||
* which are of much more manageable number.
|
||||
*/
|
||||
|
||||
typedef short color; /* colors of characters */
|
||||
typedef int pcolor; /* what color promotes to */
|
||||
#define COLORLESS (-1) /* impossible color */
|
||||
#define WHITE 0 /* default color, parent of all others */
|
||||
|
||||
/*
|
||||
* A colormap is a tree -- more precisely, a DAG -- indexed at each level by a
|
||||
* byt of the chr, to map the chr to a color efficiently. Because lower
|
||||
* sections of the tree can be shared, it can exploit the usual sparseness of
|
||||
* such a mapping table. The tree is always NBYTS levels deep (in the past it
|
||||
* was shallower during construction but was "filled" to full depth at the end
|
||||
* of that); areas that are unaltered as yet point to "fill blocks" which are
|
||||
* entirely WHITE in color.
|
||||
*/
|
||||
|
||||
/* the tree itself */
|
||||
struct colors {
|
||||
color ccolor[BYTTAB];
|
||||
};
|
||||
struct ptrs {
|
||||
union tree *pptr[BYTTAB];
|
||||
};
|
||||
union tree {
|
||||
struct colors colors;
|
||||
struct ptrs ptrs;
|
||||
};
|
||||
#define tcolor colors.ccolor
|
||||
#define tptr ptrs.pptr
|
||||
|
||||
/* Internal per-color descriptor structure for the color machinery */
|
||||
struct colordesc {
|
||||
uchr nchrs; /* number of chars of this color */
|
||||
color sub; /* open subcolor (if any); free chain ptr */
|
||||
#define NOSUB COLORLESS
|
||||
struct arc *arcs; /* color chain */
|
||||
int flags;
|
||||
#define FREECOL 01 /* currently free */
|
||||
#define PSEUDO 02 /* pseudocolor, no real chars */
|
||||
#define UNUSEDCOLOR(cd) ((cd)->flags&FREECOL)
|
||||
union tree *block; /* block of solid color, if any */
|
||||
};
|
||||
|
||||
/* the color map itself */
|
||||
struct colormap {
|
||||
int magic;
|
||||
#define CMMAGIC 0x876
|
||||
struct vars *v; /* for compile error reporting */
|
||||
size_t ncds; /* number of colordescs */
|
||||
size_t max; /* highest in use */
|
||||
color free; /* beginning of free chain (if non-0) */
|
||||
struct colordesc *cd;
|
||||
#define CDEND(cm) (&(cm)->cd[(cm)->max + 1])
|
||||
#define NINLINECDS ((size_t)10)
|
||||
struct colordesc cdspace[NINLINECDS];
|
||||
union tree tree[NBYTS]; /* tree top, plus fill blocks */
|
||||
};
|
||||
|
||||
/* optimization magic to do fast chr->color mapping */
|
||||
#define B0(c) ((c) & BYTMASK)
|
||||
#define B1(c) (((c)>>BYTBITS) & BYTMASK)
|
||||
#define B2(c) (((c)>>(2*BYTBITS)) & BYTMASK)
|
||||
#define B3(c) (((c)>>(3*BYTBITS)) & BYTMASK)
|
||||
#if NBYTS == 1
|
||||
#define GETCOLOR(cm, c) ((cm)->tree->tcolor[B0(c)])
|
||||
#endif
|
||||
/* beware, for NBYTS>1, GETCOLOR() is unsafe -- 2nd arg used repeatedly */
|
||||
#if NBYTS == 2
|
||||
#define GETCOLOR(cm, c) ((cm)->tree->tptr[B1(c)]->tcolor[B0(c)])
|
||||
#endif
|
||||
#if NBYTS == 4
|
||||
#define GETCOLOR(cm, c) ((cm)->tree->tptr[B3(c)]->tptr[B2(c)]->tptr[B1(c)]->tcolor[B0(c)])
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Interface definitions for locale-interface functions in locale.c.
|
||||
*/
|
||||
|
||||
/* Representation of a set of characters. */
|
||||
struct cvec {
|
||||
int nchrs; /* number of chrs */
|
||||
int chrspace; /* number of chrs possible */
|
||||
chr *chrs; /* pointer to vector of chrs */
|
||||
int nranges; /* number of ranges (chr pairs) */
|
||||
int rangespace; /* number of chrs possible */
|
||||
chr *ranges; /* pointer to vector of chr pairs */
|
||||
};
|
||||
|
||||
/*
|
||||
* definitions for non-deterministic finite autmaton (NFA) internal
|
||||
* representation
|
||||
*
|
||||
* Having a "from" pointer within each arc may seem redundant, but it saves a
|
||||
* lot of hassle.
|
||||
*/
|
||||
|
||||
struct state;
|
||||
|
||||
struct arc {
|
||||
int type;
|
||||
#define ARCFREE '\0'
|
||||
color co;
|
||||
struct state *from; /* where it's from (and contained within) */
|
||||
struct state *to; /* where it's to */
|
||||
struct arc *outchain; /* *from's outs chain or free chain */
|
||||
#define freechain outchain
|
||||
struct arc *inchain; /* *to's ins chain */
|
||||
struct arc *colorchain; /* color's arc chain */
|
||||
struct arc *colorchainRev; /* back-link in color's arc chain */
|
||||
};
|
||||
|
||||
struct arcbatch { /* for bulk allocation of arcs */
|
||||
struct arcbatch *next;
|
||||
#define ABSIZE 10
|
||||
struct arc a[ABSIZE];
|
||||
};
|
||||
|
||||
struct state {
|
||||
int no;
|
||||
#define FREESTATE (-1)
|
||||
char flag; /* marks special states */
|
||||
int nins; /* number of inarcs */
|
||||
struct arc *ins; /* chain of inarcs */
|
||||
int nouts; /* number of outarcs */
|
||||
struct arc *outs; /* chain of outarcs */
|
||||
struct arc *free; /* chain of free arcs */
|
||||
struct state *tmp; /* temporary for traversal algorithms */
|
||||
struct state *next; /* chain for traversing all */
|
||||
struct state *prev; /* back chain */
|
||||
struct arcbatch oas; /* first arcbatch, avoid malloc in easy case */
|
||||
int noas; /* number of arcs used in first arcbatch */
|
||||
};
|
||||
|
||||
struct nfa {
|
||||
struct state *pre; /* pre-initial state */
|
||||
struct state *init; /* initial state */
|
||||
struct state *final; /* final state */
|
||||
struct state *post; /* post-final state */
|
||||
int nstates; /* for numbering states */
|
||||
struct state *states; /* state-chain header */
|
||||
struct state *slast; /* tail of the chain */
|
||||
struct state *free; /* free list */
|
||||
struct colormap *cm; /* the color map */
|
||||
color bos[2]; /* colors, if any, assigned to BOS and BOL */
|
||||
color eos[2]; /* colors, if any, assigned to EOS and EOL */
|
||||
size_t size; /* Current NFA size; differs from nstates as
|
||||
* it also counts the number of states created
|
||||
* by children of this state. */
|
||||
struct vars *v; /* simplifies compile error reporting */
|
||||
struct nfa *parent; /* parent NFA, if any */
|
||||
};
|
||||
|
||||
/*
|
||||
* definitions for compacted NFA
|
||||
*/
|
||||
|
||||
struct carc {
|
||||
color co; /* COLORLESS is list terminator */
|
||||
int to; /* state number */
|
||||
};
|
||||
|
||||
struct cnfa {
|
||||
int nstates; /* number of states */
|
||||
int ncolors; /* number of colors */
|
||||
int flags;
|
||||
#define HASLACONS 01 /* uses lookahead constraints */
|
||||
int pre; /* setup state number */
|
||||
int post; /* teardown state number */
|
||||
color bos[2]; /* colors, if any, assigned to BOS and BOL */
|
||||
color eos[2]; /* colors, if any, assigned to EOS and EOL */
|
||||
struct carc **states; /* vector of pointers to outarc lists */
|
||||
struct carc *arcs; /* the area for the lists */
|
||||
};
|
||||
#define ZAPCNFA(cnfa) ((cnfa).nstates = 0)
|
||||
#define NULLCNFA(cnfa) ((cnfa).nstates == 0)
|
||||
|
||||
/*
|
||||
* Used to limit the maximum NFA size to something sane. [Bug 1810264]
|
||||
*/
|
||||
|
||||
#ifndef OB_REG_MAX_STATES
|
||||
# define OB_REG_MAX_STATES 100000
|
||||
#endif
|
||||
|
||||
/*
|
||||
* subexpression tree
|
||||
*/
|
||||
|
||||
struct subre {
|
||||
char op; /* '|', '.' (concat), 'b' (backref), '(',
|
||||
* '=' */
|
||||
char flags;
|
||||
#define LONGER 01 /* prefers longer match */
|
||||
#define SHORTER 02 /* prefers shorter match */
|
||||
#define MIXED 04 /* mixed preference below */
|
||||
#define CAP 010 /* capturing parens below */
|
||||
#define BACKR 020 /* back reference below */
|
||||
#define INUSE 0100 /* in use in final tree */
|
||||
#define LOCAL 03 /* bits which may not propagate up */
|
||||
#define LMIX(f) ((f)<<2) /* LONGER -> MIXED */
|
||||
#define SMIX(f) ((f)<<1) /* SHORTER -> MIXED */
|
||||
#define UP(f) (((f)&~LOCAL) | (LMIX(f) & SMIX(f) & MIXED))
|
||||
#define MESSY(f) ((f)&(MIXED|CAP|BACKR))
|
||||
#define PREF(f) ((f)&LOCAL)
|
||||
#define PREF2(f1, f2) ((PREF(f1) != 0) ? PREF(f1) : PREF(f2))
|
||||
#define COMBINE(f1, f2) (UP((f1)|(f2)) | PREF2(f1, f2))
|
||||
short retry; /* index into retry memory */
|
||||
int subno; /* subexpression number (for 'b' and '(') */
|
||||
short min; /* min repetitions, for backref only */
|
||||
short max; /* max repetitions, for backref only */
|
||||
struct subre *left; /* left child, if any (also freelist chain) */
|
||||
struct subre *right; /* right child, if any */
|
||||
struct state *begin; /* outarcs from here... */
|
||||
struct state *end; /* ...ending in inarcs here */
|
||||
struct cnfa cnfa; /* compacted NFA, if any */
|
||||
struct subre *chain; /* for bookkeeping and error cleanup */
|
||||
};
|
||||
|
||||
/*
|
||||
* table of function pointers for generic manipulation functions. A ob_regex_t's
|
||||
* re_fns points to one of these.
|
||||
*/
|
||||
|
||||
struct fns {
|
||||
VOID FUNCPTR(free, (ob_regex_t *));
|
||||
};
|
||||
|
||||
/*
|
||||
* the insides of a ob_regex_t, hidden behind a void *
|
||||
*/
|
||||
|
||||
struct guts {
|
||||
int magic;
|
||||
#define GUTSMAGIC 0xfed9
|
||||
int cflags; /* copy of compile flags */
|
||||
long info; /* copy of re_info */
|
||||
size_t nsub; /* copy of re_nsub */
|
||||
struct subre *tree;
|
||||
struct cnfa search; /* for fast preliminary search */
|
||||
int ntree;
|
||||
struct colormap cmap;
|
||||
int FUNCPTR(compare, (CONST1 chr *, CONST1 chr *, size_t));
|
||||
struct subre *lacons; /* lookahead-constraint vector */
|
||||
int nlacons; /* size of lacons */
|
||||
};
|
||||
|
||||
/*
|
||||
* Magic for allocating a variable workspace. This default version is
|
||||
* stack-hungry.
|
||||
*/
|
||||
|
||||
#ifndef AllocVars
|
||||
#define AllocVars(vPtr) \
|
||||
struct vars var; \
|
||||
register struct vars *vPtr = &var
|
||||
#endif
|
||||
#ifndef FreeVars
|
||||
#define FreeVars(vPtr) ((void) 0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Local Variables:
|
||||
* mode: c
|
||||
* c-basic-offset: 4
|
||||
* fill-column: 78
|
||||
* End:
|
||||
*/
|
15
deps/oblib/src/lib/rowid/ob_urowid.cpp
vendored
15
deps/oblib/src/lib/rowid/ob_urowid.cpp
vendored
@ -334,7 +334,9 @@ inline int ObURowIDData::get_pk_value(ObObjType obj_type, int64_t &pos, ObObj &p
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const uint8_t version = get_version();
|
||||
if (OB_UNLIKELY(PK_ROWID_VERSION != version && NO_PK_ROWID_VERSION != version)) {
|
||||
if (OB_UNLIKELY(PK_ROWID_VERSION != version
|
||||
&& NO_PK_ROWID_VERSION != version
|
||||
&& LOB_NO_PK_ROWID_VERSION != version)) {
|
||||
ret = OB_INVALID_ROWID;
|
||||
COMMON_LOG(WARN, "invalid rowid version", K(ret), K(version));
|
||||
} else if (OB_UNLIKELY(obj_type >= ObMaxType)
|
||||
@ -489,7 +491,9 @@ bool ObURowIDData::is_valid_urowid() const
|
||||
is_valid = rowid_len_ == HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE;
|
||||
} else if (EXT_HEAP_TABLE_ROWID_VERSION == version) {
|
||||
is_valid = rowid_len_ == EXT_HEAP_ORGANIZED_TABLE_ROWID_CONTENT_BUF_SIZE;
|
||||
} else if (NO_PK_ROWID_VERSION == version || PK_ROWID_VERSION == version) {
|
||||
} else if (NO_PK_ROWID_VERSION == version
|
||||
|| PK_ROWID_VERSION == version
|
||||
|| LOB_NO_PK_ROWID_VERSION == version) {
|
||||
int64_t pos = get_pk_content_offset();
|
||||
ObObj obj;
|
||||
for (; is_valid && pos < rowid_len_; ) {
|
||||
@ -516,7 +520,8 @@ bool ObURowIDData::is_valid_version(int64_t v)
|
||||
} else if (PK_ROWID_VERSION != v
|
||||
&& NO_PK_ROWID_VERSION != v
|
||||
&& HEAP_TABLE_ROWID_VERSION != v
|
||||
&& EXT_HEAP_TABLE_ROWID_VERSION != v) {
|
||||
&& EXT_HEAP_TABLE_ROWID_VERSION != v
|
||||
&& LOB_NO_PK_ROWID_VERSION != v) {
|
||||
if (!is_valid_part_gen_col_version(v)) {
|
||||
bret = false;
|
||||
}
|
||||
@ -542,7 +547,9 @@ uint8_t ObURowIDData::get_version() const
|
||||
int64_t offset = get_pk_version_offset();
|
||||
if (offset < rowid_len_) {
|
||||
raw_version = rowid_content_[offset];
|
||||
if (PK_ROWID_VERSION == raw_version || NO_PK_ROWID_VERSION == raw_version) {
|
||||
if (PK_ROWID_VERSION == raw_version
|
||||
|| NO_PK_ROWID_VERSION == raw_version
|
||||
|| LOB_NO_PK_ROWID_VERSION == raw_version) {
|
||||
version = raw_version;
|
||||
} else if (is_valid_part_gen_col_version(raw_version)) {
|
||||
version = PK_ROWID_VERSION;
|
||||
|
2
deps/oblib/src/lib/rowid/ob_urowid.h
vendored
2
deps/oblib/src/lib/rowid/ob_urowid.h
vendored
@ -46,6 +46,8 @@ public:
|
||||
INVALID_ROWID_VERSION = 0,
|
||||
PK_ROWID_VERSION = 1,
|
||||
NO_PK_ROWID_VERSION = 2,
|
||||
|
||||
LOB_NO_PK_ROWID_VERSION = 3,
|
||||
HEAP_TABLE_ROWID_VERSION = 128, // 0x80
|
||||
EXT_HEAP_TABLE_ROWID_VERSION = 160, // 0xA0
|
||||
};
|
||||
|
1
deps/oblib/src/lib/stat/ob_latch_define.h
vendored
1
deps/oblib/src/lib/stat/ob_latch_define.h
vendored
@ -305,6 +305,7 @@ LATCH_DEF(REWRITE_RULE_ITEM_LOCK, 292, "rewrite rule item lock", LATCH_FIFO, 200
|
||||
LATCH_DEF(SRS_LOCK, 292, "srs lock", LATCH_READ_PREFER, 2000, 0, SRS_LOCK_WAIT, "srs lock")
|
||||
LATCH_DEF(DDL_EXECUTE_LOCK, 293, "ddl execute lock", LATCH_FIFO, 2000, 0, DDL_EXECUTE_LOCK_WAIT, "ddl execute lock")
|
||||
LATCH_DEF(TENANT_IO_CONFIG_LOCK, 294, "tenant io config lock", LATCH_FIFO, 2000, 0, TENANT_IO_CONFIG_WAIT, "tenant io config lock")
|
||||
LATCH_DEF(SQL_WF_PARTICIPATOR_COND_LOCK, 295, "window function participator lock", LATCH_FIFO, 2000, 0, SQL_WF_PARTICIPATOR_COND_WAIT, "window function participator lock")
|
||||
|
||||
LATCH_DEF(LATCH_END, 99999, "latch end", LATCH_FIFO, 2000, 0, WAIT_EVENT_END, "latch end")
|
||||
#endif
|
||||
|
30
deps/oblib/src/lib/timezone/ob_time_convert.cpp
vendored
30
deps/oblib/src/lib/timezone/ob_time_convert.cpp
vendored
@ -393,7 +393,7 @@ int ObTimeConverter::str_to_datetime(const ObString &str, const ObTimeConvertCtx
|
||||
if (cvrt_ctx.is_timestamp_) {
|
||||
local_date_sql_mode.allow_invalid_dates_ = false;
|
||||
}
|
||||
if (OB_FAIL(str_to_ob_time_with_date(str, ob_time, scale, false, local_date_sql_mode))) {
|
||||
if (OB_FAIL(str_to_ob_time_with_date(str, ob_time, scale, false, local_date_sql_mode, cvrt_ctx.need_truncate_))) {
|
||||
LOG_WARN("failed to convert string to datetime", K(ret));
|
||||
} else if (!cvrt_ctx.is_timestamp_ && ob_time.is_tz_name_valid_) {
|
||||
//only enable time zone data type can has tz name and tz addr
|
||||
@ -792,11 +792,12 @@ int ObTimeConverter::str_to_date(const ObString &str, int32_t &value,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTimeConverter::str_to_time(const ObString &str, int64_t &value, int16_t *scale, const ObScale &time_scale)
|
||||
int ObTimeConverter::str_to_time(const ObString &str, int64_t &value, int16_t *scale,
|
||||
const ObScale &time_scale, const bool &need_truncate)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObTime ob_time(DT_TYPE_TIME);
|
||||
if (OB_FAIL(str_to_ob_time_without_date(str, ob_time, scale))) {
|
||||
if (OB_FAIL(str_to_ob_time_without_date(str, ob_time, scale, need_truncate))) {
|
||||
LOG_WARN("failed to convert string to time", K(ret), K(str));
|
||||
if (OB_ERR_TRUNCATED_WRONG_VALUE == ret) {
|
||||
value = ob_time_to_time(ob_time);
|
||||
@ -1819,7 +1820,7 @@ int ObTimeConverter::get_time_zone(const ObTimeDelims *delims, ObTime &ob_time,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTimeConverter::str_to_digit_with_date(const ObString &str, ObTimeDigits *digits, ObTime &ob_time)
|
||||
int ObTimeConverter::str_to_digit_with_date(const ObString &str, ObTimeDigits *digits, ObTime &ob_time, const bool &need_truncate)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(str.ptr()) || OB_UNLIKELY(str.length() <= 0) || OB_ISNULL(digits)) {
|
||||
@ -1909,7 +1910,7 @@ int ObTimeConverter::str_to_digit_with_date(const ObString &str, ObTimeDigits *d
|
||||
//if HAS_TYPE_ORACLE, digits[DT_USEC] store nanosecond in fact
|
||||
const int64_t max_precision = (HAS_TYPE_ORACLE(ob_time.mode_) ? OB_MAX_TIMESTAMP_TZ_PRECISION: OB_MAX_DATETIME_PRECISION);
|
||||
const bool use_strict_check = HAS_TYPE_ORACLE(ob_time.mode_);
|
||||
if (OB_FAIL(apply_usecond_delim_rule(delims[DT_SEC], digits[DT_USEC], max_precision, use_strict_check))) {
|
||||
if (OB_FAIL(apply_usecond_delim_rule(delims[DT_SEC], digits[DT_USEC], max_precision, use_strict_check, need_truncate))) {
|
||||
LOG_WARN("failed to apply rule", K(use_strict_check), K(ret));
|
||||
} else if (!(DT_TYPE_DATE & ob_time.mode_) && (DT_TYPE_TIME & ob_time.mode_)) {
|
||||
if (OB_FAIL(apply_datetime_for_time_rule(ob_time, digits, delims))) {
|
||||
@ -1931,7 +1932,8 @@ int ObTimeConverter::str_to_digit_with_date(const ObString &str, ObTimeDigits *d
|
||||
//dayofmonth函数需要容忍月、日为0的错误
|
||||
int ObTimeConverter::str_to_ob_time_with_date(
|
||||
const ObString &str, ObTime &ob_time, int16_t *scale,
|
||||
const bool is_dayofmonth, const ObDateSqlMode date_sql_mode)
|
||||
const bool is_dayofmonth, const ObDateSqlMode date_sql_mode,
|
||||
const bool &need_truncate)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(str.ptr()) || OB_UNLIKELY(str.length() <= 0)) {
|
||||
@ -1939,7 +1941,7 @@ int ObTimeConverter::str_to_ob_time_with_date(
|
||||
LOG_WARN("datetime string is invalid", K(ret), K(str));
|
||||
} else {
|
||||
ObTimeDigits digits[DATETIME_PART_CNT];
|
||||
if (OB_FAIL(str_to_digit_with_date(str, digits, ob_time))) {
|
||||
if (OB_FAIL(str_to_digit_with_date(str, digits, ob_time, need_truncate))) {
|
||||
LOG_WARN("failed to get digits", K(ret), K(str));
|
||||
} else if (OB_FAIL(validate_datetime(ob_time, is_dayofmonth, date_sql_mode))) {
|
||||
// OK, it seems like a valid format, now we need check its value.
|
||||
@ -1983,7 +1985,7 @@ int ObTimeConverter::str_is_date_format(const ObString &str, bool &date_flag)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTimeConverter::str_to_ob_time_without_date(const ObString &str, ObTime &ob_time, int16_t *scale)
|
||||
int ObTimeConverter::str_to_ob_time_without_date(const ObString &str, ObTime &ob_time, int16_t *scale, const bool &need_truncate)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(str.ptr()) || OB_UNLIKELY(str.length() <= 0)) {
|
||||
@ -2090,7 +2092,7 @@ int ObTimeConverter::str_to_ob_time_without_date(const ObString &str, ObTime &ob
|
||||
// 7 is used for rounding to 6 digits.
|
||||
if (OB_FAIL(get_datetime_digits(pos, end, 7, digits))) {
|
||||
LOG_WARN("failed to get digits from datetime string", K(ret));
|
||||
} else if (OB_FAIL(normalize_usecond_round(digits, OB_MAX_DATETIME_PRECISION))) {
|
||||
} else if (OB_FAIL(normalize_usecond(digits, OB_MAX_DATETIME_PRECISION, false, need_truncate))) {
|
||||
LOG_WARN("failed to round usecond", K(ret));
|
||||
} else {
|
||||
ob_time.parts_[DT_USEC] = digits.value_; // usecond.
|
||||
@ -5583,8 +5585,8 @@ OB_INLINE bool ObTimeConverter::is_negative(const char *&str, const char *end)
|
||||
return ret;
|
||||
}
|
||||
|
||||
OB_INLINE int ObTimeConverter::normalize_usecond_round(ObTimeDigits &digits, const int64_t max_precision,
|
||||
const bool use_strict_check/*false*/)
|
||||
OB_INLINE int ObTimeConverter::normalize_usecond(ObTimeDigits &digits, const int64_t max_precision,
|
||||
const bool use_strict_check/*false*/, const bool &need_truncate)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(digits.value_ < 0)
|
||||
@ -5605,7 +5607,7 @@ OB_INLINE int ObTimeConverter::normalize_usecond_round(ObTimeDigits &digits, con
|
||||
} else {
|
||||
// .1234567 will round to 123457.
|
||||
digits.value_ /= static_cast<int32_t>(power_of_10[digits.len_ - max_precision]);
|
||||
if (digits.ptr_[max_precision] >= '5') {
|
||||
if (!need_truncate && digits.ptr_[max_precision] >= '5') {
|
||||
++digits.value_;
|
||||
}
|
||||
}
|
||||
@ -5668,11 +5670,11 @@ OB_INLINE void ObTimeConverter::apply_date_year2_rule(int64_t &year)
|
||||
}
|
||||
|
||||
OB_INLINE int ObTimeConverter::apply_usecond_delim_rule(ObTimeDelims &second, ObTimeDigits &usecond,
|
||||
const int64_t max_precision, const bool use_strict_check)
|
||||
const int64_t max_precision, const bool use_strict_check, const bool &need_truncate)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (is_single_dot(second) && usecond.value_ > 0) {
|
||||
ret = normalize_usecond_round(usecond, max_precision, use_strict_check);
|
||||
ret = normalize_usecond(usecond, max_precision, use_strict_check, need_truncate);
|
||||
} else {
|
||||
usecond.value_ = 0;
|
||||
}
|
||||
|
21
deps/oblib/src/lib/timezone/ob_time_convert.h
vendored
21
deps/oblib/src/lib/timezone/ob_time_convert.h
vendored
@ -293,10 +293,11 @@ struct ObTimeConstStr {
|
||||
|
||||
struct ObTimeConvertCtx
|
||||
{
|
||||
ObTimeConvertCtx(const ObTimeZoneInfo *tz_info, const bool is_timestamp)
|
||||
ObTimeConvertCtx(const ObTimeZoneInfo *tz_info, const bool is_timestamp, const bool &need_truncate = false)
|
||||
:tz_info_(tz_info),
|
||||
oracle_nls_format_(),
|
||||
is_timestamp_(is_timestamp) {}
|
||||
is_timestamp_(is_timestamp),
|
||||
need_truncate_(need_truncate) {}
|
||||
ObTimeConvertCtx(const ObTimeZoneInfo *tz_info, const ObString &oracle_nls_format, const bool is_timestamp)
|
||||
:tz_info_(tz_info),
|
||||
oracle_nls_format_(oracle_nls_format),
|
||||
@ -304,6 +305,7 @@ struct ObTimeConvertCtx
|
||||
const ObTimeZoneInfo *tz_info_;
|
||||
ObString oracle_nls_format_;
|
||||
bool is_timestamp_; //means mysql timestamp?
|
||||
bool need_truncate_;
|
||||
};
|
||||
class ObTimeConverter
|
||||
{
|
||||
@ -406,7 +408,8 @@ public:
|
||||
|
||||
static int str_is_date_format(const ObString &str, bool &date_flag);
|
||||
static int str_to_date(const ObString &str, int32_t &value, const ObDateSqlMode date_sql_mode = 0);
|
||||
static int str_to_time(const ObString &str, int64_t &value, int16_t *scale = NULL, const ObScale &time_scale = 0);
|
||||
static int str_to_time(const ObString &str, int64_t &value, int16_t *scale = NULL,
|
||||
const ObScale &time_scale = 0, const bool &need_truncate = false);
|
||||
static int str_to_year(const ObString &str, uint8_t &value);
|
||||
static int str_to_interval(const ObString &str, ObDateUnitType unit_type, int64_t &value);
|
||||
// int / double / string <- datetime(timestamp) / date / time / year.
|
||||
@ -478,8 +481,8 @@ public:
|
||||
const ObDateSqlMode date_sql_mode);
|
||||
static int int_to_ob_time_without_date(int64_t time_second, ObTime &ob_time, int64_t nano_second = 0);
|
||||
static int str_to_ob_time_with_date(const ObString &str, ObTime &ob_time, int16_t *scale,
|
||||
const bool is_dayofmonth, const ObDateSqlMode date_sql_mode);
|
||||
static int str_to_ob_time_without_date(const ObString &str, ObTime &ob_time, int16_t *scale = NULL);
|
||||
const bool is_dayofmonth, const ObDateSqlMode date_sql_mode, const bool &need_truncate = false);
|
||||
static int str_to_ob_time_without_date(const ObString &str, ObTime &ob_time, int16_t *scale = NULL, const bool &need_truncate = false);
|
||||
static int str_to_ob_time_format(const ObString &str, const ObString &fmt, ObTime &ob_time,
|
||||
int16_t *scale, const bool no_zero_in_date,
|
||||
const ObDateSqlMode date_sql_mode);
|
||||
@ -647,7 +650,7 @@ private:
|
||||
static int get_datetime_delims(const char *&str, const char *end, ObTimeDelims &delims);
|
||||
static int get_datetime_digits_delims(const char *&str, const char *end,
|
||||
int32_t max_len, ObTimeDigits &digits, ObTimeDelims &delims);
|
||||
static int str_to_digit_with_date(const ObString &str, ObTimeDigits *digits, ObTime &obtime);
|
||||
static int str_to_digit_with_date(const ObString &str, ObTimeDigits *digits, ObTime &obtime, const bool &need_truncate = false);
|
||||
static int get_time_zone(const ObTimeDelims *delims, ObTime &ob_time, const char *end_ptr);
|
||||
static void skip_delims(const char *&str, const char *end);
|
||||
static bool is_year4(int64_t first_token_len);
|
||||
@ -657,14 +660,14 @@ private:
|
||||
static bool is_all_spaces(const ObTimeDelims &delims);
|
||||
static bool has_any_space(const ObTimeDelims &delims);
|
||||
static bool is_negative(const char *&str, const char *end);
|
||||
static int normalize_usecond_round(ObTimeDigits &digits, const int64_t max_precision,
|
||||
const bool use_strict_check = false);
|
||||
static int normalize_usecond(ObTimeDigits &digits, const int64_t max_precision,
|
||||
const bool use_strict_check = false, const bool &need_truncate = false);
|
||||
static int normalize_usecond_trunc(ObTimeDigits &digits, bool need_trunc);
|
||||
static int apply_date_space_rule(const ObTimeDelims *delims);
|
||||
static void apply_date_year2_rule(ObTimeDigits &year);
|
||||
static void apply_date_year2_rule(int32_t &year);
|
||||
static void apply_date_year2_rule(int64_t &year);
|
||||
static int apply_usecond_delim_rule(ObTimeDelims &second, ObTimeDigits &usecond, const int64_t max_precision, const bool use_strict_check);
|
||||
static int apply_usecond_delim_rule(ObTimeDelims &second, ObTimeDigits &usecond, const int64_t max_precision, const bool use_strict_check, const bool &truncate = false);
|
||||
static int apply_datetime_for_time_rule(ObTime &ob_time, const ObTimeDigits *digits, const ObTimeDelims *delims);
|
||||
// static int find_time_range(int64_t t, const int64_t *range_boundaries, uint64_t higher_bound, uint64_t& result);
|
||||
// static int find_transition_type(int64_t t, const ObTimeZoneInfo *sp, TRAN_TYPE_INFO *& result);
|
||||
|
48
deps/oblib/src/lib/trace/ob_trace.cpp
vendored
48
deps/oblib/src/lib/trace/ob_trace.cpp
vendored
@ -28,10 +28,8 @@ ObFLTSpanMgr* __attribute__((weak)) get_flt_span_manager()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
int __attribute__((weak)) handle_span_record(char* buf, const int64_t buf_len, ObFLTSpanMgr* flt_span_manager)
|
||||
int __attribute__((weak))handle_span_record(ObFLTSpanMgr *flt_span_manager, char* tag_buf, int64_t tag_len, ::oceanbase::trace::ObSpanCtx* span)
|
||||
{
|
||||
UNUSED(buf);
|
||||
UNUSED(buf_len);
|
||||
UNUSED(flt_span_manager);
|
||||
return 0;
|
||||
}
|
||||
@ -49,17 +47,6 @@ if (OB_NOT_NULL(span) && 0 == span->span_id_.high_) { \
|
||||
span->span_id_.low_ = UUID::gen_rand(); \
|
||||
span->span_id_.high_ = span->start_ts_; \
|
||||
}
|
||||
static const char* __span_type_mapper[] = {
|
||||
#define FLT_DEF_SPAN(name, comment) #name,
|
||||
#define __HIGH_LEVEL_SPAN
|
||||
#define __MIDDLE_LEVEL_SPAN
|
||||
#define __LOW_LEVEL_SPAN
|
||||
#include "lib/trace/ob_trace_def.h"
|
||||
#undef __LOW_LEVEL_SPAN
|
||||
#undef __MIDDLE_LEVEL_SPAN
|
||||
#undef __HIGH_LEVEL_SPAN
|
||||
#undef FLT_DEF_SPAN
|
||||
};
|
||||
thread_local ObTrace* ObTrace::save_buffer = nullptr;
|
||||
|
||||
void flush_trace()
|
||||
@ -119,7 +106,7 @@ void flush_trace()
|
||||
span->is_follow_ ? "true" : "false",
|
||||
buf);
|
||||
buf[0] = '\0';
|
||||
IGNORE_RETURN sql::handle_span_record(buf, MAX_TRACE_LOG_SIZE, sql::get_flt_span_manager());
|
||||
IGNORE_RETURN sql::handle_span_record(sql::get_flt_span_manager(), buf, pos, span);
|
||||
if (0 != span->end_ts_) {
|
||||
current_span.remove(span);
|
||||
trace.freed_span_.add_first(span);
|
||||
@ -432,6 +419,7 @@ ObSpanCtx* ObTrace::begin_span(uint32_t span_type, uint8_t level, bool is_follow
|
||||
current_span_.add_first(new_span);
|
||||
new_span->span_type_ = span_type;
|
||||
new_span->span_id_.low_ = ++seq_;
|
||||
new_span->span_id_.high_ = 0;
|
||||
new_span->source_span_ = last_active_span_;
|
||||
new_span->is_follow_ = is_follow;
|
||||
new_span->start_ts_ = ObTimeUtility::fast_current_time();
|
||||
@ -443,6 +431,18 @@ ObSpanCtx* ObTrace::begin_span(uint32_t span_type, uint8_t level, bool is_follow
|
||||
return new_span;
|
||||
}
|
||||
|
||||
// used in ddl task tracing
|
||||
ObSpanCtx* ObTrace::begin_span_by_id(const uint32_t span_type, const uint8_t level,
|
||||
const bool is_follow, const UUID span_id, const int64_t start_ts)
|
||||
{
|
||||
ObSpanCtx *span = begin_span(span_type, level, is_follow);
|
||||
if (OB_NOT_NULL(span)) {
|
||||
span->span_id_ = span_id;
|
||||
span->start_ts_ = start_ts;
|
||||
}
|
||||
return span;
|
||||
}
|
||||
|
||||
void ObTrace::end_span(ObSpanCtx* span)
|
||||
{
|
||||
if (!trace_id_.is_inited() || OB_ISNULL(span) || !span->span_id_.is_inited()) {
|
||||
@ -453,6 +453,19 @@ void ObTrace::end_span(ObSpanCtx* span)
|
||||
}
|
||||
}
|
||||
|
||||
// used in ddl task tracing
|
||||
void ObTrace::release_span(ObSpanCtx *&span)
|
||||
{
|
||||
if (!trace_id_.is_inited() || OB_ISNULL(span) || !span->span_id_.is_inited()) {
|
||||
// do nothing
|
||||
} else {
|
||||
end_span(span);
|
||||
current_span_.remove(span);
|
||||
freed_span_.add_first(span);
|
||||
span = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ObTrace::reset_span()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
@ -555,5 +568,10 @@ void ObTrace::dump_span()
|
||||
_LIB_LOG(WARN, "%s backtrace: %s", buf, lbt());
|
||||
}
|
||||
|
||||
OB_SERIALIZE_MEMBER(FltTransCtx,
|
||||
trace_id_,
|
||||
span_id_,
|
||||
policy_);
|
||||
|
||||
}
|
||||
}
|
||||
|
44
deps/oblib/src/lib/trace/ob_trace.h
vendored
44
deps/oblib/src/lib/trace/ob_trace.h
vendored
@ -39,15 +39,10 @@ if (OB_NOT_NULL(span)) { \
|
||||
#define FLT_SET_TRACE_LEVEL(level) (OBTRACE->set_level(level))
|
||||
#define FLT_SET_AUTO_FLUSH(value) (OBTRACE->set_auto_flush(value))
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObFLTSpanMgr;
|
||||
extern ObFLTSpanMgr* get_flt_span_manager();
|
||||
extern int handle_span_record(char* buf, const int64_t buf_len, ObFLTSpanMgr* flt_span_manager);
|
||||
}
|
||||
}
|
||||
#define FLT_RESTORE_DDL_TRACE_CTX(flt_ctx) (OBTRACE->init(flt_ctx))
|
||||
#define FLT_RESTORE_DDL_SPAN(span_type, span_id, start_ts) (OBTRACE->begin_span_by_id(::oceanbase::trace::ObSpanType::span_type, GET_SPANLEVEL(::oceanbase::trace::ObSpanType::span_type), false, span_id, start_ts))
|
||||
#define FLT_RELEASE_DDL_SPAN(span) (OBTRACE->release_span(span))
|
||||
|
||||
#define FLUSH_TRACE() ::oceanbase::trace::flush_trace();
|
||||
|
||||
#define FLTSpanGuard(span_type) ::oceanbase::trace::__ObFLTSpanGuard __##span_type##__LINE__(::oceanbase::trace::ObSpanType::span_type, GET_SPANLEVEL(::oceanbase::trace::ObSpanType::span_type))
|
||||
@ -58,6 +53,18 @@ namespace oceanbase
|
||||
{
|
||||
namespace trace
|
||||
{
|
||||
static const char* __span_type_mapper[] = {
|
||||
#define FLT_DEF_SPAN(name, comment) #name,
|
||||
#define __HIGH_LEVEL_SPAN
|
||||
#define __MIDDLE_LEVEL_SPAN
|
||||
#define __LOW_LEVEL_SPAN
|
||||
#include "lib/trace/ob_trace_def.h"
|
||||
#undef __LOW_LEVEL_SPAN
|
||||
#undef __MIDDLE_LEVEL_SPAN
|
||||
#undef __HIGH_LEVEL_SPAN
|
||||
#undef FLT_DEF_SPAN
|
||||
};
|
||||
|
||||
extern void flush_trace();
|
||||
|
||||
struct UUID
|
||||
@ -98,6 +105,7 @@ struct UUID
|
||||
};
|
||||
|
||||
struct FltTransCtx {
|
||||
OB_UNIS_VERSION(1);
|
||||
public:
|
||||
FltTransCtx()
|
||||
: trace_id_(), span_id_(), policy_(0)
|
||||
@ -225,6 +233,13 @@ struct ObTrace
|
||||
UUID begin();
|
||||
void end();
|
||||
ObSpanCtx* begin_span(uint32_t span_type, uint8_t level, bool is_follow);
|
||||
// used in ddl task tracing
|
||||
ObSpanCtx* begin_span_by_id(const uint32_t span_type,
|
||||
const uint8_t level,
|
||||
const bool is_follow,
|
||||
const UUID span_id,
|
||||
const int64_t start_ts);
|
||||
void release_span(ObSpanCtx *&span);
|
||||
void end_span(ObSpanCtx* span_id);
|
||||
void reset_span();
|
||||
template <typename T, typename... Targs>
|
||||
@ -246,6 +261,7 @@ struct ObTrace
|
||||
OB_INLINE UUID get_trace_id() { return trace_id_; }
|
||||
OB_INLINE UUID get_root_span_id() { return root_span_id_; }
|
||||
OB_INLINE uint8_t get_policy() { return policy_; }
|
||||
OB_INLINE uint8_t get_level() { return level_; }
|
||||
OB_INLINE void set_level(uint8_t level) { level_ = 0x7f & level; }
|
||||
OB_INLINE void set_auto_flush(bool auto_flush) { auto_flush_ = auto_flush; }
|
||||
OB_INLINE bool is_auto_flush() { return auto_flush_; }
|
||||
@ -348,4 +364,14 @@ int ObTagCtx<char*>::tostring(char* buf, const int64_t buf_len, int64_t& pos);
|
||||
} // trace
|
||||
} // oceanbase
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObFLTSpanMgr;
|
||||
extern ObFLTSpanMgr* get_flt_span_manager();
|
||||
extern int handle_span_record(char* buf, const int64_t buf_len, ObFLTSpanMgr* flt_span_manager, ::oceanbase::trace::ObSpanCtx* span);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _OB_TRACE_H */
|
||||
|
57
deps/oblib/src/lib/trace/ob_trace_def.h
vendored
57
deps/oblib/src/lib/trace/ob_trace_def.h
vendored
@ -40,6 +40,8 @@ FLT_DEF_SPAN(com_query_process, "com_query process")
|
||||
FLT_DEF_SPAN(close, "close plan")
|
||||
FLT_DEF_SPAN(cmd_execute, "command execute")
|
||||
FLT_DEF_SPAN(cmd_open, "command open")
|
||||
FLT_DEF_SPAN(remote_execute, "remote execute")
|
||||
FLT_DEF_SPAN(remote_compile, "compile for remote sql")
|
||||
// **** for sql end ****
|
||||
|
||||
// **** for pl ****
|
||||
@ -84,6 +86,48 @@ FLT_DEF_SPAN(com_query_process, "com_query process")
|
||||
FLT_DEF_SPAN(fetch_das_extra_result, "fetch das extra result")
|
||||
FLT_DEF_SPAN(fetch_das_result_process, "fetch das result process")
|
||||
|
||||
// for ddl task
|
||||
FLT_DEF_SPAN(ddl_prepare, "prepare phase of ddl task")
|
||||
FLT_DEF_SPAN(ddl_failure_cleanup, "cleanup phase of ddl task failure")
|
||||
FLT_DEF_SPAN(ddl_success, "success check of ddl task")
|
||||
FLT_DEF_SPAN(ddl_wait_trans_end, "wait for all previous transaction finish")
|
||||
FLT_DEF_SPAN(ddl_lock_table, "lock table")
|
||||
FLT_DEF_SPAN(ddl_redefinition, "redefinition phase of ddl task")
|
||||
FLT_DEF_SPAN(ddl_copy_table_dependent_objects, "copy table dependent object")
|
||||
FLT_DEF_SPAN(ddl_modify_autoinc, "modify autoincrease column")
|
||||
FLT_DEF_SPAN(ddl_take_effect, "index take effect")
|
||||
FLT_DEF_SPAN(ddl_check_table_empty, "check table empty")
|
||||
|
||||
// build index task
|
||||
FLT_DEF_SPAN(ddl_build_index, "ddl build index task")
|
||||
FLT_DEF_SPAN(ddl_validate_checksum, "ddl task verify checksum")
|
||||
|
||||
// drop index task
|
||||
FLT_DEF_SPAN(ddl_drop_index, "ddl drop index task")
|
||||
FLT_DEF_SPAN(ddl_set_write_only, "set index to write only mode")
|
||||
FLT_DEF_SPAN(ddl_set_unusable, "set index to unusable state")
|
||||
FLT_DEF_SPAN(ddl_drop_schema, "drop index schema")
|
||||
|
||||
// drop primary key task
|
||||
FLT_DEF_SPAN(ddl_drop_primary_key, "ddl drop primary key task")
|
||||
|
||||
// table redefinition task
|
||||
FLT_DEF_SPAN(ddl_table_redefinition, "ddl table redefinition task")
|
||||
|
||||
// column redefinition task
|
||||
FLT_DEF_SPAN(ddl_column_redefinition, "ddl column redefinition task")
|
||||
|
||||
// ddl constraint task
|
||||
FLT_DEF_SPAN(ddl_constraint, "ddl constraint task")
|
||||
FLT_DEF_SPAN(ddl_check_constraint_valid, "check constraint valid")
|
||||
FLT_DEF_SPAN(ddl_set_constraint_valid, "set constraint valid")
|
||||
|
||||
// ddl modify autoinc
|
||||
FLT_DEF_SPAN(ddl_modify_autoinc_task, "ddl modify autoincrease column task")
|
||||
|
||||
// ddl retry task
|
||||
FLT_DEF_SPAN(ddl_retry_task, "ddl_ retry task")
|
||||
|
||||
#endif // __HIGH_LEVEL_SPAN
|
||||
|
||||
#ifdef __MIDDLE_LEVEL_SPAN
|
||||
@ -157,6 +201,19 @@ FLT_DEF_TAG(index_block_cache_hits, "index block cache hit count")
|
||||
FLT_DEF_TAG(sstable_read_cnt, "sstable count involved in the scan")
|
||||
FLT_DEF_TAG(rescan_read_cnt, "table scan iterator rescan count")
|
||||
|
||||
// ddl task
|
||||
FLT_DEF_TAG(ddl_task_id, "ddl task id")
|
||||
FLT_DEF_TAG(ddl_parent_task_id, "ddl parent task id")
|
||||
FLT_DEF_TAG(ddl_data_table_id, "data table id")
|
||||
FLT_DEF_TAG(ddl_index_table_id, "index table id")
|
||||
FLT_DEF_TAG(ddl_snapshot_version, "snapshot version")
|
||||
FLT_DEF_TAG(ddl_schema_version, "schema version")
|
||||
FLT_DEF_TAG(ddl_is_unique_index, "is unique index")
|
||||
FLT_DEF_TAG(ddl_is_global_index, "is global index")
|
||||
FLT_DEF_TAG(ddl_need_verify, "need verify")
|
||||
FLT_DEF_TAG(ddl_check_unique_snapshot, "check unique snapshot")
|
||||
FLT_DEF_TAG(ddl_ret_code, "return value")
|
||||
|
||||
// debug
|
||||
FLT_DEF_TAG(span_back_trace, "full link tracing debug")
|
||||
#endif // __HIGH_LEVEL_TAG
|
||||
|
2
deps/oblib/src/lib/utility/ob_tracepoint.h
vendored
2
deps/oblib/src/lib/utility/ob_tracepoint.h
vendored
@ -501,7 +501,7 @@ class EventTable
|
||||
EN_OPEN_REMOTE_ASYNC_EXECUTION = 244,
|
||||
EN_BACKUP_DELETE_EXCEPTION_HANDLING = 245,
|
||||
EN_SORT_IMPL_FORCE_DO_DUMP = 246,
|
||||
|
||||
EN_ENFORCE_PUSH_DOWN_WF = 247,
|
||||
//
|
||||
EN_TRANS_SHARED_LOCK_CONFLICT = 250,
|
||||
EN_HASH_JOIN_OPTION = 251,
|
||||
|
@ -295,7 +295,8 @@ WAIT_EVENT_DEF(DEADLOCK_DETECT_LOCK_WAIT, 15247, "spinlock: deadlock detect lock
|
||||
WAIT_EVENT_DEF(SRS_LOCK_WAIT, 15251, "latch: srs lock wait", "address", "number", "tries", CONCURRENCY, "latch: srs lock wait", true)
|
||||
WAIT_EVENT_DEF(CLOG_CKPT_RWLOCK_WAIT, 15252, "rwlock: clog checkpoint rwlock wait", "address", "number", "tries", CONCURRENCY, "rwlock: clog checkpoint rwlock wait", true)
|
||||
WAIT_EVENT_DEF(TENANT_IO_CONFIG_WAIT, 15253, "rwlock: tenant io config wait", "address", "number", "tries", CONCURRENCY, "rwlock: tenant io config wait", true)
|
||||
|
||||
WAIT_EVENT_DEF(SQL_WF_PARTICIPATOR_LOCK_WAIT, 15254, "latch: window function participator cond lock wait", "address", "", "", CONCURRENCY, "window function participator cond lock wait", true)
|
||||
WAIT_EVENT_DEF(SQL_WF_PARTICIPATOR_COND_WAIT, 15255, "mutex: window function participator cond wait", "address", "", "", CONCURRENCY, "window function participator cond wait", true)
|
||||
|
||||
//transaction
|
||||
WAIT_EVENT_DEF(END_TRANS_WAIT, 16001, "wait end trans", "rollback", "trans_hash_value", "participant_count", COMMIT,"wait end trans", false)
|
||||
|
1
deps/oblib/src/rpc/CMakeLists.txt
vendored
1
deps/oblib/src/rpc/CMakeLists.txt
vendored
@ -38,6 +38,7 @@ ob_set_subtarget(oblib_rpc obmysql
|
||||
obmysql/ob_sql_sock_session.cpp
|
||||
obmysql/ob_virtual_cs_protocol_processor.cpp
|
||||
obmysql/obp20_extra_info.cpp
|
||||
obmysql/ob_packet_record.cpp
|
||||
)
|
||||
|
||||
ob_set_subtarget(oblib_rpc obmysql_packet
|
||||
|
@ -346,13 +346,17 @@ int Ob20ProtocolProcessor::decode_new_extra_info(const Ob20ProtocolHeader &hdr,
|
||||
int Ob20ProtocolProcessor::do_splice(ObSMConnection& conn, ObICSMemPool& pool, void*& pkt, bool& need_decode_more)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
if (OB_FAIL(process_ob20_packet(conn.proto20_pkt_context_, conn.mysql_pkt_context_, pool, pkt, need_decode_more))) {
|
||||
if (OB_FAIL(process_ob20_packet(conn.proto20_pkt_context_, conn.mysql_pkt_context_,
|
||||
conn.pkt_rec_wrapper_, pool, pkt, need_decode_more))) {
|
||||
LOG_ERROR("fail to process_ob20_packet", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline int Ob20ProtocolProcessor::process_ob20_packet(ObProto20PktContext& context, ObMysqlPktContext &mysql_pkt_context, ObICSMemPool& pool,
|
||||
inline int Ob20ProtocolProcessor::process_ob20_packet(ObProto20PktContext& context,
|
||||
ObMysqlPktContext &mysql_pkt_context,
|
||||
obmysql::ObPacketRecordWrapper &pkt_rec_wrapper,
|
||||
ObICSMemPool& pool,
|
||||
void *&ipacket, bool &need_decode_more)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
@ -382,6 +386,9 @@ inline int Ob20ProtocolProcessor::process_ob20_packet(ObProto20PktContext& conte
|
||||
if (OB_SUCC(ret)) {
|
||||
uint32_t mysql_data_size = pkt20->get_mysql_packet_len();
|
||||
char *mysql_data_start = const_cast<char *>(pkt20->get_cdata());
|
||||
if (pkt_rec_wrapper.enable_proto_dia()) {
|
||||
pkt_rec_wrapper.record_recieve_mysql_pkt_fragment(mysql_data_size);
|
||||
}
|
||||
if (mysql_data_size == 0) {
|
||||
// waitting for a not empty packet
|
||||
need_decode_more = true;
|
||||
@ -413,6 +420,9 @@ inline int Ob20ProtocolProcessor::process_ob20_packet(ObProto20PktContext& conte
|
||||
// set again for sending response
|
||||
context.proto20_last_pkt_seq_ = pkt20->get_seq();
|
||||
context.proto20_last_request_id_ = pkt20->get_request_id();
|
||||
if (pkt_rec_wrapper.enable_proto_dia()) {
|
||||
pkt_rec_wrapper.record_recieve_obp20_packet(*pkt20, *input_packet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "rpc/obmysql/ob_mysql_protocol_processor.h"
|
||||
#include "rpc/obmysql/obp20_extra_info.h"
|
||||
#include "rpc/obmysql/ob_packet_record.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -47,7 +48,8 @@ private:
|
||||
const char*& payload_start,
|
||||
Ob20ExtraInfo &extra_info);
|
||||
int decode_ob20_body(ObICSMemPool& pool, const char*& buf, const Ob20ProtocolHeader &hdr, rpc::ObPacket *&pkt);
|
||||
int process_ob20_packet(ObProto20PktContext& context, ObMysqlPktContext &mysql_pkt_context, ObICSMemPool& pool,
|
||||
int process_ob20_packet(ObProto20PktContext& context, ObMysqlPktContext &mysql_pkt_context,
|
||||
obmysql::ObPacketRecordWrapper &pkt_rec_wrapper, ObICSMemPool& pool,
|
||||
void *&ipacket, bool &need_decode_more);
|
||||
Obp20Decoder* svr_decoders_[OBP20_SVR_END-OBP20_PROXY_MAX_TYPE] = {
|
||||
&trace_info_dcd_,
|
||||
|
@ -98,7 +98,11 @@ int ObProto20Utils::do_packet_encode(ObProtoEncodeParam ¶m) {
|
||||
ObEasyBuffer easy_buffer(*param.ez_buf_);
|
||||
|
||||
//SET_OB_LOG_TRACE_MODE(); // prevent printing log
|
||||
int32_t old_len = param.seri_size_;
|
||||
ret = param.pkt_->encode(easy_buffer.last(), easy_buffer.write_avail_size(), param.seri_size_);
|
||||
if (param.conn_->pkt_rec_wrapper_.enable_proto_dia()) {
|
||||
param.conn_->pkt_rec_wrapper_.record_send_mysql_pkt(*param.pkt_, param.seri_size_ - old_len);
|
||||
}
|
||||
//if (((OB_SIZE_OVERFLOW != ret) && (OB_BUF_NOT_ENOUGH != ret) && (common::OB_SUCCESS != ret))
|
||||
// || ((IS_LOG_ENABLED(INFO) && (OB_LOG_NEED_TO_PRINT(DEBUG))))) {
|
||||
// PRINT_OB_LOG_TRACE_BUF(INFO);
|
||||
@ -138,6 +142,9 @@ inline int ObProto20Utils::do_proto20_packet_encode(ObProtoEncodeParam ¶m)
|
||||
switch (proto20_context.next_step_) {
|
||||
case START_TO_FILL_STEP: {
|
||||
proto20_context.next_step_ = RESERVE_HEADER_STEP;
|
||||
if (param.conn_->pkt_rec_wrapper_.enable_proto_dia()) {
|
||||
param.conn_->pkt_rec_wrapper_.begin_seal_obp20_pkt();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RESERVE_HEADER_STEP: {
|
||||
@ -465,6 +472,9 @@ inline int ObProto20Utils::fill_proto20_payload(ObProtoEncodeParam ¶m, bool
|
||||
easy_buffer.write(seri_size);
|
||||
param.is_pkt_encoded_ = true;
|
||||
// noting break, wait to encode next one
|
||||
if (param.conn_->pkt_rec_wrapper_.enable_proto_dia()) {
|
||||
param.conn_->pkt_rec_wrapper_.record_send_mysql_pkt(*param.pkt_, seri_size);
|
||||
}
|
||||
need_break = true;
|
||||
} else if (split_count > 1) {
|
||||
if (OB_FAIL(param.save_large_packet(easy_buffer.last(), seri_size))) {
|
||||
@ -477,6 +487,10 @@ inline int ObProto20Utils::fill_proto20_payload(ObProtoEncodeParam ¶m, bool
|
||||
if (OB_FAIL(param.add_pos(ObProtoEncodeParam::PROTO20_SPLIT_LEN))) {
|
||||
LOG_ERROR("fail to add pos", K(ObProtoEncodeParam::PROTO20_SPLIT_LEN), K(ret));
|
||||
}
|
||||
if (param.conn_->pkt_rec_wrapper_.enable_proto_dia()) {
|
||||
param.conn_->pkt_rec_wrapper_.record_send_mysql_pkt(*param.pkt_,
|
||||
ObProtoEncodeParam::PROTO20_SPLIT_LEN);
|
||||
}
|
||||
}
|
||||
proto20_context.next_step_ = FILL_TAILER_STEP;
|
||||
}
|
||||
@ -559,12 +573,9 @@ inline int ObProto20Utils::fill_proto20_header(ObProtoEncodeParam ¶m) {
|
||||
uint16_t header_checksum = 0;
|
||||
int64_t pos = 0;
|
||||
char *start = easy_buffer.begin();
|
||||
observer::ObSMConnection *conn = NULL;
|
||||
if (OB_ISNULL(param.req_)) {
|
||||
LOG_ERROR("request is null");
|
||||
} else if (FALSE_IT(conn = reinterpret_cast<observer::ObSMConnection *>(
|
||||
SQL_REQ_OP.get_sql_session(param.req_)))) {
|
||||
} else if (FALSE_IT(packet_seq = conn->proto20_pkt_context_.proto20_last_pkt_seq_ + 1)) {
|
||||
} else if (FALSE_IT(packet_seq = param.conn_->proto20_pkt_context_.proto20_last_pkt_seq_ + 1)) {
|
||||
} else if (OB_UNLIKELY(compress_len > OB_MYSQL_MAX_PAYLOAD_LENGTH)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_ERROR("invalid compress_len", K(compress_len), K(OB_MYSQL_MAX_PAYLOAD_LENGTH), K(ret));
|
||||
@ -591,8 +602,12 @@ inline int ObProto20Utils::fill_proto20_header(ObProtoEncodeParam ¶m) {
|
||||
} else if (OB_FAIL(ObMySQLUtil::store_int2(start, proto20_context.header_len_, reserved, pos))) {
|
||||
LOG_ERROR("fail to store int2", K(ret));
|
||||
} else {
|
||||
++conn->proto20_pkt_context_.proto20_last_pkt_seq_;
|
||||
++param.conn_->proto20_pkt_context_.proto20_last_pkt_seq_;
|
||||
// calc header checksum
|
||||
if (param.conn_->pkt_rec_wrapper_.enable_proto_dia()) {
|
||||
param.conn_->pkt_rec_wrapper_.end_seal_obp20_pkt((uint32_t)(payload_len), flag, packet_seq, 0,
|
||||
request_id, compress_len, compress_seq);
|
||||
}
|
||||
if (!proto20_context.is_checksum_off_) {
|
||||
header_checksum = ob_crc16(0, reinterpret_cast<uint8_t *>(start), pos);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "rpc/obmysql/ob_mysql_packet.h"
|
||||
#include "rpc/ob_request.h"
|
||||
#include "rpc/obmysql/obp20_extra_info.h"
|
||||
#include "rpc/obmysql/obsm_struct.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -118,6 +119,7 @@ public:
|
||||
int64_t large_pkt_buf_pos_;
|
||||
common::ObIArray<ObObjKV> *extra_info_kvs_;
|
||||
common::ObIArray<Obp20Encoder*> *extra_info_ecds_;
|
||||
observer::ObSMConnection* conn_;
|
||||
|
||||
const static int64_t MAX_PROTO20_PAYLOAD_LEN;
|
||||
const static int64_t PROTO20_SPLIT_LEN;
|
||||
@ -128,11 +130,11 @@ public:
|
||||
seri_size_(0), conn_id_(0), encode_ret_(common::OB_SUCCESS),
|
||||
need_flush_(false), is_last_(false), is_pkt_encoded_(false),
|
||||
large_pkt_buf_(NULL), large_pkt_buf_len_(0), large_pkt_buf_pos_(0),
|
||||
extra_info_kvs_(NULL), extra_info_ecds_(NULL)
|
||||
extra_info_kvs_(NULL), extra_info_ecds_(NULL), conn_(NULL)
|
||||
{}
|
||||
|
||||
inline bool is_valid() const
|
||||
{ return (NULL != proto20_context_) && (NULL != ez_buf_) && (NULL != req_); }
|
||||
{ return (NULL != proto20_context_) && (NULL != ez_buf_) && (NULL != req_) && (NULL != conn_); }
|
||||
|
||||
inline static void build_param(ObProtoEncodeParam ¶m, ObMySQLPacket *pkt,
|
||||
easy_buf_t &ez_buf, const uint32_t sessid, const bool is_last,
|
||||
@ -148,6 +150,10 @@ public:
|
||||
param.req_ = req;
|
||||
param.extra_info_kvs_ = extra_info;
|
||||
param.extra_info_ecds_ = extra_info_ecds;
|
||||
if (NULL != param.req_) {
|
||||
param.conn_ = reinterpret_cast<observer::ObSMConnection *>
|
||||
(SQL_REQ_OP.get_sql_session(param.req_));
|
||||
}
|
||||
}
|
||||
|
||||
inline int add_pos(const int64_t delta);
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "rpc/obmysql/ob_mysql_request_utils.h"
|
||||
#include "lib/compress/zlib/ob_zlib_compressor.h"
|
||||
#include "rpc/obmysql/obsm_struct.h"
|
||||
#include "rpc/obmysql/ob_packet_record.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -77,7 +78,8 @@ int ObMysqlCompressProtocolProcessor::do_decode(ObSMConnection& conn, ObICSMemPo
|
||||
int ObMysqlCompressProtocolProcessor::do_splice(observer::ObSMConnection& conn, ObICSMemPool& pool, void*& pkt, bool& need_decode_more)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
if (OB_FAIL(process_compressed_packet(conn.compressed_pkt_context_, conn.mysql_pkt_context_, pool, pkt, need_decode_more))) {
|
||||
if (OB_FAIL(process_compressed_packet(conn.compressed_pkt_context_, conn.mysql_pkt_context_,
|
||||
conn.pkt_rec_wrapper_, pool, pkt, need_decode_more))) {
|
||||
LOG_ERROR("fail to process_compressed_packet", K(ret));
|
||||
}
|
||||
return ret;
|
||||
@ -143,7 +145,8 @@ inline int ObMysqlCompressProtocolProcessor::decode_compressed_packet(
|
||||
}
|
||||
|
||||
inline int ObMysqlCompressProtocolProcessor::process_compressed_packet(
|
||||
ObCompressedPktContext& context, ObMysqlPktContext &mysql_pkt_context, ObICSMemPool& pool,
|
||||
ObCompressedPktContext& context, ObMysqlPktContext &mysql_pkt_context,
|
||||
obmysql::ObPacketRecordWrapper &pkt_rec_wrapper, ObICSMemPool& pool,
|
||||
void *&ipacket, bool &need_decode_more)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -163,7 +166,9 @@ inline int ObMysqlCompressProtocolProcessor::process_compressed_packet(
|
||||
? iraw_pkt->get_comp_len()
|
||||
: iraw_pkt->get_uncomp_len());
|
||||
int64_t alloc_size = static_cast<int64_t>(decompress_data_size);
|
||||
|
||||
if (pkt_rec_wrapper.enable_proto_dia()) {
|
||||
pkt_rec_wrapper.record_recieve_mysql_pkt_fragment(iraw_pkt->get_comp_len());
|
||||
}
|
||||
//in order to reuse optimize memory, we put decompressed data into raw_pkt directly
|
||||
char *tmp_buffer = NULL;
|
||||
if (OB_ISNULL(tmp_buffer = reinterpret_cast<char *>(pool.alloc(alloc_size)))) {
|
||||
@ -184,6 +189,15 @@ inline int ObMysqlCompressProtocolProcessor::process_compressed_packet(
|
||||
if (need_decode_more) {
|
||||
context.is_multi_pkt_ = true;
|
||||
} else {
|
||||
if (pkt_rec_wrapper.enable_proto_dia()) {
|
||||
ObMySQLRawPacket *raw_pkt = NULL;
|
||||
if (OB_ISNULL(raw_pkt = reinterpret_cast<ObMySQLRawPacket *>(ipacket))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_ERROR("ipacket is null", K(ret));
|
||||
} else {
|
||||
pkt_rec_wrapper.record_recieve_comp_packet(*iraw_pkt, *raw_pkt);
|
||||
}
|
||||
}
|
||||
context.reset();
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ private:
|
||||
const uint32_t pktlen_before_compress, char *&pkt_body,
|
||||
const uint32_t pkt_body_size);
|
||||
|
||||
int process_compressed_packet(ObCompressedPktContext& context, ObMysqlPktContext &mysql_pkt_context, ObICSMemPool& pool,
|
||||
int process_compressed_packet(ObCompressedPktContext& context, ObMysqlPktContext &mysql_pkt_context,
|
||||
obmysql::ObPacketRecordWrapper &pkt_rec_wrapper, ObICSMemPool& pool,
|
||||
void *&ipacket, bool &need_decode_more);
|
||||
|
||||
private:
|
||||
|
19
deps/oblib/src/rpc/obmysql/ob_mysql_packet.h
vendored
19
deps/oblib/src/rpc/obmysql/ob_mysql_packet.h
vendored
@ -91,6 +91,23 @@ enum ObMySQLCmd
|
||||
COM_MAX_NUM
|
||||
};
|
||||
|
||||
enum class ObMySQLPacketType
|
||||
{
|
||||
INVALID_PKT = 0,
|
||||
PKT_MYSQL, // 1 -> mysql packet;
|
||||
PKT_OKP, // 2 -> okp;
|
||||
PKT_ERR, // 3 -> error packet;
|
||||
PKT_EOF, // 4 -> eof packet;
|
||||
PKT_ROW, // 5 -> row packet;
|
||||
PKT_FIELD, // 6 -> field packet;
|
||||
PKT_PIECE, // 7 -> piece packet;
|
||||
PKT_STR, // 8 -> string packet;
|
||||
PKT_PREPARE, // 9 -> prepare packet;
|
||||
PKT_RESHEAD, // 10 -> result header packet
|
||||
PKT_PREXEC, // 11 -> prepare execute packet;
|
||||
PKT_END // 12 -> end of packet type
|
||||
};
|
||||
|
||||
union ObServerStatusFlags
|
||||
{
|
||||
ObServerStatusFlags() : flags_(0) {}
|
||||
@ -411,7 +428,9 @@ public:
|
||||
virtual int64_t get_serialize_size() const;
|
||||
int encode(char *buffer, int64_t length, int64_t &pos, int64_t &pkt_count) const;
|
||||
int encode(char *buffer, int64_t length, int64_t &pos);
|
||||
int get_pkt_len() { return hdr_.len_; }
|
||||
virtual int decode() { return common::OB_NOT_SUPPORTED; }
|
||||
virtual ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::INVALID_PKT; }
|
||||
|
||||
virtual void reset()
|
||||
{
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "rpc/obmysql/packet/ompk_ssl_request.h"
|
||||
#include "rpc/obmysql/ob_mysql_request_utils.h"
|
||||
#include "rpc/obmysql/obsm_struct.h"
|
||||
#include "rpc/obmysql/ob_packet_record.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -113,7 +114,10 @@ int ObMysqlProtocolProcessor::do_decode(ObSMConnection& conn, ObICSMemPool& pool
|
||||
int ObMysqlProtocolProcessor::do_splice(ObSMConnection& conn, ObICSMemPool& pool, void*& pkt, bool& need_decode_more)
|
||||
{
|
||||
INIT_SUCC(ret);
|
||||
if (OB_FAIL(process_mysql_packet(conn.mysql_pkt_context_, pool, pkt, need_decode_more))) {
|
||||
__builtin_prefetch(&conn.pkt_rec_wrapper_.pkt_rec_[conn.pkt_rec_wrapper_.cur_pkt_pos_
|
||||
% ObPacketRecordWrapper::REC_BUF_SIZE]);
|
||||
if (OB_FAIL(process_mysql_packet(conn.mysql_pkt_context_, &conn.pkt_rec_wrapper_,
|
||||
pool, pkt, need_decode_more))) {
|
||||
LOG_ERROR("fail to process_mysql_packet", K(ret));
|
||||
}
|
||||
return ret;
|
||||
@ -276,7 +280,8 @@ int ObMysqlProtocolProcessor::read_body(
|
||||
context.raw_pkt_.set_content(start + pos, static_cast<uint32_t>(context.payload_len_));
|
||||
const int64_t actual_data_len = handle_len;
|
||||
void *tmp_ipacket = reinterpret_cast<void *>(&context.raw_pkt_);
|
||||
if (OB_FAIL(process_one_mysql_packet(context, pool, actual_data_len, tmp_ipacket, need_decode_more))) {
|
||||
if (OB_FAIL(process_one_mysql_packet(context, NULL, pool, actual_data_len,
|
||||
tmp_ipacket, need_decode_more))) {
|
||||
LOG_ERROR("fail to process one mysql packet", K(context), K(ret));
|
||||
} else {
|
||||
if (need_decode_more) { // mysql packet not received complete
|
||||
@ -410,6 +415,7 @@ int ObMysqlProtocolProcessor::process_fragment_mysql_packet(
|
||||
|
||||
int ObMysqlProtocolProcessor::process_one_mysql_packet(
|
||||
ObMysqlPktContext &context,
|
||||
obmysql::ObPacketRecordWrapper *pkt_rec_wrapper,
|
||||
ObICSMemPool& pool,
|
||||
const int64_t actual_data_len,
|
||||
void *&ipacket,
|
||||
@ -468,6 +474,9 @@ int ObMysqlProtocolProcessor::process_one_mysql_packet(
|
||||
// no need set seq again
|
||||
need_decode_more = false;
|
||||
ipacket = raw_pkt;
|
||||
if (OB_NOT_NULL(pkt_rec_wrapper) && pkt_rec_wrapper->enable_proto_dia()) {
|
||||
pkt_rec_wrapper->record_recieve_mysql_packet(*raw_pkt);
|
||||
}
|
||||
LOG_DEBUG("recevie one mysql packet complete", K(context), KPC(raw_pkt),
|
||||
K(total_data_len), K(actual_data_len));
|
||||
}
|
||||
@ -489,6 +498,7 @@ int ObMysqlProtocolProcessor::process_one_mysql_packet(
|
||||
|
||||
int ObMysqlProtocolProcessor::process_mysql_packet(
|
||||
ObMysqlPktContext &context,
|
||||
obmysql::ObPacketRecordWrapper *pkt_rec_wrapper,
|
||||
ObICSMemPool& pool,
|
||||
void *&ipacket,
|
||||
bool &need_decode_more) {
|
||||
@ -501,9 +511,13 @@ int ObMysqlProtocolProcessor::process_mysql_packet(
|
||||
} else {
|
||||
int64_t data_len = raw_pkt->get_clen();
|
||||
const char *payload = raw_pkt->get_cdata();
|
||||
if (OB_NOT_NULL(pkt_rec_wrapper) && pkt_rec_wrapper->enable_proto_dia()) {
|
||||
pkt_rec_wrapper->record_recieve_mysql_pkt_fragment(raw_pkt->get_clen());
|
||||
}
|
||||
if (FALSE_IT(context.payload_len_ = data_len)) {
|
||||
// impossible
|
||||
} else if (OB_FAIL(process_one_mysql_packet(context, pool, data_len, ipacket, need_decode_more))) {
|
||||
} else if (OB_FAIL(process_one_mysql_packet(context, pkt_rec_wrapper,
|
||||
pool, data_len, ipacket, need_decode_more))) {
|
||||
LOG_ERROR("fail to process one mysql packet", K(context), K(need_decode_more), K(ret));
|
||||
} else {
|
||||
if (need_decode_more) {
|
||||
@ -520,6 +534,7 @@ int ObMysqlProtocolProcessor::process_mysql_packet(
|
||||
context.payload_len_ = 0;
|
||||
}
|
||||
} else {
|
||||
|
||||
// nothing
|
||||
context.reset();
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "lib/ob_define.h"
|
||||
#include "rpc/obmysql/ob_mysql_packet.h"
|
||||
#include "rpc/obmysql/ob_virtual_cs_protocol_processor.h"
|
||||
#include "rpc/obmysql/ob_packet_record.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -57,9 +58,12 @@ private:
|
||||
void *&ipacket, bool &need_decode_more, int64_t &pos);
|
||||
|
||||
int process_mysql_packet(ObMysqlPktContext &context,
|
||||
obmysql::ObPacketRecordWrapper *pkt_rec_wrapper,
|
||||
ObICSMemPool& pool,
|
||||
void *&ipacket, bool &need_decode_more);
|
||||
int process_one_mysql_packet(ObMysqlPktContext &context, ObICSMemPool& pool,
|
||||
int process_one_mysql_packet(ObMysqlPktContext &context,
|
||||
obmysql::ObPacketRecordWrapper *pkt_rec_wrapper,
|
||||
ObICSMemPool& pool,
|
||||
const int64_t actual_data_len, void *&ipacket,
|
||||
bool &need_decode_more);
|
||||
protected:
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "rpc/ob_request.h"
|
||||
#include "rpc/obmysql/ob_mysql_util.h"
|
||||
#include "rpc/obmysql/ob_mysql_packet.h"
|
||||
#include "rpc/obmysql/ob_packet_record.h"
|
||||
#include "rpc/obmysql/obsm_struct.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
|
||||
@ -70,6 +72,9 @@ static int build_compressed_packet(ObEasyBuffer &src_buf,
|
||||
if (OB_ISNULL(context.send_buf_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
SERVER_LOG(WARN, "send_buf_ is null", K(context), K(ret));
|
||||
} else if (OB_ISNULL(context.conn_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
SERVER_LOG(WARN, "conn_ is null", K(context), K(ret));
|
||||
} else {
|
||||
ObEasyBuffer dst_buf(*context.send_buf_);
|
||||
const int64_t comp_buf_size = dst_buf.write_avail_size() - OB_MYSQL_COMPRESSED_HEADER_SIZE;
|
||||
@ -111,6 +116,10 @@ static int build_compressed_packet(ObEasyBuffer &src_buf,
|
||||
static_cast<int32_t>(len_before_compress), pos))) {
|
||||
SERVER_LOG(WARN, "failed to store_int3", K(ret));
|
||||
} else {
|
||||
if (context.conn_->pkt_rec_wrapper_.enable_proto_dia()) {
|
||||
context.conn_->pkt_rec_wrapper_.end_seal_comp_pkt(
|
||||
static_cast<uint32_t>(dst_data_size), context.seq_);
|
||||
}
|
||||
SERVER_LOG(DEBUG, "succ to build compressed pkt", "comp_len", dst_data_size,
|
||||
"comp_seq", context.seq_, K(len_before_compress), K(next_compress_size),
|
||||
K(src_buf), K(dst_buf), K(context));
|
||||
|
@ -29,6 +29,10 @@ namespace rpc
|
||||
{
|
||||
class ObRequest;
|
||||
}
|
||||
namespace observer
|
||||
{
|
||||
class ObSMConnection;
|
||||
}
|
||||
|
||||
namespace obmysql
|
||||
{
|
||||
@ -281,6 +285,7 @@ public:
|
||||
easy_buf_t *send_buf_;
|
||||
char *last_pkt_pos_;//proxy last pkt(error+ok, eof+ok, ok)'s pos in orig_ezbuf, default is null
|
||||
uint32_t sessid_;
|
||||
observer::ObSMConnection *conn_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObCompressionContext);
|
||||
|
124
deps/oblib/src/rpc/obmysql/ob_packet_record.cpp
vendored
Normal file
124
deps/oblib/src/rpc/obmysql/ob_packet_record.cpp
vendored
Normal file
@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE 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.
|
||||
*/
|
||||
|
||||
#define USING_LOG_PREFIX RPC_OBMYSQL
|
||||
|
||||
#include "rpc/obmysql/ob_packet_record.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
using namespace oceanbase::obmysql;
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace observer{
|
||||
bool __attribute__((weak)) enable_proto_dia()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
namespace obmysql
|
||||
{
|
||||
static const char* pkt_type_name[13] =
|
||||
{
|
||||
"INVALID_PKT",
|
||||
"PKT_MYSQL", // 1 -> mysql packet;
|
||||
"PKT_OKP", // 2 -> okp;
|
||||
"PKT_ERR", // 3 -> error packet;
|
||||
"PKT_EOF", // 4 -> eof packet;
|
||||
"PKT_ROW", // 5 -> row packet;
|
||||
"PKT_FIELD", // 6 -> field packet;
|
||||
"PKT_PIECE", // 7 -> piece packet;
|
||||
"PKT_STR", // 8 -> string packet;
|
||||
"PKT_PREPARE", // 9 -> prepare packet;
|
||||
"PKT_RESHEAD", // 10 -> result header packet
|
||||
"PKT_PREXEC", // 11 -> prepare execute packet;
|
||||
"PKT_END" // 12 -> end of packet type
|
||||
};
|
||||
|
||||
int64_t ObPacketRecord::to_string(char *buf, const int64_t buf_len) const
|
||||
{
|
||||
int64_t pos = 0;
|
||||
J_OBJ_START();
|
||||
if (is_send_record()) {
|
||||
databuff_printf(buf, buf_len, pos, "send:");
|
||||
if (obp_mysql_header_.is_com_pkt_valid()) {
|
||||
databuff_printf(buf, buf_len, pos, "obp_compess_header_");
|
||||
J_OBJ_START();
|
||||
J_KV("com_len", obp_mysql_header_.com_len_, "com_seq", obp_mysql_header_.com_seq_);
|
||||
J_OBJ_END();
|
||||
J_COMMA();
|
||||
}
|
||||
if (obp20_header_.is_valid()) {
|
||||
J_KV(K(obp20_header_));
|
||||
J_COMMA();
|
||||
}
|
||||
databuff_printf(buf, buf_len, pos, "obp_mysql_header_");
|
||||
J_OBJ_START();
|
||||
if (obp_mysql_header_.type_ == static_cast<uint8_t>(ObMySQLPacketType::PKT_ROW)
|
||||
|| obp_mysql_header_.type_ == static_cast<uint8_t>(ObMySQLPacketType::PKT_FIELD)) {
|
||||
J_KV("pkt_num_", obp_mysql_header_.mysql_header_.pkt_num_,"seq_", obp_mysql_header_.seq_);
|
||||
} else {
|
||||
J_KV("len_", obp_mysql_header_.mysql_header_.len_, "seq_", obp_mysql_header_.seq_);
|
||||
}
|
||||
J_OBJ_END();
|
||||
J_COMMA();
|
||||
J_KV("pkt_name", pkt_type_name[obp_mysql_header_.type_], K(obp_mysql_header_.is_send_));
|
||||
} else {
|
||||
databuff_printf(buf, buf_len, pos, "receive:");
|
||||
if (obp_mysql_header_.is_com_pkt_valid()) {
|
||||
databuff_printf(buf, buf_len, pos, "obp_compess_header_");
|
||||
J_OBJ_START();
|
||||
J_KV("com_len", obp_mysql_header_.com_len_, "com_seq", obp_mysql_header_.com_seq_);
|
||||
J_OBJ_END();
|
||||
J_COMMA();
|
||||
}
|
||||
if (obp20_header_.is_valid()) {
|
||||
J_KV(K(obp20_header_));
|
||||
J_COMMA();
|
||||
}
|
||||
databuff_printf(buf, buf_len, pos, "obp_mysql_header_");
|
||||
J_OBJ_START();
|
||||
J_KV("len_", obp_mysql_header_.mysql_header_.len_,
|
||||
"rec_", obp_mysql_header_.rec_, "seq_", obp_mysql_header_.seq_);
|
||||
J_OBJ_END();
|
||||
J_COMMA();
|
||||
J_KV(K(obp_mysql_header_.type_), K(obp_mysql_header_.is_send_));
|
||||
}
|
||||
J_OBJ_END();
|
||||
return pos;
|
||||
}
|
||||
|
||||
int64_t ObPacketRecordWrapper::to_string(char *buf, int64_t buf_len) const
|
||||
{
|
||||
int64_t pos = 0;
|
||||
J_ARRAY_START();
|
||||
J_KV(K(start_pkt_pos_), K(cur_pkt_pos_));
|
||||
if (cur_pkt_pos_ > 0) {
|
||||
J_COMMA();
|
||||
}
|
||||
int64_t start = 0;
|
||||
if (cur_pkt_pos_-REC_BUF_SIZE > 0) {
|
||||
start = cur_pkt_pos_-REC_BUF_SIZE;
|
||||
}
|
||||
for (int64_t index = start; (index < cur_pkt_pos_); index++) {
|
||||
databuff_printf(buf, buf_len, pos, "pkt_rec[%ld]:", index);
|
||||
BUF_PRINTO(pkt_rec_[index % REC_BUF_SIZE]);
|
||||
if (index != cur_pkt_pos_-1) {
|
||||
J_COMMA();
|
||||
}
|
||||
}
|
||||
J_ARRAY_END();
|
||||
return pos;
|
||||
}
|
||||
|
||||
} // end of namespace obmysql
|
||||
} // end of namespace oceanbase
|
284
deps/oblib/src/rpc/obmysql/ob_packet_record.h
vendored
Normal file
284
deps/oblib/src/rpc/obmysql/ob_packet_record.h
vendored
Normal file
@ -0,0 +1,284 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE 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_MYSQL_OB_PACKET_RECORD_H_
|
||||
#define _OB_MYSQL_OB_PACKET_RECORD_H_
|
||||
#include "rpc/obmysql/ob_mysql_packet.h"
|
||||
#include "rpc/obmysql/ob_2_0_protocol_struct.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace observer{
|
||||
bool __attribute__((weak)) enable_proto_dia();
|
||||
}
|
||||
namespace obmysql
|
||||
{
|
||||
|
||||
struct ResRecordFlags {
|
||||
uint8_t is_send_: 1; // 0-send, 1-receive
|
||||
uint8_t processed_: 1; // 请求处理结束,发送包后将会标记该位。
|
||||
uint8_t reservered_: 8; // 其余位用于特殊标记
|
||||
};
|
||||
|
||||
struct Obp20Header {
|
||||
uint32_t payload_len_; // 4byte
|
||||
Ob20ProtocolFlags flag_; // 4byte
|
||||
int32_t req_id_; // 4byte
|
||||
uint8_t pkt_seq_; // 1byte
|
||||
uint16_t ext_flags_; // 2byte
|
||||
Obp20Header() {
|
||||
payload_len_ = 0;
|
||||
flag_.flags_ = 0;
|
||||
pkt_seq_ = 0;
|
||||
ext_flags_ = 0;
|
||||
req_id_ = 0;
|
||||
}
|
||||
bool is_valid() const {
|
||||
return req_id_ != 0;
|
||||
}
|
||||
~Obp20Header() {}
|
||||
TO_STRING_KV(K_(payload_len), K_(pkt_seq), K_(req_id), K_(flag_.flags), K_(ext_flags));
|
||||
};//12byte
|
||||
|
||||
|
||||
/*
|
||||
// for send packet
|
||||
// 0-> mysql packet; 1->okp;
|
||||
// 2->error packet; 3->eof packet
|
||||
// 4-> row packet; 5-> field packet;
|
||||
// 6->piece packet; 7-> string packet;
|
||||
// 8-> prepare packet; 9 ->result header packet
|
||||
// 10-> prepare execute packet;
|
||||
|
||||
// for recieve packet
|
||||
this field represents packet command
|
||||
*/
|
||||
struct ObpMysqHeader {
|
||||
union {
|
||||
uint32_t len_;
|
||||
uint32_t pkt_num_; // 表示row packet/feild packet的数量。
|
||||
} mysql_header_;
|
||||
uint32_t rec_; // 表示目前收到多少byte的mysql包。
|
||||
uint32_t com_len_; // compress head len
|
||||
uint8_t seq_;
|
||||
uint8_t type_;
|
||||
uint8_t com_seq_; // compress head sequence
|
||||
uint8_t is_send_;
|
||||
ObpMysqHeader() {
|
||||
rec_ = 0;
|
||||
seq_ = 0;
|
||||
mysql_header_.len_ = 0;
|
||||
}
|
||||
~ObpMysqHeader() {}
|
||||
|
||||
bool is_com_pkt_valid() const {
|
||||
return com_len_ != 0 && com_seq_ != 0;
|
||||
}
|
||||
TO_STRING_KV(K_(mysql_header_.len), K_(rec), K_(seq));
|
||||
}; // 16byte
|
||||
|
||||
class ObPacketRecord
|
||||
{
|
||||
public:
|
||||
ObPacketRecord() {
|
||||
obp_mysql_header_.type_ = 0;
|
||||
obp_mysql_header_.is_send_ = 0;
|
||||
}
|
||||
~ObPacketRecord() {}
|
||||
|
||||
//for mysql fragment
|
||||
inline void record_recieve_mysql_pkt_fragment(int32_t rec) __restrict__ {
|
||||
obp_mysql_header_.rec_ += rec;
|
||||
}
|
||||
//for mysql fragment end
|
||||
|
||||
// for mysql protocol
|
||||
inline void record_recieve_mysql_packet(ObMySQLRawPacket &__restrict__ pkt) __restrict__
|
||||
{
|
||||
obp_mysql_header_.mysql_header_.len_ = pkt.get_pkt_len();
|
||||
obp_mysql_header_.seq_ = pkt.get_seq();
|
||||
obp_mysql_header_.type_ = static_cast<uint8_t>(pkt.get_cmd());
|
||||
obp_mysql_header_.is_send_ = 0;
|
||||
}
|
||||
inline void record_send_mysql_packet(ObMySQLPacket &__restrict__ pkt, int32_t len) __restrict__
|
||||
{
|
||||
if (pkt.get_mysql_packet_type() == ObMySQLPacketType::PKT_ROW ||
|
||||
pkt.get_mysql_packet_type() == ObMySQLPacketType::PKT_FIELD) {
|
||||
obp_mysql_header_.mysql_header_.pkt_num_++;
|
||||
} else {
|
||||
obp_mysql_header_.mysql_header_.len_ = len;
|
||||
}
|
||||
obp_mysql_header_.seq_ = pkt.get_seq();
|
||||
obp_mysql_header_.type_ = static_cast<uint8_t>(pkt.get_mysql_packet_type());
|
||||
obp_mysql_header_.is_send_ = 1;
|
||||
}
|
||||
// for mysql protocol end
|
||||
|
||||
// for ob20 protocol
|
||||
inline void record_send_obp20_packet(uint32_t payload_len, Ob20ProtocolFlags flag,
|
||||
uint8_t pkt_seq, uint16_t ext_flags,
|
||||
int32_t req_id, uint32_t com_len, uint8_t com_seq)
|
||||
{
|
||||
obp20_header_.payload_len_ = payload_len;
|
||||
obp20_header_.flag_ = flag;
|
||||
obp20_header_.pkt_seq_ = pkt_seq;
|
||||
obp20_header_.req_id_ = req_id;
|
||||
obp20_header_.ext_flags_ = ext_flags;
|
||||
obp_mysql_header_.com_len_ = com_len;
|
||||
obp_mysql_header_.com_seq_ = com_seq;
|
||||
}
|
||||
inline void record_recieve_obp20_packet(Ob20Packet& obp20_pkt)
|
||||
{
|
||||
obp20_header_.payload_len_ = obp20_pkt.get_payload_len();
|
||||
obp20_header_.flag_ = obp20_pkt.get_flags();
|
||||
obp20_header_.pkt_seq_ = obp20_pkt.get_seq();
|
||||
obp20_header_.req_id_ = obp20_pkt.get_request_id();
|
||||
obp20_header_.ext_flags_ = 0;
|
||||
obp_mysql_header_.com_len_ = obp20_pkt.get_comp_len();
|
||||
obp_mysql_header_.com_seq_ = obp20_pkt.get_comp_seq();
|
||||
}
|
||||
// for ob20 protocol end
|
||||
|
||||
|
||||
// for compress mysql protocol
|
||||
inline void record_send_comp_packet(uint32_t com_len, uint8_t com_seq) __restrict__ {
|
||||
obp_mysql_header_.com_len_ = com_len;
|
||||
obp_mysql_header_.com_seq_ = com_seq;
|
||||
}
|
||||
inline void record_recieve_comp_packet(ObMySQLCompressedPacket &com_pkt) __restrict__ {
|
||||
obp_mysql_header_.com_len_ = com_pkt.get_comp_len();
|
||||
obp_mysql_header_.com_seq_ = com_pkt.get_comp_seq();
|
||||
}
|
||||
// for compress mysql protocol end
|
||||
|
||||
inline bool is_send_record() const __restrict__ {
|
||||
return obp_mysql_header_.is_send_ == 1;
|
||||
}
|
||||
|
||||
inline void set_packet_type(ObMySQLPacketType type) __restrict__ {
|
||||
obp_mysql_header_.type_ = static_cast<uint8_t>(type);
|
||||
}
|
||||
|
||||
int64_t to_string(char *buf, const int64_t buf_len) const;
|
||||
Obp20Header obp20_header_; // 16 byte
|
||||
ObpMysqHeader obp_mysql_header_; // 16 byte
|
||||
|
||||
}__attribute((aligned(32)));; // end of class ObPacketRecord
|
||||
|
||||
class ObPacketRecordWrapper {
|
||||
public:
|
||||
static const int64_t REC_BUF_SIZE = 32;
|
||||
ObPacketRecordWrapper() {
|
||||
start_pkt_pos_ = 0;
|
||||
cur_pkt_pos_ = 0;
|
||||
last_type_ = obmysql::ObMySQLPacketType::INVALID_PKT;
|
||||
enable_proto_dia_ = false;
|
||||
}
|
||||
~ObPacketRecordWrapper() {}
|
||||
void init() {
|
||||
start_pkt_pos_ = 0;
|
||||
cur_pkt_pos_ = 0;
|
||||
last_type_ = obmysql::ObMySQLPacketType::INVALID_PKT;
|
||||
enable_proto_dia_ = observer::enable_proto_dia();
|
||||
}
|
||||
int64_t to_string(char *buf, int64_t buf_len) const;
|
||||
|
||||
// for 20 protocol
|
||||
inline void begin_seal_obp20_pkt() { start_pkt_pos_ = cur_pkt_pos_; }
|
||||
inline void end_seal_obp20_pkt(uint32_t payload_len, obmysql::Ob20ProtocolFlags flag,
|
||||
uint8_t pkt_seq, uint16_t ext_flags, int32_t req_id,
|
||||
uint32_t com_len, uint8_t com_seq)
|
||||
{
|
||||
for (int64_t i = start_pkt_pos_; i < cur_pkt_pos_; i++) {
|
||||
int64_t idx = i % ObPacketRecordWrapper::REC_BUF_SIZE;
|
||||
obmysql::ObPacketRecord& rec = pkt_rec_[idx];
|
||||
rec.record_send_obp20_packet(payload_len, flag, pkt_seq,
|
||||
ext_flags, req_id, com_len, com_seq);
|
||||
}
|
||||
}
|
||||
|
||||
inline void record_recieve_obp20_packet(Ob20Packet &obp20_pkt,
|
||||
obmysql::ObMySQLRawPacket &pkt)
|
||||
{
|
||||
int64_t idx = cur_pkt_pos_ % ObPacketRecordWrapper::REC_BUF_SIZE;
|
||||
obmysql::ObPacketRecord& rec = pkt_rec_[idx];
|
||||
rec.record_recieve_obp20_packet(obp20_pkt);
|
||||
rec.record_recieve_mysql_packet(pkt);
|
||||
cur_pkt_pos_++;
|
||||
}
|
||||
// for 20 protocol end
|
||||
|
||||
|
||||
// for compress protocol
|
||||
inline void begin_seal_comp_pkt() { start_pkt_pos_ = cur_pkt_pos_; }
|
||||
inline void end_seal_comp_pkt(uint32_t com_len, uint8_t com_seq)
|
||||
{
|
||||
for (int64_t i = start_pkt_pos_; i < cur_pkt_pos_; i++) {
|
||||
int64_t idx = i % ObPacketRecordWrapper::REC_BUF_SIZE;
|
||||
obmysql::ObPacketRecord& rec = pkt_rec_[idx];
|
||||
rec.record_send_comp_packet(com_len, com_seq);
|
||||
}
|
||||
}
|
||||
void record_recieve_comp_packet(ObMySQLCompressedPacket &com_pkt,
|
||||
obmysql::ObMySQLRawPacket &pkt)
|
||||
{
|
||||
int64_t idx = cur_pkt_pos_ % ObPacketRecordWrapper::REC_BUF_SIZE;
|
||||
obmysql::ObPacketRecord& rec = pkt_rec_[idx];
|
||||
rec.record_recieve_comp_packet(com_pkt);
|
||||
rec.record_recieve_mysql_packet(pkt);
|
||||
cur_pkt_pos_++;
|
||||
}
|
||||
// for compress protocol end
|
||||
|
||||
|
||||
// for mysql protocol
|
||||
inline void record_send_mysql_pkt(obmysql::ObMySQLPacket &__restrict__ pkt, int32_t len) __restrict__
|
||||
{
|
||||
if (pkt.get_mysql_packet_type() == last_type_) {
|
||||
// do nothing
|
||||
} else {
|
||||
cur_pkt_pos_++;
|
||||
}
|
||||
int64_t idx = (cur_pkt_pos_-1) % ObPacketRecordWrapper::REC_BUF_SIZE;
|
||||
pkt_rec_[idx].record_send_mysql_packet(pkt, len);
|
||||
last_type_ = pkt.get_mysql_packet_type();
|
||||
}
|
||||
inline void record_recieve_mysql_packet(obmysql::ObMySQLRawPacket &__restrict__ pkt) __restrict__
|
||||
{
|
||||
int64_t idx = cur_pkt_pos_ % ObPacketRecordWrapper::REC_BUF_SIZE;
|
||||
pkt_rec_[idx].record_recieve_mysql_packet(pkt);
|
||||
cur_pkt_pos_++;
|
||||
}
|
||||
inline void record_recieve_mysql_pkt_fragment(int32_t recive) __restrict__
|
||||
{
|
||||
int64_t idx = cur_pkt_pos_ % ObPacketRecordWrapper::REC_BUF_SIZE;
|
||||
pkt_rec_[idx].record_recieve_mysql_pkt_fragment(recive);
|
||||
}
|
||||
// for mysql protocol end
|
||||
|
||||
inline bool enable_proto_dia() {
|
||||
return enable_proto_dia_;
|
||||
}
|
||||
public:
|
||||
obmysql::ObPacketRecord pkt_rec_[REC_BUF_SIZE];
|
||||
uint32_t start_pkt_pos_;
|
||||
uint32_t cur_pkt_pos_;
|
||||
obmysql::ObMySQLPacketType last_type_;
|
||||
bool enable_proto_dia_;
|
||||
};
|
||||
|
||||
|
||||
|
||||
} // end of namespace obmysql
|
||||
} // end of namespace oceanbase
|
||||
|
||||
#endif /* _OB_MYSQL_OB_PACKET_RECORD_H_ */
|
4
deps/oblib/src/rpc/obmysql/obsm_struct.h
vendored
4
deps/oblib/src/rpc/obmysql/obsm_struct.h
vendored
@ -17,6 +17,8 @@
|
||||
#include "rpc/obmysql/ob_mysql_request_utils.h"
|
||||
#include "rpc/ob_packet.h"
|
||||
#include "lib/lock/ob_latch.h"
|
||||
#include "rpc/obmysql/ob_packet_record.h"
|
||||
#include "rpc/obmysql/ob_2_0_protocol_struct.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -65,6 +67,7 @@ public:
|
||||
proxy_version_ = 0;
|
||||
group_id_ = 0;
|
||||
client_cs_type_ = 0;
|
||||
pkt_rec_wrapper_.init();
|
||||
}
|
||||
|
||||
obmysql::ObCompressType get_compress_type() {
|
||||
@ -180,6 +183,7 @@ public:
|
||||
uint64_t proxy_version_;
|
||||
int32_t group_id_;
|
||||
int32_t client_cs_type_;
|
||||
obmysql::ObPacketRecordWrapper pkt_rec_wrapper_;
|
||||
};
|
||||
} // end of namespace observer
|
||||
} // end of namespace oceanbase
|
||||
|
1
deps/oblib/src/rpc/obmysql/packet/ompk_eof.h
vendored
1
deps/oblib/src/rpc/obmysql/packet/ompk_eof.h
vendored
@ -41,6 +41,7 @@ public:
|
||||
inline uint8_t get_field_count() const { return field_count_; }
|
||||
inline uint16_t get_warning_count() const { return warning_count_; }
|
||||
inline ObServerStatusFlags get_server_status() const { return server_status_; }
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_EOF; }
|
||||
virtual int64_t to_string(char *buf, const int64_t buf_len) const;
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(OMPKEOF);
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
inline common::ObString get_sql_state() const { return sqlstate_; }
|
||||
inline common::ObString get_message() const { return message_; }
|
||||
virtual int64_t to_string(char *buf, const int64_t buf_len) const;
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_ERR; }
|
||||
|
||||
private:
|
||||
|
||||
|
@ -27,6 +27,7 @@ class OMPKField
|
||||
public:
|
||||
explicit OMPKField(ObMySQLField &field);
|
||||
virtual ~OMPKField() { }
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_FIELD; }
|
||||
|
||||
virtual int serialize(char *buffer, int64_t len, int64_t &pos) const;
|
||||
private:
|
||||
|
1
deps/oblib/src/rpc/obmysql/packet/ompk_ok.h
vendored
1
deps/oblib/src/rpc/obmysql/packet/ompk_ok.h
vendored
@ -63,6 +63,7 @@ public:
|
||||
inline const common::ObIArray<ObStringKV> &get_system_vars() const { return system_vars_; }
|
||||
inline const common::ObIArray<ObStringKV> &get_user_vars() const { return user_vars_; }
|
||||
inline ObMySQLCapabilityFlags get_capability() const { return capability_; }
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_OKP; }
|
||||
|
||||
virtual int64_t to_string(char *buf, const int64_t buf_len) const;
|
||||
private:
|
||||
|
@ -45,6 +45,7 @@ public:
|
||||
|
||||
virtual int serialize(char *buffer, int64_t len, int64_t &pos) const;
|
||||
virtual int64_t get_serialize_size() const;
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_PIECE; }
|
||||
|
||||
inline void set_piece_mode(int8_t piece_mode) { piece_mode_ = piece_mode; }
|
||||
inline void set_data(common::ObString &data) { data_ = data; }
|
||||
|
@ -57,6 +57,7 @@ public:
|
||||
inline void set_param_num(const uint16_t num) { param_num_ = num; }
|
||||
|
||||
inline void set_warning_count(const uint16_t count) { warning_count_ = count; }
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_PREPARE; }
|
||||
|
||||
private:
|
||||
uint8_t status_;
|
||||
|
@ -61,6 +61,7 @@ public:
|
||||
inline void set_extend_flag(ObServerExtendFlag flag) { extend_flag_ = flag; }
|
||||
|
||||
inline void set_has_result_set(int8_t has_result) { has_result_set_ = has_result; }
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_PREXEC; }
|
||||
|
||||
private:
|
||||
ObServerExtendFlag extend_flag_;
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
{
|
||||
return field_count_;
|
||||
}
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_RESHEAD; }
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(OMPKResheader);
|
||||
|
1
deps/oblib/src/rpc/obmysql/packet/ompk_row.h
vendored
1
deps/oblib/src/rpc/obmysql/packet/ompk_row.h
vendored
@ -26,6 +26,7 @@ class OMPKRow : public ObMySQLPacket
|
||||
public:
|
||||
explicit OMPKRow(const ObMySQLRow &row);
|
||||
virtual ~OMPKRow() { }
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_ROW; }
|
||||
|
||||
virtual int serialize(char *buffer, int64_t len, int64_t &pos) const;
|
||||
private:
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
inline ObMySQLPacketType get_mysql_packet_type() { return ObMySQLPacketType::PKT_STR; }
|
||||
|
||||
VIRTUAL_TO_STRING_KV("header", hdr_, K_(str));
|
||||
|
||||
|
1
deps/oblib/unittest/lib/CMakeLists.txt
vendored
1
deps/oblib/unittest/lib/CMakeLists.txt
vendored
@ -81,7 +81,6 @@ oblib_addtest(queue/test_priority_queue.cpp)
|
||||
oblib_addtest(random/test_mysql_random.cpp)
|
||||
oblib_addtest(random/test_random.cpp)
|
||||
oblib_addtest(rc/test_context.cpp)
|
||||
oblib_addtest(regex/test_regex.cpp)
|
||||
oblib_addtest(resource/test_resource_mgr.cpp)
|
||||
#oblib_addtest(restore/test_storage_file.cpp)
|
||||
#oblib_addtest(restore/test_storage_oss.cpp)
|
||||
|
622
deps/oblib/unittest/lib/regex/test_regex.cpp
vendored
622
deps/oblib/unittest/lib/regex/test_regex.cpp
vendored
@ -1,622 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2021 OceanBase
|
||||
* OceanBase CE 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.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include "lib/ob_define.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include "lib/regex/regex/regalone.h"
|
||||
#include "lib/regex/regex/ob_regex.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "test_regex.ih"
|
||||
|
||||
#include "lib/utility/ob_macro_utils.h"
|
||||
|
||||
using namespace oceanbase::common;
|
||||
|
||||
#if 0
|
||||
int debug = 0;
|
||||
int line = 0;
|
||||
int status = 0;
|
||||
|
||||
int copts = OB_REG_EXTENDED;
|
||||
int eopts = 0;
|
||||
ob_regoff_t startoff = 0;
|
||||
ob_regoff_t endoff = 0;
|
||||
|
||||
|
||||
//extern void regprint();
|
||||
|
||||
/*
|
||||
- split - divide a string into fields, like awk split()
|
||||
= int split(char *string, char *fields[], int nfields, char *sep);
|
||||
*/
|
||||
int /* number of fields, including overflow */
|
||||
split(char *string,
|
||||
char *fields[], /* list is not NULL-terminated */
|
||||
int nfields, /* number of entries available in fields[] */
|
||||
char *sep /* "" white, "c" single char, "ab" [ab]+ */
|
||||
)
|
||||
{
|
||||
register char *p = string;
|
||||
register char c; /* latest character */
|
||||
register char sepc = sep[0];
|
||||
register char sepc2;
|
||||
register int fn;
|
||||
register char **fp = fields;
|
||||
register char *sepp;
|
||||
register int trimtrail;
|
||||
|
||||
/* white space */
|
||||
if (sepc == '\0') {
|
||||
while ((c = *p++) == ' ' || c == '\t')
|
||||
continue;
|
||||
p--;
|
||||
trimtrail = 1;
|
||||
static char static_sep[5] = " \t";
|
||||
sep = static_sep; /* note, code below knows this is 2 long */
|
||||
sepc = ' ';
|
||||
} else
|
||||
trimtrail = 0;
|
||||
sepc2 = sep[1]; /* now we can safely pick this up */
|
||||
|
||||
/* catch empties */
|
||||
if (*p == '\0')
|
||||
return(0);
|
||||
|
||||
/* single separator */
|
||||
if (sepc2 == '\0') {
|
||||
fn = nfields;
|
||||
for (;;) {
|
||||
*fp++ = p;
|
||||
fn--;
|
||||
if (fn == 0)
|
||||
break;
|
||||
while ((c = *p++) != sepc)
|
||||
if (c == '\0')
|
||||
return(nfields - fn);
|
||||
*(p-1) = '\0';
|
||||
}
|
||||
/* we have overflowed the fields vector -- just count them */
|
||||
fn = nfields;
|
||||
for (;;) {
|
||||
while ((c = *p++) != sepc)
|
||||
if (c == '\0')
|
||||
return(fn);
|
||||
fn++;
|
||||
}
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
/* two separators */
|
||||
if (sep[2] == '\0') {
|
||||
fn = nfields;
|
||||
for (;;) {
|
||||
*fp++ = p;
|
||||
fn--;
|
||||
while ((c = *p++) != sepc && c != sepc2)
|
||||
if (c == '\0') {
|
||||
if (trimtrail && **(fp-1) == '\0')
|
||||
fn++;
|
||||
return(nfields - fn);
|
||||
}
|
||||
if (fn == 0)
|
||||
break;
|
||||
*(p-1) = '\0';
|
||||
while ((c = *p++) == sepc || c == sepc2)
|
||||
continue;
|
||||
p--;
|
||||
}
|
||||
/* we have overflowed the fields vector -- just count them */
|
||||
fn = nfields;
|
||||
while (c != '\0') {
|
||||
while ((c = *p++) == sepc || c == sepc2)
|
||||
continue;
|
||||
p--;
|
||||
fn++;
|
||||
while ((c = *p++) != '\0' && c != sepc && c != sepc2)
|
||||
continue;
|
||||
}
|
||||
/* might have to trim trailing white space */
|
||||
if (trimtrail) {
|
||||
p--;
|
||||
while ((c = *--p) == sepc || c == sepc2)
|
||||
continue;
|
||||
p++;
|
||||
if (*p != '\0') {
|
||||
if (fn == nfields+1)
|
||||
*p = '\0';
|
||||
fn--;
|
||||
}
|
||||
}
|
||||
return(fn);
|
||||
}
|
||||
|
||||
/* n separators */
|
||||
fn = 0;
|
||||
for (;;) {
|
||||
if (fn < nfields)
|
||||
*fp++ = p;
|
||||
fn++;
|
||||
for (;;) {
|
||||
c = *p++;
|
||||
if (c == '\0')
|
||||
return(fn);
|
||||
sepp = sep;
|
||||
while ((sepc = *sepp++) != '\0' && sepc != c)
|
||||
continue;
|
||||
if (sepc != '\0') /* it was a separator */
|
||||
break;
|
||||
}
|
||||
if (fn < nfields)
|
||||
*(p-1) = '\0';
|
||||
for (;;) {
|
||||
c = *p++;
|
||||
sepp = sep;
|
||||
while ((sepc = *sepp++) != '\0' && sepc != c)
|
||||
continue;
|
||||
if (sepc == '\0') /* it wasn't a separator */
|
||||
break;
|
||||
}
|
||||
p--;
|
||||
}
|
||||
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
- regress - main loop of regression test
|
||||
== bool regress(FILE *in);
|
||||
*/
|
||||
bool
|
||||
regress(FILE *in)
|
||||
{
|
||||
char inbuf[1000];
|
||||
# define MAXF 10
|
||||
char *f[MAXF];
|
||||
int nf;
|
||||
int i;
|
||||
char erbuf[100];
|
||||
size_t ne;
|
||||
const char *badpat = "invalid regular expression";
|
||||
# define SHORT 10
|
||||
const wchar_t *bpname = "OB_REG_BADPAT";
|
||||
ob_regex_t re;
|
||||
char sep[5] = "\t\t";
|
||||
|
||||
while (fgets(inbuf, sizeof(inbuf), in) != NULL) {
|
||||
line++;
|
||||
if (inbuf[0] == '#' || inbuf[0] == '\n')
|
||||
continue; /* NOTE CONTINUE */
|
||||
inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */
|
||||
if (debug)
|
||||
fprintf(stdout, "%d:\n", line);
|
||||
nf = split(inbuf, f, MAXF, sep);
|
||||
if (nf < 3) {
|
||||
fprintf(stderr, "bad input, line %d\n", line);
|
||||
return false;
|
||||
}
|
||||
for (i = 0; i < nf; i++)
|
||||
if (strcmp(f[i], "\"\"") == 0)
|
||||
f[i][0] = '\0';
|
||||
//f[i] = "";
|
||||
if (nf <= 3)
|
||||
f[3] = NULL;
|
||||
if (nf <= 4)
|
||||
f[4] = NULL;
|
||||
try_case(f[0], f[1], f[2], f[3], f[4], options('c', f[1]));
|
||||
if (opt('&', f[1])) /* try with either type of RE */
|
||||
try_case(f[0], f[1], f[2], f[3], f[4],
|
||||
options('c', f[1]) &~ OB_REG_EXTENDED);
|
||||
}
|
||||
|
||||
ne = ob_regerror(OB_REG_BADPAT, (ob_regex_t *)NULL, erbuf, sizeof(erbuf));
|
||||
if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) {
|
||||
fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n",
|
||||
erbuf, badpat);
|
||||
status = 1;
|
||||
}
|
||||
ne = ob_regerror(OB_REG_BADPAT, (ob_regex_t *)NULL, erbuf, (size_t)SHORT);
|
||||
if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' ||
|
||||
ne != strlen(badpat)+1) {
|
||||
fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n",
|
||||
erbuf, SHORT-1, badpat);
|
||||
status = 1;
|
||||
}
|
||||
ne = ob_regerror(OB_REG_ITOA|OB_REG_BADPAT, (ob_regex_t *)NULL, erbuf, sizeof(erbuf));
|
||||
if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) {
|
||||
fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n",
|
||||
erbuf, bpname);
|
||||
status = 1;
|
||||
}
|
||||
re.re_endp = bpname;
|
||||
ne = ob_regerror(OB_REG_ATOI, &re, erbuf, sizeof(erbuf));
|
||||
if (atoi(erbuf) != (int)OB_REG_BADPAT) {
|
||||
fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n",
|
||||
erbuf, (long)OB_REG_BADPAT);
|
||||
status = 1;
|
||||
} else if (ne != strlen(erbuf)+1) {
|
||||
fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n",
|
||||
erbuf, (long)OB_REG_BADPAT);
|
||||
status = 1;
|
||||
}
|
||||
return 0 == status;
|
||||
}
|
||||
|
||||
/*
|
||||
- try_case - try it, and report on problems
|
||||
== void try_case(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
|
||||
*/
|
||||
void
|
||||
try_case(char *f0,
|
||||
char *f1,
|
||||
char *f2,
|
||||
char *f3,
|
||||
char *f4,
|
||||
int opts /* may not match f1 */
|
||||
)
|
||||
{
|
||||
ob_regex_t re;
|
||||
# define NSUBS 10
|
||||
ob_regmatch_t subs[NSUBS];
|
||||
# define NSHOULD 15
|
||||
char *should[NSHOULD];
|
||||
int nshould;
|
||||
char erbuf[100];
|
||||
int err;
|
||||
int len;
|
||||
const char *type = (opts & OB_REG_EXTENDED) ? "ERE" : "BRE";
|
||||
register int i;
|
||||
char *grump;
|
||||
char f0copy[1000];
|
||||
char f2copy[1000];
|
||||
char sep[5] = ",";
|
||||
|
||||
strcpy(f0copy, f0);
|
||||
re.re_endp = (opts&OB_REG_PEND) ? f0copy + strlen(f0copy) : NULL;
|
||||
fixstr(f0copy);
|
||||
err = ob_regcomp(&re, f0copy, opts, &ob_charset_utf8mb4_general_ci);
|
||||
if (err != 0 && (!opt('C', f1) || err != efind(f2))) {
|
||||
/* unexpected error or wrong error */
|
||||
len = (int) ob_regerror(err, &re, erbuf, sizeof(erbuf));
|
||||
fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n",
|
||||
line, type, eprint(err), len,
|
||||
(int) sizeof(erbuf), erbuf);
|
||||
status = 1;
|
||||
} else if (err == 0 && opt('C', f1)) {
|
||||
/* unexpected success */
|
||||
fprintf(stderr, "%d: %s should have given OB_REG_%s\n",
|
||||
line, type, f2);
|
||||
status = 1;
|
||||
err = 1; /* so we won't try regexec */
|
||||
}
|
||||
|
||||
if (err != 0) {
|
||||
ob_regfree(&re);
|
||||
return;
|
||||
}
|
||||
|
||||
strcpy(f2copy, f2);
|
||||
fixstr(f2copy);
|
||||
|
||||
if (options('e', f1)&OB_REG_STARTEND) {
|
||||
if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL)
|
||||
fprintf(stderr, "%d: bad STARTEND syntax\n", line);
|
||||
subs[0].rm_so = strchr(f2, '(') - f2 + 1;
|
||||
subs[0].rm_eo = strchr(f2, ')') - f2;
|
||||
}
|
||||
err = ob_regexec(&re, f2copy, NSUBS, subs, options('e', f1));
|
||||
|
||||
if (err != 0 && (f3 != NULL || err != OB_REG_NOMATCH)) {
|
||||
/* unexpected error or wrong error */
|
||||
len = (int) ob_regerror(err, &re, erbuf, sizeof(erbuf));
|
||||
fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n",
|
||||
line, type, eprint(err), len,
|
||||
(int) sizeof(erbuf), erbuf);
|
||||
status = 1;
|
||||
} else if (err != 0) {
|
||||
/* nothing more to check */
|
||||
} else if (f3 == NULL) {
|
||||
/* unexpected success */
|
||||
fprintf(stderr, "%d: %s exec should have failed\n",
|
||||
line, type);
|
||||
status = 1;
|
||||
err = 1; /* just on principle */
|
||||
} else if (opts&OB_REG_NOSUB) {
|
||||
/* nothing more to check */
|
||||
} else if ((grump = check(f2, subs[0], f3)) != NULL) {
|
||||
fprintf(stderr, "%d: %s %s\n", line, type, grump);
|
||||
status = 1;
|
||||
err = 1;
|
||||
}
|
||||
|
||||
if (err != 0 || f4 == NULL) {
|
||||
ob_regfree(&re);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 1; i < NSHOULD; i++)
|
||||
should[i] = NULL;
|
||||
nshould = split(f4, should+1, NSHOULD-1, sep);
|
||||
if (nshould == 0) {
|
||||
nshould = 1;
|
||||
should[1][0] = '\0';
|
||||
//should[1] = "";
|
||||
}
|
||||
for (i = 1; i < NSUBS; i++) {
|
||||
grump = check(f2, subs[i], should[i]);
|
||||
if (grump != NULL) {
|
||||
fprintf(stderr, "%d: %s $%d %s\n", line,
|
||||
type, i, grump);
|
||||
status = 1;
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
ob_regfree(&re);
|
||||
}
|
||||
|
||||
/*
|
||||
- options - pick options out of a regression-test string
|
||||
== int options(int type, char *s);
|
||||
*/
|
||||
int
|
||||
options(int type, /* 'c' compile, 'e' exec */
|
||||
char *s)
|
||||
{
|
||||
register char *p;
|
||||
register int o = (type == 'c') ? copts : eopts;
|
||||
register const char *legal = (type == 'c') ? "bisnmp" : "^$#tl";
|
||||
|
||||
for (p = s; *p != '\0'; p++)
|
||||
if (strchr(legal, *p) != NULL)
|
||||
switch (*p) {
|
||||
case 'b':
|
||||
o &= ~OB_REG_EXTENDED;
|
||||
break;
|
||||
case 'i':
|
||||
o |= OB_REG_ICASE;
|
||||
break;
|
||||
case 's':
|
||||
o |= OB_REG_NOSUB;
|
||||
break;
|
||||
case 'n':
|
||||
o |= OB_REG_NEWLINE;
|
||||
break;
|
||||
case 'm':
|
||||
o &= ~OB_REG_EXTENDED;
|
||||
o |= OB_REG_NOSPEC;
|
||||
break;
|
||||
case 'p':
|
||||
o |= OB_REG_PEND;
|
||||
break;
|
||||
case '^':
|
||||
o |= OB_REG_NOTBOL;
|
||||
break;
|
||||
case '$':
|
||||
o |= OB_REG_NOTEOL;
|
||||
break;
|
||||
case '#':
|
||||
o |= OB_REG_STARTEND;
|
||||
break;
|
||||
case 't': /* trace */
|
||||
o |= OB_REG_TRACE;
|
||||
break;
|
||||
case 'l': /* force long representation */
|
||||
o |= OB_REG_LARGE;
|
||||
break;
|
||||
case 'r': /* force backref use */
|
||||
o |= OB_REG_BACKR;
|
||||
break;
|
||||
}
|
||||
return(o);
|
||||
}
|
||||
|
||||
/*
|
||||
- opt - is a particular option in a regression string?
|
||||
== int opt(int c, char *s);
|
||||
*/
|
||||
int /* predicate */
|
||||
opt(int c, char *s)
|
||||
{
|
||||
return(strchr(s, c) != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
- fixstr - transform magic characters in strings
|
||||
== void fixstr(register char *p);
|
||||
*/
|
||||
void
|
||||
fixstr(register char *p)
|
||||
{
|
||||
if (p == NULL)
|
||||
return;
|
||||
|
||||
for (; *p != '\0'; p++)
|
||||
if (*p == 'N')
|
||||
*p = '\n';
|
||||
else if (*p == 'T')
|
||||
*p = '\t';
|
||||
else if (*p == 'S')
|
||||
*p = ' ';
|
||||
else if (*p == 'Z')
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
- check - check a substring match
|
||||
== char *check(char *str, ob_regmatch_t sub, char *should);
|
||||
*/
|
||||
char * /* NULL or complaint */
|
||||
check(char *str, ob_regmatch_t sub, char *should)
|
||||
{
|
||||
register int len;
|
||||
register int shlen;
|
||||
register char *p;
|
||||
static char grump[500];
|
||||
register char *at = NULL;
|
||||
|
||||
if (should != NULL && strcmp(should, "-") == 0)
|
||||
should = NULL;
|
||||
if (should != NULL && should[0] == '@') {
|
||||
at = should + 1;
|
||||
should[0] = '\0';
|
||||
}
|
||||
|
||||
/* check rm_so and rm_eo for consistency */
|
||||
if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) ||
|
||||
(sub.rm_so != -1 && sub.rm_eo == -1) ||
|
||||
(sub.rm_so != -1 && sub.rm_so < 0) ||
|
||||
(sub.rm_eo != -1 && sub.rm_eo < 0) ) {
|
||||
sprintf(grump, "start %ld end %ld", (long)sub.rm_so,
|
||||
(long)sub.rm_eo);
|
||||
return(grump);
|
||||
}
|
||||
|
||||
/* check for no match */
|
||||
if (sub.rm_so == -1 && should == NULL)
|
||||
return(NULL);
|
||||
if (sub.rm_so == -1) {
|
||||
static char ret_err_buf[50] = "did not match";
|
||||
return(ret_err_buf);
|
||||
}
|
||||
|
||||
/* check for in range */
|
||||
if (sub.rm_eo > strlen(str)) {
|
||||
sprintf(grump, "start %ld end %ld, past end of string",
|
||||
(long)sub.rm_so, (long)sub.rm_eo);
|
||||
return(grump);
|
||||
}
|
||||
|
||||
len = (int)(sub.rm_eo - sub.rm_so);
|
||||
shlen = (int)strlen(should);
|
||||
p = str + sub.rm_so;
|
||||
|
||||
/* check for not supposed to match */
|
||||
if (should == NULL) {
|
||||
sprintf(grump, "matched `%.*s'", len, p);
|
||||
return(grump);
|
||||
}
|
||||
|
||||
/* check for wrong match */
|
||||
if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) {
|
||||
sprintf(grump, "matched `%.*s' instead", len, p);
|
||||
return(grump);
|
||||
}
|
||||
if (shlen > 0)
|
||||
return(NULL);
|
||||
|
||||
/* check null match in right place */
|
||||
if (at == NULL)
|
||||
return(NULL);
|
||||
shlen = (int)strlen(at);
|
||||
if (shlen == 0)
|
||||
shlen = 1; /* force check for end-of-string */
|
||||
if (strncmp(p, at, shlen) != 0) {
|
||||
sprintf(grump, "matched null at `%.20s'", p);
|
||||
return(grump);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
- eprint - convert error number to name
|
||||
== static char *eprint(int err);
|
||||
*/
|
||||
static char *
|
||||
eprint(int err)
|
||||
{
|
||||
static char epbuf[100];
|
||||
size_t len;
|
||||
|
||||
len = ob_regerror(OB_REG_ITOA|err, (ob_regex_t *)NULL, epbuf, sizeof(epbuf));
|
||||
assert(len <= sizeof(epbuf));
|
||||
UNUSED(len);
|
||||
return(epbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
- efind - convert error name to number
|
||||
== static int efind(char *name);
|
||||
*/
|
||||
static int
|
||||
efind(char *name)
|
||||
{
|
||||
static char efbuf[100];
|
||||
//size_t n;
|
||||
ob_regex_t re;
|
||||
|
||||
sprintf(efbuf, "OB_REG_%s", name);
|
||||
assert(strlen(efbuf) < sizeof(efbuf));
|
||||
re.re_endp = efbuf;
|
||||
(void) ob_regerror(OB_REG_ATOI, &re, efbuf, sizeof(efbuf));
|
||||
return(atoi(efbuf));
|
||||
}
|
||||
|
||||
|
||||
class ObRegexTest : public ::testing::Test
|
||||
{
|
||||
public:
|
||||
ObRegexTest();
|
||||
virtual ~ObRegexTest();
|
||||
virtual void SetUp();
|
||||
virtual void TearDown();
|
||||
private:
|
||||
// disallow copy
|
||||
ObRegexTest(const ObRegexTest &other);
|
||||
ObRegexTest& operator=(const ObRegexTest &other);
|
||||
private:
|
||||
// data members
|
||||
};
|
||||
ObRegexTest::ObRegexTest()
|
||||
{
|
||||
}
|
||||
|
||||
ObRegexTest::~ObRegexTest()
|
||||
{
|
||||
}
|
||||
|
||||
void ObRegexTest::SetUp()
|
||||
{
|
||||
}
|
||||
|
||||
void ObRegexTest::TearDown()
|
||||
{
|
||||
}
|
||||
|
||||
TEST_F(ObRegexTest, basic_test)
|
||||
{
|
||||
/*
|
||||
- main - do the simple case, hand off to regress() for regression
|
||||
*/
|
||||
char test_filename[] = "regex/tests";
|
||||
FILE *test_file = fopen(test_filename, "r");
|
||||
if (NULL == test_file) {
|
||||
fprintf(stderr, "fail to open file '%s'\n", test_filename);
|
||||
} else {
|
||||
ASSERT_TRUE(regress(test_file));
|
||||
fclose(test_file);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
OB_LOGGER.set_log_level("INFO");
|
||||
//ob_init_memory_pool();
|
||||
::testing::InitGoogleTest(&argc,argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
19
deps/oblib/unittest/lib/regex/test_regex.ih
vendored
19
deps/oblib/unittest/lib/regex/test_regex.ih
vendored
@ -1,19 +0,0 @@
|
||||
/* ========= begin header generated by ./mkh ========= */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* === main.c === */
|
||||
bool regress(FILE *in);
|
||||
void try_case(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
|
||||
int options(int type, char *s);
|
||||
int opt(int c, char *s);
|
||||
void fixstr(register char *p);
|
||||
char *check(char *str, ob_regmatch_t sub, char *should);
|
||||
static char *eprint(int err);
|
||||
static int efind(char *name);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* ========= end header generated by ./mkh ========= */
|
479
deps/oblib/unittest/lib/regex/tests
vendored
479
deps/oblib/unittest/lib/regex/tests
vendored
@ -1,479 +0,0 @@
|
||||
# regular expression test set
|
||||
# Lines are at least three fields, separated by one or more tabs. "" stands
|
||||
# for an empty field. First field is an RE. Second field is flags. If
|
||||
# C flag given, regcomp() is expected to fail, and the third field is the
|
||||
# error name (minus the leading REG_).
|
||||
#
|
||||
# Otherwise it is expected to succeed, and the third field is the string to
|
||||
# try matching it against. If there is no fourth field, the match is
|
||||
# expected to fail. If there is a fourth field, it is the substring that
|
||||
# the RE is expected to match. If there is a fifth field, it is a comma-
|
||||
# separated list of what the subexpressions should match, with - indicating
|
||||
# no match for that one. In both the fourth and fifth fields, a (sub)field
|
||||
# starting with @ indicates that the (sub)expression is expected to match
|
||||
# a null string followed by the stuff after the @; this provides a way to
|
||||
# test where null strings match. The character `N' in REs and strings
|
||||
# is newline, `S' is space, `T' is tab, `Z' is NUL.
|
||||
#
|
||||
# The full list of flags:
|
||||
# - placeholder, does nothing
|
||||
# b RE is a BRE, not an ERE
|
||||
# & try it as both an ERE and a BRE
|
||||
# C regcomp() error expected, third field is error name
|
||||
# i REG_ICASE
|
||||
# m ("mundane") REG_NOSPEC
|
||||
# s REG_NOSUB (not really testable)
|
||||
# n REG_NEWLINE
|
||||
# ^ REG_NOTBOL
|
||||
# $ REG_NOTEOL
|
||||
# # REG_STARTEND (see below)
|
||||
# p REG_PEND
|
||||
#
|
||||
# For REG_STARTEND, the start/end offsets are those of the substring
|
||||
# enclosed in ().
|
||||
|
||||
# basics
|
||||
a & a a
|
||||
abc & abc abc
|
||||
abc|de - abc abc
|
||||
a|b|c - abc a
|
||||
|
||||
# parentheses and perversions thereof
|
||||
a(b)c - abc abc
|
||||
a\(b\)c b abc abc
|
||||
a( C EPAREN
|
||||
a( b a( a(
|
||||
a\( - a( a(
|
||||
a\( bC EPAREN
|
||||
a\(b bC EPAREN
|
||||
a(b C EPAREN
|
||||
a(b b a(b a(b
|
||||
# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly)
|
||||
a) - a) a)
|
||||
) - ) )
|
||||
# end gagging (in a just world, those *should* give EPAREN)
|
||||
a) b a) a)
|
||||
a\) bC EPAREN
|
||||
\) bC EPAREN
|
||||
a()b - ab ab
|
||||
a\(\)b b ab ab
|
||||
|
||||
# anchoring and REG_NEWLINE
|
||||
^abc$ & abc abc
|
||||
a^b - a^b
|
||||
a^b b a^b a^b
|
||||
a$b - a$b
|
||||
a$b b a$b a$b
|
||||
^ & abc @abc
|
||||
$ & abc @
|
||||
^$ & "" @
|
||||
$^ - "" @
|
||||
\($\)\(^\) b "" @
|
||||
# stop retching, those are legitimate (although disgusting)
|
||||
^^ - "" @
|
||||
$$ - "" @
|
||||
b$ & abNc
|
||||
b$ &n abNc b
|
||||
^b$ & aNbNc
|
||||
^b$ &n aNbNc b
|
||||
^$ &n aNNb @Nb
|
||||
^$ n abc
|
||||
^$ n abcN @
|
||||
$^ n aNNb @Nb
|
||||
\($\)\(^\) bn aNNb @Nb
|
||||
^^ n^ aNNb @Nb
|
||||
$$ n aNNb @NN
|
||||
^a ^ a
|
||||
a$ $ a
|
||||
^a ^n aNb
|
||||
^b ^n aNb b
|
||||
a$ $n bNa
|
||||
b$ $n bNa b
|
||||
a*(^b$)c* - b b
|
||||
a*\(^b$\)c* b b b
|
||||
|
||||
# certain syntax errors and non-errors
|
||||
| C EMPTY
|
||||
| b | |
|
||||
* C BADRPT
|
||||
* b * *
|
||||
+ C BADRPT
|
||||
? C BADRPT
|
||||
"" &C EMPTY
|
||||
() - abc @abc
|
||||
\(\) b abc @abc
|
||||
a||b C EMPTY
|
||||
|ab C EMPTY
|
||||
ab| C EMPTY
|
||||
(|a)b C EMPTY
|
||||
(a|)b C EMPTY
|
||||
(*a) C BADRPT
|
||||
(+a) C BADRPT
|
||||
(?a) C BADRPT
|
||||
({1}a) C BADRPT
|
||||
\(\{1\}a\) bC BADRPT
|
||||
(a|*b) C BADRPT
|
||||
(a|+b) C BADRPT
|
||||
(a|?b) C BADRPT
|
||||
(a|{1}b) C BADRPT
|
||||
^* C BADRPT
|
||||
^* b * *
|
||||
^+ C BADRPT
|
||||
^? C BADRPT
|
||||
^{1} C BADRPT
|
||||
^\{1\} bC BADRPT
|
||||
|
||||
# metacharacters, backslashes
|
||||
a.c & abc abc
|
||||
a[bc]d & abd abd
|
||||
a\*c & a*c a*c
|
||||
a\\b & a\b a\b
|
||||
a\\\*b & a\*b a\*b
|
||||
a\bc & abc abc
|
||||
a\ &C EESCAPE
|
||||
a\\bc & a\bc a\bc
|
||||
\{ bC BADRPT
|
||||
a\[b & a[b a[b
|
||||
a[b &C EBRACK
|
||||
# trailing $ is a peculiar special case for the BRE code
|
||||
a$ & a a
|
||||
a$ & a$
|
||||
a\$ & a
|
||||
a\$ & a$ a$
|
||||
a\\$ & a
|
||||
a\\$ & a$
|
||||
a\\$ & a\$
|
||||
a\\$ & a\ a\
|
||||
|
||||
# back references, ugh
|
||||
a\(b\)\2c bC ESUBREG
|
||||
a\(b\1\)c bC ESUBREG
|
||||
a\(b*\)c\1d b abbcbbd abbcbbd bb
|
||||
a\(b*\)c\1d b abbcbd
|
||||
a\(b*\)c\1d b abbcbbbd
|
||||
^\(.\)\1 b abc
|
||||
a\([bc]\)\1d b abcdabbd abbd b
|
||||
a\(\([bc]\)\2\)*d b abbccd abbccd
|
||||
a\(\([bc]\)\2\)*d b abbcbd
|
||||
# actually, this next one probably ought to fail, but the spec is unclear
|
||||
a\(\(b\)*\2\)*d b abbbd abbbd
|
||||
# here is a case that no NFA implementation does right
|
||||
\(ab*\)[ab]*\1 b ababaaa ababaaa a
|
||||
# check out normal matching in the presence of back refs
|
||||
\(a\)\1bcd b aabcd aabcd
|
||||
\(a\)\1bc*d b aabcd aabcd
|
||||
\(a\)\1bc*d b aabd aabd
|
||||
\(a\)\1bc*d b aabcccd aabcccd
|
||||
\(a\)\1bc*[ce]d b aabcccd aabcccd
|
||||
^\(a\)\1b\(c\)*cd$ b aabcccd aabcccd
|
||||
|
||||
# ordinary repetitions
|
||||
ab*c & abc abc
|
||||
ab+c - abc abc
|
||||
ab?c - abc abc
|
||||
a\(*\)b b a*b a*b
|
||||
a\(**\)b b ab ab
|
||||
a\(***\)b bC BADRPT
|
||||
*a b *a *a
|
||||
**a b a a
|
||||
***a bC BADRPT
|
||||
|
||||
# the dreaded bounded repetitions
|
||||
{ & { {
|
||||
{abc & {abc {abc
|
||||
{1 C BADRPT
|
||||
{1} C BADRPT
|
||||
a{b & a{b a{b
|
||||
a{1}b - ab ab
|
||||
a\{1\}b b ab ab
|
||||
a{1,}b - ab ab
|
||||
a\{1,\}b b ab ab
|
||||
a{1,2}b - aab aab
|
||||
a\{1,2\}b b aab aab
|
||||
a{1 C EBRACE
|
||||
a\{1 bC EBRACE
|
||||
a{1a C EBRACE
|
||||
a\{1a bC EBRACE
|
||||
a{1a} C BADBR
|
||||
a\{1a\} bC BADBR
|
||||
a{,2} - a{,2} a{,2}
|
||||
a\{,2\} bC BADBR
|
||||
a{,} - a{,} a{,}
|
||||
a\{,\} bC BADBR
|
||||
a{1,x} C BADBR
|
||||
a\{1,x\} bC BADBR
|
||||
a{1,x C EBRACE
|
||||
a\{1,x bC EBRACE
|
||||
a{300} C BADBR
|
||||
a\{300\} bC BADBR
|
||||
a{1,0} C BADBR
|
||||
a\{1,0\} bC BADBR
|
||||
ab{0,0}c - abcac ac
|
||||
ab\{0,0\}c b abcac ac
|
||||
ab{0,1}c - abcac abc
|
||||
ab\{0,1\}c b abcac abc
|
||||
ab{0,3}c - abbcac abbc
|
||||
ab\{0,3\}c b abbcac abbc
|
||||
ab{1,1}c - acabc abc
|
||||
ab\{1,1\}c b acabc abc
|
||||
ab{1,3}c - acabc abc
|
||||
ab\{1,3\}c b acabc abc
|
||||
ab{2,2}c - abcabbc abbc
|
||||
ab\{2,2\}c b abcabbc abbc
|
||||
ab{2,4}c - abcabbc abbc
|
||||
ab\{2,4\}c b abcabbc abbc
|
||||
((a{1,10}){1,10}){1,10} - a a a,a
|
||||
|
||||
# multiple repetitions
|
||||
a** &C BADRPT
|
||||
a++ C BADRPT
|
||||
a?? C BADRPT
|
||||
a*+ C BADRPT
|
||||
a*? C BADRPT
|
||||
a+* C BADRPT
|
||||
a+? C BADRPT
|
||||
a?* C BADRPT
|
||||
a?+ C BADRPT
|
||||
a{1}{1} C BADRPT
|
||||
a*{1} C BADRPT
|
||||
a+{1} C BADRPT
|
||||
a?{1} C BADRPT
|
||||
a{1}* C BADRPT
|
||||
a{1}+ C BADRPT
|
||||
a{1}? C BADRPT
|
||||
a*{b} - a{b} a{b}
|
||||
a\{1\}\{1\} bC BADRPT
|
||||
a*\{1\} bC BADRPT
|
||||
a\{1\}* bC BADRPT
|
||||
|
||||
# brackets, and numerous perversions thereof
|
||||
a[b]c & abc abc
|
||||
a[ab]c & abc abc
|
||||
a[^ab]c & adc adc
|
||||
a[]b]c & a]c a]c
|
||||
a[[b]c & a[c a[c
|
||||
a[-b]c & a-c a-c
|
||||
a[^]b]c & adc adc
|
||||
a[^-b]c & adc adc
|
||||
a[b-]c & a-c a-c
|
||||
a[b &C EBRACK
|
||||
a[] &C EBRACK
|
||||
a[1-3]c & a2c a2c
|
||||
a[3-1]c &C ERANGE
|
||||
a[1-3-5]c &C ERANGE
|
||||
a[[.-.]--]c & a-c a-c
|
||||
a[1- &C ERANGE
|
||||
a[[. &C EBRACK
|
||||
a[[.x &C EBRACK
|
||||
a[[.x. &C EBRACK
|
||||
a[[.x.] &C EBRACK
|
||||
a[[.x.]] & ax ax
|
||||
a[[.x,.]] &C ECOLLATE
|
||||
a[[.one.]]b & a1b a1b
|
||||
a[[.notdef.]]b &C ECOLLATE
|
||||
a[[.].]]b & a]b a]b
|
||||
a[[:alpha:]]c & abc abc
|
||||
a[[:notdef:]]c &C ECTYPE
|
||||
a[[: &C EBRACK
|
||||
a[[:alpha &C EBRACK
|
||||
a[[:alpha:] &C EBRACK
|
||||
a[[:alpha,:] &C ECTYPE
|
||||
a[[:]:]]b &C ECTYPE
|
||||
a[[:-:]]b &C ECTYPE
|
||||
a[[:alph:]] &C ECTYPE
|
||||
a[[:alphabet:]] &C ECTYPE
|
||||
[[:alnum:]]+ - -%@a0X- a0X
|
||||
[[:alpha:]]+ - -%@aX0- aX
|
||||
# 在字符集utf8mb4_general_ci中,'\t'不是[:blank:],因此这里只适配SS,不适配T
|
||||
#[[:blank:]]+ - aSSTb SST
|
||||
[[:blank:]]+ - aSSTb SS
|
||||
[[:cntrl:]]+ - aNTb NT
|
||||
[[:digit:]]+ - a019b 019
|
||||
[[:graph:]]+ - Sa%bS a%b
|
||||
[[:lower:]]+ - AabC ab
|
||||
[[:print:]]+ - NaSbN aSb
|
||||
[[:punct:]]+ - S%-&T %-&
|
||||
[[:space:]]+ - aSNTb SNT
|
||||
[[:upper:]]+ - aBCd BC
|
||||
[[:xdigit:]]+ - p0f3Cq 0f3C
|
||||
a[[=b=]]c & abc abc
|
||||
a[[= &C EBRACK
|
||||
a[[=b &C EBRACK
|
||||
a[[=b= &C EBRACK
|
||||
a[[=b=] &C EBRACK
|
||||
a[[=b,=]] &C ECOLLATE
|
||||
a[[=one=]]b & a1b a1b
|
||||
|
||||
# complexities
|
||||
a(((b)))c - abc abc
|
||||
a(b|(c))d - abd abd
|
||||
a(b*|c)d - abbd abbd
|
||||
# just gotta have one DFA-buster, of course
|
||||
a[ab]{20} - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab
|
||||
# and an inline expansion in case somebody gets tricky
|
||||
a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab
|
||||
# and in case somebody just slips in an NFA...
|
||||
a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) - aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights
|
||||
# fish for anomalies as the number of states passes 32
|
||||
12345678901234567890123456789 - a12345678901234567890123456789b 12345678901234567890123456789
|
||||
123456789012345678901234567890 - a123456789012345678901234567890b 123456789012345678901234567890
|
||||
1234567890123456789012345678901 - a1234567890123456789012345678901b 1234567890123456789012345678901
|
||||
12345678901234567890123456789012 - a12345678901234567890123456789012b 12345678901234567890123456789012
|
||||
123456789012345678901234567890123 - a123456789012345678901234567890123b 123456789012345678901234567890123
|
||||
# and one really big one, beyond any plausible word width
|
||||
1234567890123456789012345678901234567890123456789012345678901234567890 - a1234567890123456789012345678901234567890123456789012345678901234567890b 1234567890123456789012345678901234567890123456789012345678901234567890
|
||||
# fish for problems as brackets go past 8
|
||||
[ab][cd][ef][gh][ij][kl][mn] - xacegikmoq acegikm
|
||||
[ab][cd][ef][gh][ij][kl][mn][op] - xacegikmoq acegikmo
|
||||
[ab][cd][ef][gh][ij][kl][mn][op][qr] - xacegikmoqy acegikmoq
|
||||
[ab][cd][ef][gh][ij][kl][mn][op][q] - xacegikmoqy acegikmoq
|
||||
|
||||
# subtleties of matching
|
||||
abc & xabcy abc
|
||||
a\(b\)?c\1d b acd
|
||||
aBc i Abc Abc
|
||||
a[Bc]*d i abBCcd abBCcd
|
||||
0[[:upper:]]1 &i 0a1 0a1
|
||||
0[[:lower:]]1 &i 0A1 0A1
|
||||
a[^b]c &i abc
|
||||
a[^b]c &i aBc
|
||||
a[^b]c &i adc adc
|
||||
[a]b[c] - abc abc
|
||||
[a]b[a] - aba aba
|
||||
[abc]b[abc] - abc abc
|
||||
[abc]b[abd] - abd abd
|
||||
a(b?c)+d - accd accd
|
||||
(wee|week)(knights|night) - weeknights weeknights
|
||||
(we|wee|week|frob)(knights|night|day) - weeknights weeknights
|
||||
a[bc]d - xyzaaabcaababdacd abd
|
||||
a[ab]c - aaabc abc
|
||||
abc s abc abc
|
||||
a* & b @b
|
||||
|
||||
# Let's have some fun -- try to match a C comment.
|
||||
# first the obvious, which looks okay at first glance...
|
||||
/\*.*\*/ - /*x*/ /*x*/
|
||||
# but...
|
||||
/\*.*\*/ - /*x*/y/*z*/ /*x*/y/*z*/
|
||||
# okay, we must not match */ inside; try to do that...
|
||||
/\*([^*]|\*[^/])*\*/ - /*x*/ /*x*/
|
||||
/\*([^*]|\*[^/])*\*/ - /*x*/y/*z*/ /*x*/
|
||||
# but...
|
||||
/\*([^*]|\*[^/])*\*/ - /*x**/y/*z*/ /*x**/y/*z*/
|
||||
# and a still fancier version, which does it right (I think)...
|
||||
/\*([^*]|\*+[^*/])*\*+/ - /*x*/ /*x*/
|
||||
/\*([^*]|\*+[^*/])*\*+/ - /*x*/y/*z*/ /*x*/
|
||||
/\*([^*]|\*+[^*/])*\*+/ - /*x**/y/*z*/ /*x**/
|
||||
/\*([^*]|\*+[^*/])*\*+/ - /*x****/y/*z*/ /*x****/
|
||||
/\*([^*]|\*+[^*/])*\*+/ - /*x**x*/y/*z*/ /*x**x*/
|
||||
/\*([^*]|\*+[^*/])*\*+/ - /*x***x/y/*z*/ /*x***x/y/*z*/
|
||||
|
||||
# subexpressions
|
||||
.* - abc abc -
|
||||
a(b)(c)d - abcd abcd b,c
|
||||
a(((b)))c - abc abc b,b,b
|
||||
a(b|(c))d - abd abd b,-
|
||||
a(b*|c|e)d - abbd abbd bb
|
||||
a(b*|c|e)d - acd acd c
|
||||
a(b*|c|e)d - ad ad @d
|
||||
a(b?)c - abc abc b
|
||||
a(b?)c - ac ac @c
|
||||
a(b+)c - abc abc b
|
||||
a(b+)c - abbbc abbbc bbb
|
||||
a(b*)c - ac ac @c
|
||||
(a|ab)(bc([de]+)f|cde) - abcdef abcdef a,bcdef,de
|
||||
# the regression tester only asks for 9 subexpressions
|
||||
a(b)(c)(d)(e)(f)(g)(h)(i)(j)k - abcdefghijk abcdefghijk b,c,d,e,f,g,h,i,j
|
||||
a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l - abcdefghijkl abcdefghijkl b,c,d,e,f,g,h,i,j,k
|
||||
a([bc]?)c - abc abc b
|
||||
a([bc]?)c - ac ac @c
|
||||
a([bc]+)c - abc abc b
|
||||
a([bc]+)c - abcc abcc bc
|
||||
a([bc]+)bc - abcbc abcbc bc
|
||||
a(bb+|b)b - abb abb b
|
||||
a(bbb+|bb+|b)b - abb abb b
|
||||
a(bbb+|bb+|b)b - abbb abbb bb
|
||||
a(bbb+|bb+|b)bb - abbb abbb b
|
||||
(.*).* - abcdef abcdef abcdef
|
||||
(a*)* - bc @b @b
|
||||
|
||||
# do we get the right subexpression when it is used more than once?
|
||||
a(b|c)*d - ad ad -
|
||||
a(b|c)*d - abcd abcd c
|
||||
a(b|c)+d - abd abd b
|
||||
a(b|c)+d - abcd abcd c
|
||||
a(b|c?)+d - ad ad @d
|
||||
a(b|c?)+d - abcd abcd @d
|
||||
a(b|c){0,0}d - ad ad -
|
||||
a(b|c){0,1}d - ad ad -
|
||||
a(b|c){0,1}d - abd abd b
|
||||
a(b|c){0,2}d - ad ad -
|
||||
a(b|c){0,2}d - abcd abcd c
|
||||
a(b|c){0,}d - ad ad -
|
||||
a(b|c){0,}d - abcd abcd c
|
||||
a(b|c){1,1}d - abd abd b
|
||||
a(b|c){1,1}d - acd acd c
|
||||
a(b|c){1,2}d - abd abd b
|
||||
a(b|c){1,2}d - abcd abcd c
|
||||
a(b|c){1,}d - abd abd b
|
||||
a(b|c){1,}d - abcd abcd c
|
||||
a(b|c){2,2}d - acbd acbd b
|
||||
a(b|c){2,2}d - abcd abcd c
|
||||
a(b|c){2,4}d - abcd abcd c
|
||||
a(b|c){2,4}d - abcbd abcbd b
|
||||
a(b|c){2,4}d - abcbcd abcbcd c
|
||||
a(b|c){2,}d - abcd abcd c
|
||||
a(b|c){2,}d - abcbd abcbd b
|
||||
a(b+|((c)*))+d - abd abd @d,@d,-
|
||||
a(b+|((c)*))+d - abcd abcd @d,@d,-
|
||||
|
||||
# check out the STARTEND option
|
||||
[abc] &# a(b)c b
|
||||
[abc] &# a(d)c
|
||||
[abc] &# a(bc)d b
|
||||
[abc] &# a(dc)d c
|
||||
. &# a()c
|
||||
b.*c &# b(bc)c bc
|
||||
b.* &# b(bc)c bc
|
||||
.*c &# b(bc)c bc
|
||||
|
||||
# plain strings, with the NOSPEC flag
|
||||
abc m abc abc
|
||||
abc m xabcy abc
|
||||
abc m xyz
|
||||
a*b m aba*b a*b
|
||||
a*b m ab
|
||||
"" mC EMPTY
|
||||
|
||||
# cases involving NULs
|
||||
aZb & a a
|
||||
aZb &p a
|
||||
aZb &p# (aZb) aZb
|
||||
aZ*b &p# (ab) ab
|
||||
a.b &# (aZb) aZb
|
||||
a.* &# (aZb)c aZb
|
||||
|
||||
# word boundaries (ick)
|
||||
[[:<:]]a & a a
|
||||
[[:<:]]a & ba
|
||||
[[:<:]]a & -a a
|
||||
a[[:>:]] & a a
|
||||
a[[:>:]] & ab
|
||||
a[[:>:]] & a- a
|
||||
[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc abc
|
||||
[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc-q abc
|
||||
[[:<:]]a.c[[:>:]] & axc-dayc-dazce-abc axc
|
||||
[[:<:]]b.c[[:>:]] & a_bxc-byc_d-bzc-q bzc
|
||||
[[:<:]].x..[[:>:]] & y_xa_-_xb_y-_xc_-axdc _xc_
|
||||
[[:<:]]a_b[[:>:]] & x_a_b
|
||||
|
||||
# past problems, and suspected problems
|
||||
(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A]) - A1 A1
|
||||
abcdefghijklmnop i abcdefghijklmnop abcdefghijklmnop
|
||||
abcdefghijklmnopqrstuv i abcdefghijklmnopqrstuv abcdefghijklmnopqrstuv
|
||||
(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN]) - CC11 CC11
|
||||
CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a - CC11 CC11
|
||||
Char \([a-z0-9_]*\)\[.* b Char xyz[k Char xyz[k xyz
|
||||
a?b - ab ab
|
||||
-\{0,1\}[0-9]*$ b -5 -5
|
||||
a*a*a*a*a*a*a* & aaaaaa aaaaaa
|
6911
hotfuncs.txt
6911
hotfuncs.txt
File diff suppressed because it is too large
Load Diff
@ -1219,7 +1219,7 @@ TEST_F(TestBatchExecute, partial_update)
|
||||
|
||||
|
||||
// create table if not exists append_lob_test (C1 bigint primary key, C2 bigint, C3 mediumtext not null);
|
||||
TEST_F(TestBatchExecute, append_lob)
|
||||
/*TEST_F(TestBatchExecute, append_lob)
|
||||
{
|
||||
// setup
|
||||
ObTable *the_table = NULL;
|
||||
@ -1340,7 +1340,7 @@ TEST_F(TestBatchExecute, append_lob)
|
||||
service_client_->free_table(the_table);
|
||||
the_table = NULL;
|
||||
}
|
||||
|
||||
*/
|
||||
// for lob column
|
||||
// drop table if exists all_lob_test; create table if not exists all_lob_test (C1 bigint primary key, C2 bigint, C3 mediumtext, index i1(c2) local)
|
||||
// TEST_F(TestBatchExecute, lob_column_test)
|
||||
@ -1557,7 +1557,7 @@ TEST_F(TestBatchExecute, append_lob)
|
||||
// create table if not exists virtual_generate_col_test
|
||||
// (C1 bigint primary key, C2 bigint, C3 varchar(100),
|
||||
// C3_PREFIX varchar(10) GENERATED ALWAYS AS (substr(C3,1,2)));
|
||||
TEST_F(TestBatchExecute, virtual_generate_col_test)
|
||||
/*TEST_F(TestBatchExecute, virtual_generate_col_test)
|
||||
{
|
||||
// setup
|
||||
ObTable *the_table = NULL;
|
||||
@ -1664,7 +1664,6 @@ TEST_F(TestBatchExecute, virtual_generate_col_test)
|
||||
service_client_->free_table(the_table);
|
||||
the_table = NULL;
|
||||
}
|
||||
|
||||
// create table if not exists store_generate_col_test
|
||||
// (c1 bigint primary key, c2 varchar(10), c3 varchar(10),
|
||||
// gen varchar(30) generated always as (concat(c2,c3)) stored)
|
||||
@ -1849,7 +1848,7 @@ TEST_F(TestBatchExecute, stored_generate_col_test)
|
||||
service_client_->free_table(the_table);
|
||||
the_table = NULL;
|
||||
}
|
||||
|
||||
*/
|
||||
// create table if not exists large_scan_test (C1 bigint primary key, C2 bigint, C3 varchar(100));
|
||||
TEST_F(TestBatchExecute, large_scan)
|
||||
{
|
||||
@ -6053,7 +6052,7 @@ TEST_F(TestBatchExecute, htable_scan_with_filter)
|
||||
delete [] rows;
|
||||
}
|
||||
|
||||
TEST_F(TestBatchExecute, single_increment_append)
|
||||
/*TEST_F(TestBatchExecute, single_increment_append)
|
||||
{
|
||||
OB_LOG(INFO, "begin single_increment");
|
||||
ObTable *the_table = NULL;
|
||||
@ -6380,7 +6379,7 @@ TEST_F(TestBatchExecute, single_increment_append)
|
||||
}
|
||||
service_client_->free_table(the_table);
|
||||
}
|
||||
|
||||
*/
|
||||
// create table if not exists multi_update_test
|
||||
// (C1 bigint primary key, C2 double, C3 varchar(100) default 'hello world')
|
||||
// PARTITION BY KEY(C1) PARTITIONS 16
|
||||
@ -7595,7 +7594,7 @@ TEST_F(TestBatchExecute, complex_batch_execute)
|
||||
}
|
||||
service_client_->free_table(the_table);
|
||||
}
|
||||
|
||||
/*
|
||||
TEST_F(TestBatchExecute, increment_and_append_batch)
|
||||
{
|
||||
ObTable *the_table = NULL;
|
||||
@ -7737,7 +7736,7 @@ TEST_F(TestBatchExecute, increment_and_append_batch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
TEST_F(TestBatchExecute, htable_put)
|
||||
{
|
||||
// setup
|
||||
|
@ -2226,6 +2226,7 @@ typedef enum ObContextType {
|
||||
|| ((op) == T_FUN_SYS_JSON_EXISTS) \
|
||||
|| ((op) == T_BOOL) \
|
||||
|| ((op) == T_OP_XOR) \
|
||||
|| ((op) == T_FUN_SYS_IS_UUID) \
|
||||
|| ((op) == T_FUN_SYS_ST_CONTAINS) \
|
||||
|| ((op) == T_FUN_SYS_ST_WITHIN) \
|
||||
|| ((op) == T_FUN_SYS_ST_DWITHIN) \
|
||||
@ -2342,6 +2343,12 @@ inline ObItemType get_opposite_compare_type(ObItemType src_type)
|
||||
case T_OP_GE:
|
||||
ret_type = T_OP_LE;
|
||||
break;
|
||||
case T_OP_EXISTS:
|
||||
ret_type = T_OP_NOT_EXISTS;
|
||||
break;
|
||||
case T_OP_NOT_EXISTS:
|
||||
ret_type = T_OP_EXISTS;
|
||||
break;
|
||||
default:
|
||||
ret_type = src_type;
|
||||
break;
|
||||
|
@ -117,6 +117,10 @@ public:
|
||||
inline bool is_calc_part_expr() const { return T_FUN_SYS_CALC_PARTITION_ID == type_
|
||||
|| T_FUN_SYS_CALC_TABLET_ID == type_
|
||||
|| T_FUN_SYS_CALC_PARTITION_TABLET_ID == type_; }
|
||||
inline bool is_basic_const_expr_mysql() const { return EXPR_CONST == expr_class_
|
||||
|| T_FUN_SYS_VERSION == type_
|
||||
|| T_FUN_SYS_OB_VERSION == type_
|
||||
|| T_FUN_SYS_ICU_VERSION == type_; }
|
||||
inline void set_expr_type(ObItemType v) { type_ = v; }
|
||||
inline ObItemType get_expr_type() const { return type_; }
|
||||
|
||||
|
@ -310,8 +310,12 @@ ob_set_subtarget(ob_server virtual_table
|
||||
virtual_table/ob_virtual_ash.cpp
|
||||
virtual_table/ob_virtual_sql_plan_statistics.cpp
|
||||
virtual_table/ob_virtual_table_iterator_factory.cpp
|
||||
virtual_table/ob_virtual_trace_log.cpp
|
||||
virtual_table/ob_all_virtual_dml_stats.cpp
|
||||
virtual_table/ob_virtual_span_info.cpp
|
||||
virtual_table/ob_virtual_show_trace.cpp
|
||||
virtual_table/ob_all_virtual_sql_plan.cpp
|
||||
virtual_table/ob_all_virtual_plan_table.cpp
|
||||
virtual_table/ob_all_virtual_plan_real_info.cpp
|
||||
)
|
||||
|
||||
ob_server_add_target(ob_server)
|
||||
|
@ -234,13 +234,12 @@ int ObMySQLRequestManager::get_mem_limit(uint64_t tenant_id,
|
||||
ObArenaAllocator alloc;
|
||||
ObObj obj_val;
|
||||
int64_t mem_pct = 0;
|
||||
const char* conf_name = "ob_sql_audit_percentage";
|
||||
if (OB_FAIL(ObBasicSessionInfo::get_global_sys_variable(tenant_id,
|
||||
alloc,
|
||||
ObDataTypeCastParams(),
|
||||
ObString(conf_name),
|
||||
ObString(OB_SV_SQL_AUDIT_PERCENTAGE),
|
||||
obj_val))) {
|
||||
LOG_WARN("failed to get global sys variable", K(ret), K(tenant_id), K(conf_name), K(obj_val));
|
||||
LOG_WARN("failed to get global sys variable", K(ret), K(tenant_id), K(OB_SV_SQL_AUDIT_PERCENTAGE), K(obj_val));
|
||||
} else if (OB_FAIL(obj_val.get_int(mem_pct))) {
|
||||
LOG_WARN("failed to get int", K(ret), K(obj_val));
|
||||
} else if (mem_pct < 0 || mem_pct > 100) {
|
||||
|
@ -48,6 +48,18 @@ int ObSyncCmdDriver::send_eof_packet(bool has_more_result)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
OMPKEOF eofp;
|
||||
|
||||
if (OB_FAIL(seal_eof_packet(has_more_result, eofp))) {
|
||||
LOG_WARN("failed to seal eof packet", K(ret), K(has_more_result));
|
||||
} else if (OB_FAIL(sender_.response_packet(eofp, &session_))) {
|
||||
LOG_WARN("response packet fail", K(ret), K(has_more_result));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSyncCmdDriver::seal_eof_packet(bool has_more_result, OMPKEOF& eofp)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObWarningBuffer *warnings_buf = common::ob_get_tsi_warning_buffer();
|
||||
uint16_t warning_count = 0;
|
||||
if (OB_ISNULL(warnings_buf)) {
|
||||
@ -75,12 +87,6 @@ int ObSyncCmdDriver::send_eof_packet(bool has_more_result)
|
||||
&& OB_FAIL(sender_.update_last_pkt_pos())) {
|
||||
LOG_WARN("failed to update last packet pos", K(ret));
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(sender_.response_packet(eofp, &session_))) {
|
||||
LOG_WARN("response packet fail", K(ret), K(has_more_result));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -100,6 +106,8 @@ int ObSyncCmdDriver::response_result(ObMySQLResultSet &result)
|
||||
int ret = OB_SUCCESS;
|
||||
bool process_ok = false;
|
||||
// for select SQL
|
||||
OMPKEOF eofp;
|
||||
bool need_send_eof = false;
|
||||
if (OB_FAIL(result.open())) {
|
||||
// 只有open失败的时候才可能重试,因open的时候会开启事务/语句等,并且没有给用户返回任何信息
|
||||
int cret = OB_SUCCESS;
|
||||
@ -133,8 +141,10 @@ int ObSyncCmdDriver::response_result(ObMySQLResultSet &result)
|
||||
LOG_WARN("close result set fail", K(cret));
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(send_eof_packet(result.has_more_result()))) {
|
||||
if (OB_FAIL(seal_eof_packet(result.has_more_result(), eofp))) {
|
||||
LOG_WARN("failed to send eof package", K(ret), K(result.has_more_result()));
|
||||
} else {
|
||||
need_send_eof = true;
|
||||
}
|
||||
}
|
||||
} else { /*do nothing*/ }
|
||||
@ -164,10 +174,20 @@ int ObSyncCmdDriver::response_result(ObMySQLResultSet &result)
|
||||
ok_param.is_partition_hit_ = session_.partition_hit().get_bool();
|
||||
ok_param.has_more_result_ = result.has_more_result();
|
||||
ok_param.has_pl_out_ = is_prexecute_ && result.is_with_rows() ? true : false;
|
||||
if (OB_FAIL(sender_.send_ok_packet(session_, ok_param))) {
|
||||
LOG_WARN("send ok packet fail", K(ok_param), K(ret));
|
||||
if (need_send_eof) {
|
||||
if (OB_FAIL(sender_.send_ok_packet(session_, ok_param, &eofp))) {
|
||||
LOG_WARN("send ok packet fail", K(ok_param), K(ret));
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(sender_.send_ok_packet(session_, ok_param))) {
|
||||
LOG_WARN("send ok packet fail", K(ok_param), K(ret));
|
||||
}
|
||||
}
|
||||
} else { /*do nothing*/ }
|
||||
} else {
|
||||
if (need_send_eof && OB_FAIL(sender_.response_packet(eofp, &session_))) {
|
||||
LOG_WARN("response packet fail", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!OB_SUCC(ret) && !process_ok && !retry_ctrl_.need_retry()) {
|
||||
|
@ -14,6 +14,7 @@
|
||||
#define OCEANBASE_OBSERVER_MYSQL_SYNC_CMD_DRIVER_
|
||||
|
||||
#include "observer/mysql/ob_query_driver.h"
|
||||
#include "rpc/obmysql/packet/ompk_eof.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
@ -44,6 +45,7 @@ public:
|
||||
virtual ~ObSyncCmdDriver();
|
||||
|
||||
int send_eof_packet(bool has_more_result);
|
||||
int seal_eof_packet(bool has_more_result, obmysql::OMPKEOF& eofp);
|
||||
virtual int response_query_result(sql::ObResultSet &result,
|
||||
bool is_ps_protocol,
|
||||
bool has_more_result,
|
||||
|
@ -126,6 +126,7 @@ int ObSyncPlanDriver::response_result(ObMySQLResultSet &result)
|
||||
process_ok = true;
|
||||
|
||||
OMPKEOF eofp;
|
||||
bool need_send_eof = false;
|
||||
const ObWarningBuffer *warnings_buf = common::ob_get_tsi_warning_buffer();
|
||||
uint16_t warning_count = 0;
|
||||
if (OB_ISNULL(warnings_buf)) {
|
||||
@ -154,9 +155,8 @@ int ObSyncPlanDriver::response_result(ObMySQLResultSet &result)
|
||||
&& OB_FAIL(sender_.update_last_pkt_pos())) {
|
||||
LOG_WARN("failed to update last packet pos", K(ret));
|
||||
}
|
||||
if (OB_SUCC(ret) && !result.get_is_com_filed_list() &&
|
||||
OB_FAIL(sender_.response_packet(eofp, &result.get_session()))) {
|
||||
LOG_WARN("response packet fail", K(ret));
|
||||
if (OB_SUCC(ret) && !result.get_is_com_filed_list()) {
|
||||
need_send_eof = true;
|
||||
}
|
||||
// for obproxy
|
||||
if (OB_SUCC(ret)) {
|
||||
@ -167,8 +167,18 @@ int ObSyncPlanDriver::response_result(ObMySQLResultSet &result)
|
||||
ok_param.affected_rows_ = 0;
|
||||
ok_param.is_partition_hit_ = session_.partition_hit().get_bool();
|
||||
ok_param.has_more_result_ = result.has_more_result();
|
||||
if (OB_FAIL(sender_.send_ok_packet(session_, ok_param))) {
|
||||
LOG_WARN("fail to send ok packt", K(ok_param), K(ret));
|
||||
if (need_send_eof) {
|
||||
if (OB_FAIL(sender_.send_ok_packet(session_, ok_param, &eofp))) {
|
||||
LOG_WARN("fail to send ok packt", K(ok_param), K(ret));
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(sender_.send_ok_packet(session_, ok_param))) {
|
||||
LOG_WARN("fail to send ok packt", K(ok_param), K(ret));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (need_send_eof && OB_FAIL(sender_.response_packet(eofp, &result.get_session()))) {
|
||||
LOG_WARN("response packet fail", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user