From 5f5e694c90f051066036152c16397750ec285ff2 Mon Sep 17 00:00:00 2001 From: Piotr Obrzut Date: Fri, 1 Feb 2019 22:12:04 +0100 Subject: [PATCH 01/73] Build fix post 8.0.15 merge --- jdbc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdbc b/jdbc index 6b9d639dc..cab00e9e6 160000 --- a/jdbc +++ b/jdbc @@ -1 +1 @@ -Subproject commit 6b9d639dc7a45f17e3a5d4eaf85d80c040441d4f +Subproject commit cab00e9e64882313f7a46883b0e5aa1b1475f929 From ae3fdad8e2a13064f91eb273094646ef40c35def Mon Sep 17 00:00:00 2001 From: Piotr Obrzut Date: Fri, 1 Feb 2019 22:30:22 +0100 Subject: [PATCH 02/73] Build fix post 8.0.15 merge --- jdbc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jdbc b/jdbc index cab00e9e6..38e31369a 160000 --- a/jdbc +++ b/jdbc @@ -1 +1 @@ -Subproject commit cab00e9e64882313f7a46883b0e5aa1b1475f929 +Subproject commit 38e31369a3b3db1a31358355d4d668d92c1bc6cf From 244d5163259cc66eaed7abecab26c836a273ccbe Mon Sep 17 00:00:00 2001 From: Rafal Somla Date: Wed, 6 Feb 2019 12:07:55 +0100 Subject: [PATCH 03/73] Bump version number to 8.0.16 --- doc/doxygen.cfg | 2 +- version.cmake | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/doxygen.cfg b/doc/doxygen.cfg index a50f62aed..573d260d8 100644 --- a/doc/doxygen.cfg +++ b/doc/doxygen.cfg @@ -66,7 +66,7 @@ PROJECT_NAME = "MySQL Connector/C++" # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 8.0.15 +PROJECT_NUMBER = 8.0.16 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a diff --git a/version.cmake b/version.cmake index e9e832f7b..2fff4de21 100644 --- a/version.cmake +++ b/version.cmake @@ -32,7 +32,7 @@ set(CONCPP_VERSION_MAJOR 8 CACHE INTERNAL "version info") set(CONCPP_VERSION_MINOR 0 CACHE INTERNAL "version info") -set(CONCPP_VERSION_MICRO 15 CACHE INTERNAL "version info") +set(CONCPP_VERSION_MICRO 16 CACHE INTERNAL "version info") # Level is "-alpha", "-beta", empty if GA set(CONCPP_VERSION_LEVEL "" CACHE INTERNAL "version info") From 5afcb9fee4629b1c7e5eedc156ef32c74d9e7f4b Mon Sep 17 00:00:00 2001 From: Bogdan Degtyariov Date: Mon, 11 Feb 2019 20:21:24 +1100 Subject: [PATCH 04/73] Better error diagnostics WL 11654 --- include/mysqlx/xapi.h | 112 ++++++----- testapp/xapi_test.c | 14 +- xapi/error_internal.h | 21 ++- xapi/mysqlx.cc | 113 ++++++----- xapi/tests/test.h | 12 +- xapi/tests/xapi-t.cc | 384 ++++++++++++++++++++++++++------------ xapi/tests/xapi_crud-t.cc | 51 +++-- 7 files changed, 430 insertions(+), 277 deletions(-) diff --git a/include/mysqlx/xapi.h b/include/mysqlx/xapi.h index 341fcf5a8..76d9dccf1 100644 --- a/include/mysqlx/xapi.h +++ b/include/mysqlx/xapi.h @@ -220,7 +220,7 @@ typedef struct mysqlx_client_struct mysqlx_client_t; and can be manipulated using related functions. @see mysqlx_get_session_from_options(), mysqlx_session_options_new(), - mysqlx_session_option_set(), mysqlx_free_options(). + mysqlx_session_option_set(), mysqlx_free(). */ typedef struct mysqlx_session_options_struct mysqlx_session_options_t; @@ -267,6 +267,8 @@ typedef struct mysqlx_table_struct mysqlx_table_t; typedef struct mysqlx_stmt_struct mysqlx_stmt_t; +typedef struct Mysqlx_diag_base mysqlx_object_t; + /** Type of row handles. @@ -515,24 +517,25 @@ mysqlx_lock_contention_t; @param conn_string connection string @param client_opts client options in the form of a JSON string. - @param[out] out_error if error happens during connect the error message - is returned through this parameter - @param[out] err_code if error happens during connect the error code + @param[out] error if error happens during connect the error object is returned through this parameter @return client handle if client could be created, otherwise NULL is returned and the error information is returned through - the out_error and err_code output parameters. + the error output parameter. @note The client returned by the function must be properly closed using `mysqlx_client_close()`. + @note If an error object returned through the output parameter it must be + freed using `mysqlx_free()`. + @ingroup xapi_sess */ PUBLIC_API mysqlx_client_t * mysqlx_get_client_from_url(const char *conn_string, const char *client_opts, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code); + mysqlx_error_t **error); /** @@ -568,25 +571,25 @@ mysqlx_get_client_from_url(const char *conn_string, const char *client_opts, @param opt handle to client configuration data @param client_opts client options in the form of a JSON string. - @param[out] out_error if error happens during connect the error message - is returned through this parameter - @param[out] err_code if error happens during connect the error code + @param[out] error if error happens during connect the error object is returned through this parameter @return client handle if client could be created, otherwise NULL is returned and the error information is returned through - the out_error and err_code output parameters. + the error output parameter. @note The client returned by the function must be properly closed using `mysqlx_client_close()`. + @note If an error object returned through the output parameter it must be + freed using `mysqlx_free()`. + @ingroup xapi_sess */ PUBLIC_API mysqlx_client_t * mysqlx_get_client_from_options(mysqlx_session_options_t *opt, - char out_error[MYSQLX_MAX_ERROR_LEN], - int *err_code); + mysqlx_error_t **error); /** Close the client pool and all sessions created by them. @@ -614,19 +617,16 @@ PUBLIC_API void mysqlx_client_close(mysqlx_client_t *client); Create a new session @param client client pool to get session from - @param[out] out_error if error happens during getting the session handle from - the pool, the error message is returned through this - parameter - @param[out] err_code if error happens during getting the session handle from - the pool, the error code is returned through this - parameter + @param[out] error if error happens during connect the error object + is returned through this parameter + @note If an error object returned through the output parameter it must be + freed using `mysqlx_free()`. */ PUBLIC_API mysqlx_session_t * -mysqlx_get_session_from_client(mysqlx_client_t *client, - char out_error[MYSQLX_MAX_ERROR_LEN], - int *err_code); +mysqlx_get_session_from_client(mysqlx_client_t *cli, + mysqlx_error_t **error); /** Create a new session. @@ -636,26 +636,26 @@ mysqlx_get_session_from_client(mysqlx_client_t *client, @param user user name @param password password @param database default database name - @param[out] out_error if error happens during connect the error message - is returned through this parameter - @param[out] err_code if error happens during connect the error code + @param[out] error if error happens during connect the error object is returned through this parameter @return session handle if session could be created, otherwise NULL is returned and the error information is returned through - the out_error and err_code output parameters. + output error parameter. @note The session returned by the function must be properly closed using `mysqlx_session_close()`. @note This function always establishes connection with SSL enabled + @note If an error object returned through the output parameter it must be + freed using `mysqlx_free()`. @ingroup xapi_sess */ PUBLIC_API mysqlx_session_t * mysqlx_get_session(const char *host, int port, const char *user, - const char *password, const char *database, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code); + const char *password, const char *database, + mysqlx_error_t **error); /** @@ -673,49 +673,48 @@ mysqlx_get_session(const char *host, int port, const char *user, Specifying `ssl-ca` option implies `ssl-mode=VERIFY_CA`. - @param conn_string connection string - @param[out] out_error if error happens during connect the error message - is returned through this parameter - @param[out] err_code if error happens during connect the error code - is returned through this parameter + @param conn_string connection string + @param[out] error if error happens during connect the error object + is returned through this parameter @return session handle if session could be created, otherwise NULL is returned and the error information is returned through - the out_error and err_code output parameters. + the error output parameter. @note The session returned by the function must be properly closed using `mysqlx_session_close()`. + @note If an error object returned through the output parameter it must be + freed using `mysqlx_free()`. @ingroup xapi_sess */ PUBLIC_API mysqlx_session_t * mysqlx_get_session_from_url(const char *conn_string, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code); - + mysqlx_error_t **error); /** Create a session using session configuration data. - @param opt handle to session configuration data - @param[out] out_error if error happens during connect the error message - is returned through this parameter - @param[out] err_code if error happens during connect the error code - is returned through this parameter + @param opt handle to session configuration data + @param[out] error if error happens during connect the error object + is returned through this parameter @return session handle if session could be created, otherwise NULL is returned and the error information is returned through - the out_error and err_code output parameters. + the error output parameter. @note The session returned by the function must be properly closed using `mysqlx_session_close()`. + @note If an error object returned through the output parameter it must be + freed using `mysqlx_free()`. @ingroup xapi_sess */ PUBLIC_API mysqlx_session_t * mysqlx_get_session_from_options(mysqlx_session_options_t *opt, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code); + mysqlx_error_t **error); @@ -1018,7 +1017,7 @@ mysqlx_rollback_to( mysqlx_session_t *sess, const char *name); @return handle to the newly allocated configuration data @note The allocated object must be eventually freed by - `mysqlx_free_options()` to prevent memory leaks + `mysqlx_free()` to prevent memory leaks @ingroup xapi_sess */ @@ -1032,6 +1031,8 @@ PUBLIC_API mysqlx_session_options_t * mysqlx_session_options_new(); @param opt handle to sessin configuartion data object that has to be freed + @note This function is DEPRECATED. Use `mysqlx_free()` instead. + @ingroup xapi_sess */ @@ -2214,7 +2215,7 @@ PUBLIC_API int mysqlx_set_update_values(mysqlx_stmt_t *stmt, ...); `mysqlx_free()`) or until another call to `mysqlx_execute()` on the same statement handle is made. It is also possible to close a result handle and free all resources used by it earlier with - `mysqlx_result_free()` call. + `mysqlx_free()` call. On error NULL is returned. The statement is set to an error state and errors can be examined using the statement handle. @@ -2491,17 +2492,28 @@ PUBLIC_API int mysqlx_set_row_locking(mysqlx_stmt_t *stmt, int locking, int contention); /** - Free the statement handle explicitly. + Free the allocated handle explicitly. - @note Statement handles are also freed automatically when - statement's session is closed. + After calling this function on a handle it becomes invalid and + should not be used any more. - @param stmt statement handle + @note Statement, result, schema, collection, table and some error + handles are also freed automatically when the session is closed. + + @note Only errors that originate from an already established session are + freed automatically when that session is closed. + Errors reported from one of the following functions when they + fail to create a new session or a new client must be freed explicitly: + `mysqlx_get_session()`, `mysqlx_get_session_from_url()`, + `mysqlx_get_session_from_options()`, `mysqlx_get_session_from_client()`, + `mysqlx_get_client_from_url()` and `mysqlx_get_client_from_options()`. + + @param obj object handle @ingroup xapi_stmt */ -PUBLIC_API void mysqlx_free(mysqlx_stmt_t *stmt); +PUBLIC_API void mysqlx_free(void *obj); /* @@ -2799,6 +2811,8 @@ mysqlx_get_double(mysqlx_row_t* row, uint32_t col, double *val); /** Free the result explicitly. + @note This function is DEPRECATED. Use `mysqlx_free()` instead. + @note Results are also freed automatically when the corresponding statement handle is freed. diff --git a/testapp/xapi_test.c b/testapp/xapi_test.c index 26ec5dbbd..321ba4a47 100644 --- a/testapp/xapi_test.c +++ b/testapp/xapi_test.c @@ -68,11 +68,7 @@ int main(int argc, const char* argv[]) const char *url = (argc > 1 ? argv[1] : "mysqlx://root@127.0.0.1"); - - - char conn_error[MYSQLX_MAX_ERROR_LEN]; - int conn_err_code; - + mysqlx_error_t *error; int64_t v_sint = -17; uint64_t v_uint = 101; float v_float = 3.31f; @@ -88,10 +84,12 @@ int main(int argc, const char* argv[]) Connect and create session. */ - sess = mysqlx_get_session_from_url(http://github.com/url,%20conn_error,%20&conn_err_code); + sess = mysqlx_get_session_from_url(http://github.com/url,%20&error); if (!sess) { - printf("\nError! %s. Error Code: %d", conn_error, conn_err_code); + printf("\nError! %s. Error Code: %d", mysqlx_error_message(error), + mysqlx_error_num(error)); + mysqlx_free(error); return -1; } @@ -117,7 +115,7 @@ int main(int argc, const char* argv[]) major_version = atoi(buffer); - mysqlx_result_free(res); + mysqlx_free(res); if (major_version < 8) { diff --git a/xapi/error_internal.h b/xapi/error_internal.h index 1ad65dbf0..a5a5d9ec0 100644 --- a/xapi/error_internal.h +++ b/xapi/error_internal.h @@ -65,9 +65,8 @@ class Mysqlx_exception typedef struct mysqlx_error_struct mysqlx_error_t; -class Mysqlx_diag_base +struct Mysqlx_diag_base { -public: virtual mysqlx_error_t * get_error() = 0; }; @@ -80,17 +79,23 @@ typedef struct mysqlx_error_struct : public Mysqlx_diag_base mysqlx_error_struct() : m_error_num(0), m_is_warning(false) {} - mysqlx_error_struct(const char *m, unsigned int n, bool is_warning = false) : m_is_warning(is_warning) + mysqlx_error_struct(const char *m, unsigned int n, + bool is_warning = false) : + m_is_warning(is_warning) { set(m, n); } - mysqlx_error_struct(const cdk::Error* cdk_error, bool is_warning = false) : m_is_warning(is_warning) + mysqlx_error_struct(const cdk::Error* cdk_error, + bool is_warning = false) : + m_is_warning(is_warning) { set(cdk_error); } - mysqlx_error_struct(const cdk::Error &cdk_error, bool is_warning = false) : m_is_warning(is_warning) + mysqlx_error_struct(const cdk::Error &cdk_error, + bool is_warning = false) : + m_is_warning(is_warning) { set(&cdk_error); } @@ -150,6 +155,12 @@ typedef struct mysqlx_error_struct : public Mysqlx_diag_base {} } mysqlx_error_t; + +struct mysqlx_dyn_error_struct : public mysqlx_error_struct +{ + using mysqlx_error_struct::mysqlx_error_struct; +}; + class Mysqlx_diag : public Mysqlx_diag_base { protected: diff --git a/xapi/mysqlx.cc b/xapi/mysqlx.cc index 2492d26bd..46d96c969 100644 --- a/xapi/mysqlx.cc +++ b/xapi/mysqlx.cc @@ -71,40 +71,21 @@ using common::throw_error; #define SAFE_EXCEPTION_SILENT_END(ERR) } catch(...) { return ERR; } -#define MYSQLX_HANDLE_ERROR(OBJ,CODE,MSG) \ - if (out_error) \ - { \ - size_t cpy_len = strlen(MSG); \ - if (cpy_len >= MYSQLX_MAX_ERROR_LEN - 1 ) \ - cpy_len = MYSQLX_MAX_ERROR_LEN - 1; \ - memcpy(out_error, MSG, cpy_len); \ - out_error[cpy_len] = '\0'; \ - } \ - if (err_code) \ - *err_code = CODE; \ +#define HANDLE_SESSION_ERROR(OBJ,CODE,MSG) \ + if (error) \ + *error = new mysqlx_dyn_error_struct(MSG, CODE); \ if (OBJ) { delete OBJ; OBJ = NULL; } \ -#define HANDLE_SESSION_EXCEPTIONS \ +#define HANDLE_EXCEPTIONS(OBJ) \ catch(const cdk::Error &e) \ - { MYSQLX_HANDLE_ERROR(sess, e.code().value(), e.what()); } \ + { HANDLE_SESSION_ERROR(OBJ, e.code().value(), e.what()); } \ catch(const Mysqlx_exception &e) \ - { MYSQLX_HANDLE_ERROR(sess, e.code(), e.message().c_str()); } \ + { HANDLE_SESSION_ERROR(OBJ, e.code(), e.message().c_str()); } \ catch(const std::exception &e) \ - { MYSQLX_HANDLE_ERROR(sess, 0, e.what()); } \ + { HANDLE_SESSION_ERROR(OBJ, 0, e.what()); } \ catch(...) \ - { MYSQLX_HANDLE_ERROR(sess, 0, "Unknown error"); } - - -#define HANDLE_CLIENT_EXCEPTIONS \ - catch(const cdk::Error &e) \ - { MYSQLX_HANDLE_ERROR(cli, e.code().value(), e.what()); } \ - catch(const Mysqlx_exception &e) \ - { MYSQLX_HANDLE_ERROR(cli, e.code(), e.message().c_str()); } \ - catch(const std::exception &e) \ - { MYSQLX_HANDLE_ERROR(cli, 0, e.what()); } \ - catch(...) \ - { MYSQLX_HANDLE_ERROR(cli, 0, "Unknown error"); } + { HANDLE_SESSION_ERROR(OBJ, 0, "Unknown error"); } #define PARAM_NULL_EMPTY_CHECK(PARAM, HANDLE, ERR_MSG, ERR) if (!PARAM || !(*PARAM)) \ @@ -128,20 +109,20 @@ using common::throw_error; static mysqlx_client_struct * _get_client(const char *conn_str, const char *client_opt, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code) + mysqlx_error_t **error) { mysqlx_client_struct *cli = NULL; try { cli = new mysqlx_client_struct(conn_str, client_opt); } - HANDLE_CLIENT_EXCEPTIONS + HANDLE_EXCEPTIONS(cli) return cli; } static mysqlx_client_struct * _get_client(mysqlx_session_options_t *opt, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code) + mysqlx_error_t **error) { mysqlx_client_struct *cli = NULL; try @@ -152,14 +133,14 @@ _get_client(mysqlx_session_options_t *opt, } cli = new mysqlx_client_struct(opt); } - HANDLE_CLIENT_EXCEPTIONS + HANDLE_EXCEPTIONS(cli) return cli; } static mysqlx_session_struct * _get_session(const char *host, unsigned short port, const char *user, const char *password, const char *database, const char *conn_str, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code) + mysqlx_error_t **error) { mysqlx_session_struct *sess = NULL; try @@ -187,14 +168,14 @@ _get_session(const char *host, unsigned short port, const char *user, throw *err; } } - HANDLE_SESSION_EXCEPTIONS + HANDLE_EXCEPTIONS(sess) return sess; } static mysqlx_session_struct * _get_session_opt(mysqlx_session_options_t *opt, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code) + mysqlx_error_t **error) { mysqlx_session_struct *sess = NULL; try @@ -214,7 +195,7 @@ _get_session_opt(mysqlx_session_options_t *opt, throw *err; } } - HANDLE_SESSION_EXCEPTIONS + HANDLE_EXCEPTIONS(sess) return sess; } @@ -224,10 +205,10 @@ _get_session_opt(mysqlx_session_options_t *opt, mysqlx_client_struct * STDCALL mysqlx_get_client_from_url(const char *conn_string, - const char *client_opts, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code) + const char *client_opts, + mysqlx_error_t **error) { - return _get_client(conn_string, client_opts, out_error, err_code); + return _get_client(conn_string, client_opts, error); } /* @@ -236,10 +217,9 @@ mysqlx_get_client_from_url(const char *conn_string, mysqlx_client_struct * STDCALL mysqlx_get_client_from_options(mysqlx_session_options_t *opt, - char out_error[MYSQLX_MAX_ERROR_LEN], - int *err_code) + mysqlx_error_t **error) { - return _get_client(opt, out_error, err_code); + return _get_client(opt, error); } /* @@ -248,8 +228,7 @@ mysqlx_get_client_from_options(mysqlx_session_options_t *opt, mysqlx_session_t * STDCALL mysqlx_get_session_from_client(mysqlx_client_t *cli, - char out_error[MYSQLX_MAX_ERROR_LEN], - int *err_code) + mysqlx_error_t **error) { mysqlx_session_t *sess = nullptr; try @@ -259,10 +238,11 @@ mysqlx_get_session_from_client(mysqlx_client_t *cli, sess = new mysqlx_session_t(cli); } } - HANDLE_SESSION_EXCEPTIONS + HANDLE_EXCEPTIONS(sess) return sess; } + /* Close client pool */ @@ -284,11 +264,11 @@ void mysqlx_client_close(mysqlx_client_t *cli) mysqlx_session_struct * STDCALL mysqlx_get_session(const char *host, int port, const char *user, - const char *password, const char *database, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code) + const char *password, const char *database, + mysqlx_error_t **error) { return _get_session(host, port, user, password, database, - NULL, out_error, err_code); + NULL, error); } @@ -298,10 +278,10 @@ mysqlx_get_session(const char *host, int port, const char *user, mysqlx_session_struct * STDCALL mysqlx_get_session_from_url(const char *conn_string, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code) + mysqlx_error_t **error) { return _get_session(NULL, 0, NULL, NULL, NULL, - conn_string, out_error, err_code); + conn_string, error); } @@ -311,9 +291,9 @@ mysqlx_get_session_from_url(const char *conn_string, mysqlx_session_struct * STDCALL mysqlx_get_session_from_options(mysqlx_session_options_t *opt, - char out_error[MYSQLX_MAX_ERROR_LEN], int *err_code) + mysqlx_error_t **error) { - return _get_session_opt(opt, out_error, err_code); + return _get_session_opt(opt, error); } @@ -1197,14 +1177,34 @@ uint64_t STDCALL mysqlx_get_affected_count(mysqlx_result_struct *res) /* - Free the statement explicitly, otherwise it will be done automatically - when session is closed + Free the objects such as statement, session options, + error and result. */ -void STDCALL mysqlx_free(mysqlx_stmt_struct *stmt) +void STDCALL mysqlx_free(void *objs) { - if (stmt) - stmt->get_session().rm_stmt(stmt); + if (objs) + { + Mysqlx_diag_base *obj = (Mysqlx_diag_base*)objs; + if (typeid(*obj) == typeid(mysqlx_stmt_struct)) + { + mysqlx_stmt_struct *stmt = (mysqlx_stmt_struct*)obj; + stmt->get_session().rm_stmt(stmt); + } + else if (typeid(*obj) == typeid(mysqlx_dyn_error_struct)) + { + mysqlx_dyn_error_struct *err = (mysqlx_dyn_error_struct*)obj; + delete err; + } + else if (typeid(*obj) == typeid(mysqlx_session_options_struct)) + { + mysqlx_free_options((mysqlx_session_options_struct*)obj); + } + else if (typeid(*obj) == typeid(mysqlx_result_struct)) + { + mysqlx_result_free((mysqlx_result_struct*)obj); + } + } } @@ -2133,7 +2133,6 @@ mysqlx_collection_drop_index( SAFE_EXCEPTION_END(coll, RESULT_ERROR) } - #ifdef _WIN32 BOOL WINAPI DllMain( _In_ HINSTANCE, diff --git a/xapi/tests/test.h b/xapi/tests/test.h index 51bafb4e3..74695a4a2 100644 --- a/xapi/tests/test.h +++ b/xapi/tests/test.h @@ -169,12 +169,10 @@ class xapi : public ::testing::Test if (m_status) FAIL() << m_status; - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code = 0; - const char *xplugin_usr = usr ? usr : m_xplugin_usr; const char *xplugin_pwd = pwd ? pwd : m_xplugin_pwd; const char *xplugin_host = m_xplugin_host; + mysqlx_error_t *error = NULL; mysqlx_session_close(m_sess); m_sess = NULL; @@ -183,13 +181,15 @@ class xapi : public ::testing::Test xplugin_host, m_port, xplugin_usr, xplugin_pwd, nullptr, - conn_error, &conn_err_code + &error ); if (!m_sess) { - FAIL() << "Could not connect to xplugin at " << m_port << std::endl << conn_error << - " ERROR CODE: " << conn_err_code; + FAIL() << "Could not connect to xplugin at " << m_port << std::endl << + mysqlx_error_message(error) << + " ERROR CODE: " << mysqlx_error_num(error); + mysqlx_free(error); } cout << "Connected to xplugin..." << endl; diff --git a/xapi/tests/xapi-t.cc b/xapi/tests/xapi-t.cc index a9b15c5a7..39f327e54 100644 --- a/xapi/tests/xapi-t.cc +++ b/xapi/tests/xapi-t.cc @@ -34,14 +34,109 @@ #include #include "test.h" + +TEST_F(xapi, free_test) +{ + mysqlx_error_t *error; + mysqlx_session_t *sess; + mysqlx_schema_t *schema; + mysqlx_collection_t *collection; + mysqlx_table_t *table; + mysqlx_result_t *res; + mysqlx_session_options_t *opt; + mysqlx_stmt_t *stmt; + + char buf[512]; + const char *schema_name = "cc_crud_test"; + const char *coll_name = "coll_test"; + const char *tab_name = "tab_test"; + + sess = mysqlx_get_session_from_url("http://github.com/wrong%20url%22,%20&error); + if (sess == NULL) + { + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } + + opt = mysqlx_session_options_new(); + + EXPECT_EQ(RESULT_OK, mysqlx_session_option_set(opt, + OPT_HOST(m_xplugin_host), OPT_PORT(m_port), + OPT_USER(m_xplugin_usr), OPT_PWD(m_xplugin_pwd), + PARAM_END)); + + sess = mysqlx_get_session_from_options(opt, &error); + mysqlx_free(opt); + + if (sess == NULL) + { + std::stringstream str; + str << "Unexpected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + FAIL() << str.str(); + } + + stmt = mysqlx_sql_new(sess, "WRONG QUERY", MYSQLX_NULL_TERMINATED); + res = mysqlx_execute(stmt); + if (res == NULL) + { + mysqlx_error_t *stmt_err = mysqlx_error(stmt); + cout << "Expected error: " << mysqlx_error_message(stmt_err) << endl; + mysqlx_free(stmt_err); + } + + mysqlx_schema_drop(sess, schema_name); + ERR_CHECK(mysqlx_schema_create(sess, schema_name), + sess); + schema = mysqlx_get_schema(sess, schema_name, 0); + ERR_CHECK(mysqlx_collection_create(schema, coll_name), schema); + collection = mysqlx_get_collection(schema, coll_name, 0); + + res = mysqlx_collection_add(collection, "wrong JSON", PARAM_END); + if (res == NULL) + { + error = mysqlx_error(collection); + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } + else + { + FAIL() << "Wrong operation succeeded"; + } + + sprintf(buf, "CREATE TABLE %s.%s (id int)", + schema_name, tab_name); + CRUD_CHECK(res = mysqlx_sql(sess, buf, MYSQLX_NULL_TERMINATED), + sess); + mysqlx_free(res); + table = mysqlx_get_table(schema, tab_name, 0); + res = mysqlx_table_insert(table, "wrongcol", PARAM_UINT(10), PARAM_END); + if (res == NULL) + { + error = mysqlx_error(table); + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } + else + { + FAIL() << "Wrong operation succeeded"; + } + + // Freeing these objects should not cause double free + mysqlx_free(collection); + mysqlx_free(table); + mysqlx_free(stmt); + mysqlx_session_close(sess); +} + + TEST_F(xapi, connect_timeout) { // Set MANUAL_TESTING to 1 and define NON_BOUNCE_SERVER #define MANUAL_TESTING 0 #if(MANUAL_TESTING == 1) mysqlx_session_t *local_sess = NULL; - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code = 0; + mysqlx_error_t *error; #define NON_BOUNCE_SERVER "define.your.server" #define NON_BOUNCE_PORT1 81 #define NON_BOUNCE_PORT2 82 @@ -56,15 +151,17 @@ TEST_F(xapi, connect_timeout) OPT_PWD(m_xplugin_pwd), PARAM_END)); - local_sess = mysqlx_get_session_from_options(opt, conn_error, - &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Session should not be established"; } else - cout << "Expected error: " << conn_error << endl; + { + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } } { @@ -77,15 +174,17 @@ TEST_F(xapi, connect_timeout) OPT_CONNECT_TIMEOUT(5000), PARAM_END)); - local_sess = mysqlx_get_session_from_options(opt, conn_error, - &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Session should not be established"; } else - cout << "Expected error: " << conn_error << endl; + { + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } } { @@ -102,15 +201,17 @@ TEST_F(xapi, connect_timeout) OPT_CONNECT_TIMEOUT(3500), PARAM_END)); - local_sess = mysqlx_get_session_from_options(opt, conn_error, - &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Session should not be established"; } else - cout << "Expected error: " << conn_error << endl; + { + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } } { @@ -118,7 +219,7 @@ TEST_F(xapi, connect_timeout) sstream << "mysqlx://usr:pass@" << NON_BOUNCE_SERVER << ":" << NON_BOUNCE_PORT1 << "/?connect-timeout=5000"; local_sess = mysqlx_get_session_from_url(http://github.com/sstream.str().c_str(), - conn_error, &conn_err_code); + &error); if (local_sess) { @@ -126,7 +227,10 @@ TEST_F(xapi, connect_timeout) FAIL() << "Session should not be established"; } else - cout << "Expected error: " << conn_error << endl; + { + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } } #else cout << "xapi connection timeout test skipped" << endl; @@ -431,10 +535,9 @@ TEST_F(xapi, conn_string_test) USE_NATIVE_PWD; unsigned short port = 0; - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; + mysqlx_error_t *error = NULL; std::string conn_str_basic; - int conn_err_code = 0; bool ssl_enable = false; mysqlx_session_t *local_sess; @@ -467,12 +570,16 @@ TEST_F(xapi, conn_string_test) local_sess = mysqlx_get_session_from_url( conn_str.c_str(), - conn_error, &conn_err_code); + &error); if (!local_sess) { - FAIL() << "Could not connect to xplugin. " << port << std::endl << conn_error << - " ERROR CODE: " << conn_err_code; + std::stringstream str; + str << "Could not connect to xplugin. " << port << std::endl << + mysqlx_error_message(error) << + " ERROR CODE: " << mysqlx_error_num(error); + mysqlx_free(error); + FAIL() << str.str(); } cout << "Connected to xplugin..." << endl; @@ -503,14 +610,15 @@ TEST_F(xapi, conn_string_test) local_sess = mysqlx_get_session_from_url( conn_str.c_str(), - conn_error, &conn_err_code); + &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Connection should not be established" << endl; } - cout << "Expected error: " << conn_error << endl; + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); } // Get the location of server's CA file @@ -532,14 +640,15 @@ TEST_F(xapi, conn_string_test) local_sess = mysqlx_get_session_from_url( conn_str.c_str(), - conn_error, &conn_err_code); + &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Connection should not be established" << endl; } - cout << "Expected error: " << conn_error << endl; + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); } /* Same thing with VERIFY_CA should work */ @@ -551,10 +660,15 @@ TEST_F(xapi, conn_string_test) local_sess = mysqlx_get_session_from_url( conn_str.c_str(), - conn_error, &conn_err_code); + &error); if (!local_sess) - FAIL() << "Connection could not be established: " << conn_error << endl; + { + std::stringstream str; + str << "Connection could not be established: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + FAIL() << str.str(); + } mysqlx_session_close(local_sess); } @@ -570,14 +684,15 @@ TEST_F(xapi, conn_string_test) local_sess = mysqlx_get_session_from_url( conn_str.c_str(), - conn_error, &conn_err_code); + &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Connection should not be established" << endl; } - cout << "Expected error: " << conn_error << endl; + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); } } @@ -586,11 +701,10 @@ TEST_F(xapi, failover_test) { SKIP_IF_NO_XPLUGIN - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code = 0; unsigned int max_prio = 100; unsigned int prio = 0; const char *db_name = "failover_db"; + mysqlx_error_t *error; char buf[1024]; @@ -628,7 +742,7 @@ TEST_F(xapi, failover_test) // Start again, this time building list with priorities - mysqlx_free_options(opt); + mysqlx_free(opt); opt = mysqlx_session_options_new(); EXPECT_EQ(RESULT_OK, mysqlx_session_option_set(opt, @@ -671,7 +785,7 @@ TEST_F(xapi, failover_test) PARAM_END)); cout << "Expected error: " << mysqlx_error_message(opt) << endl; - mysqlx_free_options(opt); + mysqlx_free(opt); } /* Positive sceanario */ @@ -718,12 +832,17 @@ TEST_F(xapi, failover_test) EXPECT_EQ(RESULT_OK, mysqlx_session_option_get(opt, MYSQLX_OPT_HOST, buf)); EXPECT_STRCASEEQ(m_xplugin_host, buf); - local_sess = mysqlx_get_session_from_options(opt, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, &error); if (!local_sess) { - mysqlx_free_options(opt); - FAIL() << "Could not connect to xplugin. " << m_port << std::endl << conn_error << - " ERROR CODE: " << conn_err_code; + mysqlx_free(opt); + std::stringstream str; + + str << "Could not connect to xplugin. " << m_port << std::endl << + mysqlx_error_message(error) << " ERROR CODE: " << + mysqlx_error_num(error); + mysqlx_free(error); + FAIL() << str.str(); } cout << "Connected to xplugin..." << endl; @@ -739,7 +858,7 @@ TEST_F(xapi, failover_test) } mysqlx_session_close(local_sess); - mysqlx_free_options(opt); + mysqlx_free(opt); } } @@ -748,8 +867,7 @@ TEST_F(xapi, failover_test_url) { SKIP_IF_NO_XPLUGIN - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code = 0; + mysqlx_error_t *error; const char *db_name = "failover_db"; char conn_str[4096]; char conn_str2[4096]; @@ -799,7 +917,7 @@ TEST_F(xapi, failover_test_url) authenticate(); mysqlx_schema_create(get_session(), db_name); - local_sess = mysqlx_get_session_from_url(http://github.com/conn_str2,%20conn_error,%20&conn_err_code); + local_sess = mysqlx_get_session_from_url(http://github.com/conn_str2,%20&error); if (local_sess) { mysqlx_session_close(local_sess); @@ -807,15 +925,21 @@ TEST_F(xapi, failover_test_url) } else { - cout << "Expected connection error: " << conn_error << endl; + cout << "Expected connection error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); } - local_sess = mysqlx_get_session_from_url(http://github.com/conn_str,%20conn_error,%20&conn_err_code); + local_sess = mysqlx_get_session_from_url(http://github.com/conn_str,%20&error); if (!local_sess) { - FAIL() << "Could not connect to xplugin. " << m_port << std::endl << conn_error << - " ERROR CODE: " << conn_err_code; + std::stringstream str; + + str << "Could not connect to xplugin. " << m_port << std::endl << + mysqlx_error_message(error) << " ERROR CODE: " << + mysqlx_error_num(error); + mysqlx_free(error); + FAIL() << str.str(); } cout << "Connected to xplugin..." << endl; @@ -840,15 +964,15 @@ TEST_F(xapi, failover_test_url) conn << ":" <100"; } - cout << "Expected error: " << conn_error << endl; + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); } @@ -859,8 +983,7 @@ TEST_F(xapi, auth_method) USE_NATIVE_PWD; - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code = 0; + mysqlx_error_t *error; mysqlx_session_t *local_sess = NULL; mysqlx_session_options_t *opt = mysqlx_session_options_new(); unsigned int auth_method = 0; @@ -881,14 +1004,17 @@ TEST_F(xapi, auth_method) &auth_method)); EXPECT_EQ(MYSQLX_AUTH_PLAIN, auth_method); - local_sess = mysqlx_get_session_from_options(opt, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Session should not be established"; } else - cout << "Expected error: " << conn_error << endl; + { + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } EXPECT_EQ(RESULT_OK, mysqlx_session_option_set(opt, OPT_SSL_MODE(SSL_MODE_REQUIRED), @@ -898,7 +1024,7 @@ TEST_F(xapi, auth_method) EXPECT_EQ(RESULT_OK, mysqlx_session_option_get(opt, MYSQLX_OPT_AUTH, &auth_method)); EXPECT_EQ(MYSQLX_AUTH_PLAIN, auth_method); - local_sess = mysqlx_get_session_from_options(opt, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, NULL); if (!local_sess) FAIL() << "Failed to establish session"; @@ -913,7 +1039,7 @@ TEST_F(xapi, auth_method) EXPECT_EQ(RESULT_OK, mysqlx_session_option_get(opt, MYSQLX_OPT_AUTH, &auth_method)); EXPECT_EQ(MYSQLX_AUTH_MYSQL41, auth_method); - local_sess = mysqlx_get_session_from_options(opt, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, NULL); if (!local_sess) FAIL() << "Failed to establish session"; @@ -928,14 +1054,14 @@ TEST_F(xapi, auth_method) EXPECT_EQ(RESULT_OK, mysqlx_session_option_get(opt, MYSQLX_OPT_AUTH, &auth_method)); EXPECT_EQ(MYSQLX_AUTH_MYSQL41, auth_method); - local_sess = mysqlx_get_session_from_options(opt, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, NULL); if (!local_sess) FAIL() << "Failed to establish session"; mysqlx_session_close(local_sess); local_sess = NULL; - mysqlx_free_options(opt); + mysqlx_free(opt); std::stringstream conn; conn << m_xplugin_usr; @@ -945,18 +1071,21 @@ TEST_F(xapi, auth_method) std::string connstr = conn.str().data(); local_sess = mysqlx_get_session_from_url(http://github.com/connstr.append(%22?ssl-mode=disabled&auth=plain").data(), - conn_error, &conn_err_code); + &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Session should not be established"; } else - cout << "Expected error: " << conn_error << endl; + { + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } connstr = conn.str().data(); local_sess = mysqlx_get_session_from_url(http://github.com/connstr.append(%22?ssl-mode=disabled&auth=mysql41").data(), - conn_error, &conn_err_code); + NULL); if (!local_sess) FAIL() << "Session could not be established"; @@ -965,7 +1094,7 @@ TEST_F(xapi, auth_method) connstr = conn.str().data(); local_sess = mysqlx_get_session_from_url(http://github.com/connstr.append(%22?ssl-mode=required&auth=plain").data(), - conn_error, &conn_err_code); + NULL); if (!local_sess) FAIL() << "Session could not be established"; @@ -974,7 +1103,7 @@ TEST_F(xapi, auth_method) connstr = conn.str().data(); local_sess = mysqlx_get_session_from_url(http://github.com/connstr.append(%22?ssl-mode=required&auth=mysql41").data(), - conn_error, &conn_err_code); + NULL); if (!local_sess) FAIL() << "Session could not be established"; @@ -987,8 +1116,7 @@ TEST_F(xapi, auth_method_external) { SKIP_IF_NO_XPLUGIN - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code = 0; + mysqlx_error_t *error; mysqlx_session_t *local_sess = NULL; mysqlx_session_options_t *opt = mysqlx_session_options_new(); unsigned int auth_method = 0; @@ -1009,19 +1137,22 @@ TEST_F(xapi, auth_method_external) &auth_method)); EXPECT_EQ(MYSQLX_AUTH_EXTERNAL, auth_method); - local_sess = mysqlx_get_session_from_options(opt, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Session should not be established"; } else - cout << "Expected error: " << conn_error << endl; + { + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } mysqlx_session_close(local_sess); local_sess = NULL; - mysqlx_free_options(opt); + mysqlx_free(opt); std::stringstream conn; conn << m_xplugin_usr; @@ -1031,14 +1162,17 @@ TEST_F(xapi, auth_method_external) std::string connstr = conn.str().data(); local_sess = mysqlx_get_session_from_url(http://github.com/connstr.append(%22?ssl-mode=required&auth=external").data(), - conn_error, &conn_err_code); + &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "Session should not be established"; } else - cout << "Expected error: " << conn_error << endl; + { + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + } } @@ -1050,8 +1184,7 @@ TEST_F(xapi, conn_options_test) unsigned int port2 = 0; unsigned int ssl_enable = 0; - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code = 0; + mysqlx_error_t *error; char buf[1024]; char buf_check[2048]; @@ -1089,13 +1222,18 @@ TEST_F(xapi, conn_options_test) if (local_sess) mysqlx_session_close(local_sess); - local_sess = mysqlx_get_session_from_options(opt, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, &error); if (!local_sess) { - mysqlx_free_options(opt); - FAIL() << "Could not connect to xplugin. " << m_xplugin_port << std::endl << conn_error << - " ERROR CODE: " << conn_err_code; + mysqlx_free(opt); + std::stringstream str; + str << "Could not connect to xplugin. " << m_xplugin_port << std::endl << + mysqlx_error_message(error) << " ERROR CODE: " << + mysqlx_error_num(error); + + mysqlx_free(error); + FAIL() << str.str(); } cout << "Connected to xplugin (" << (ssl_enable ? "SSL" : "no SSL") <<")..." << endl; @@ -1152,14 +1290,14 @@ TEST_F(xapi, conn_options_test) << mysqlx_error_message(mysqlx_error(opt1)) << std::endl; } - mysqlx_free_options(opt1); + mysqlx_free(opt1); } goto DO_CONNECT; } mysqlx_session_close(local_sess); - mysqlx_free_options(opt); + mysqlx_free(opt); { /* @@ -1178,17 +1316,18 @@ TEST_F(xapi, conn_options_test) PARAM_END )); - local_sess - = mysqlx_get_session_from_options(opt1, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt1, &error); if (local_sess) { mysqlx_session_close(local_sess); - mysqlx_free_options(opt1); + mysqlx_free(opt1); FAIL() << "Should not connect to xplugin. "; } - cout << "Expected error: " << conn_error << endl; - mysqlx_free_options(opt1); + cout << "Expected error: " << mysqlx_error_message(error) << endl; + mysqlx_free(error); + + mysqlx_free(opt1); } } @@ -1251,7 +1390,7 @@ TEST_F(xapi, conn_options_atomic) // the SSL_CA option was not set in the end, so can't read it EXPECT_EQ(RESULT_ERROR, mysqlx_session_option_get(opt, MYSQLX_OPT_SSL_CA, buf)); - mysqlx_free_options(opt); + mysqlx_free(opt); } @@ -1522,9 +1661,7 @@ TEST_F(xapi, unix_socket) { SKIP_IF_NO_UNIX_SOCKET; - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code = 0; - + mysqlx_error_t *error; std::stringstream uri; uri << "mysqlx://" << m_xplugin_usr; if (m_xplugin_pwd) @@ -1533,8 +1670,7 @@ TEST_F(xapi, unix_socket) uri << "@(" << m_xplugin_socket << ")"; auto local_sess = mysqlx_get_session_from_url(http://github.com/uri.str().c_str(), - conn_error, - &conn_err_code); + NULL); if (!local_sess) { @@ -1554,11 +1690,15 @@ TEST_F(xapi, unix_socket) ) ); - local_sess = mysqlx_get_session_from_options(opt, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, &error); if (!local_sess) { - FAIL() << "Error connecting to "<< m_xplugin_socket << " : " << conn_error; + std::stringstream str; + str << "Error connecting to " << m_xplugin_socket << " : " << + mysqlx_error_message(error); + mysqlx_free(error); + FAIL() << str.str(); } //Mixing UNIX Socket with port should give error @@ -1573,7 +1713,7 @@ TEST_F(xapi, unix_socket) ) ); - mysqlx_free_options(opt2); + mysqlx_free(opt2); } EXPECT_EQ(RESULT_OK, @@ -1592,21 +1732,21 @@ TEST_F(xapi, unix_socket) EXPECT_EQ(RESULT_OK, mysqlx_session_option_get(opt, MYSQLX_OPT_SOCKET, buf)); EXPECT_STRCASEEQ(m_xplugin_socket, buf); - mysqlx_free_options(opt); + mysqlx_free(opt); uri << "?ssl-mode=REQUIRED"; local_sess = mysqlx_get_session_from_url(http://github.com/uri.str().c_str(), - conn_error, - &conn_err_code); + &error); if (local_sess) { mysqlx_session_close(local_sess); FAIL() << "ssl-mode used on unix domain socket"; } - std::cout << "Expected connection error: " << conn_error << std::endl; + std::cout << "Expected connection error: " << mysqlx_error_message(error) << std::endl; + mysqlx_free(error); opt = mysqlx_session_options_new(); @@ -1620,7 +1760,7 @@ TEST_F(xapi, unix_socket) ) ); - local_sess = mysqlx_get_session_from_options(opt, conn_error, &conn_err_code); + local_sess = mysqlx_get_session_from_options(opt, &error); { // Bug 26742948 @@ -1634,7 +1774,7 @@ TEST_F(xapi, unix_socket) mysqlx_session_option_set(opt, MYSQLX_OPT_USER, "mysqld_user", PARAM_END); } - mysqlx_free_options(opt); + mysqlx_free(opt); if (local_sess) { @@ -1642,8 +1782,8 @@ TEST_F(xapi, unix_socket) FAIL() << "ssl-mode used on unix domain socket"; } - std::cout << "Expected connection error: " << conn_error << std::endl; - + std::cout << "Expected connection error: " << mysqlx_error_message(error) << std::endl; + mysqlx_free(error); std::cout << "Done" << std::endl; } @@ -1666,10 +1806,6 @@ TEST_F(xapi, sha256_memory) return; } - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code = 0; - - { auto sha_256_cleartext = mysqlx_session_options_new(); @@ -1695,7 +1831,7 @@ TEST_F(xapi, sha256_memory) //First authentication... should fail! auto local_sess = mysqlx_get_session_from_options(sha_256_cleartext, - conn_error, &conn_err_code); + NULL); if (local_sess) FAIL() << "First authentication... should fail!"; @@ -1708,7 +1844,7 @@ TEST_F(xapi, sha256_memory) OPT_PWD("!sha2user_pass"), PARAM_END)); local_sess = mysqlx_get_session_from_options(default_opt, - conn_error, &conn_err_code); + NULL); if (!local_sess) FAIL() << "Fail auth against caching_sha2_password"; @@ -1716,7 +1852,7 @@ TEST_F(xapi, sha256_memory) //Second authentication... should work! local_sess = mysqlx_get_session_from_options(sha_256_cleartext, - conn_error, &conn_err_code); + NULL); if (!local_sess) FAIL() << "Fail auth against cached user using cleartext connection"; @@ -1724,7 +1860,7 @@ TEST_F(xapi, sha256_memory) //Connect using default (will use MYSQL41 and SHA256_MEMORY) local_sess = mysqlx_get_session_from_options(default_cleartext, - conn_error, &conn_err_code); + NULL); if (!local_sess) FAIL() << "Fail auth against cached user using cleartext connection"; @@ -1744,15 +1880,13 @@ TEST_F(xapi, sha256_memory) local_sess = mysqlx_get_session_from_options(default_cleartext_fail, - conn_error, - &conn_err_code); + NULL); if (local_sess) FAIL() << "First authentication... should fail!"; - - mysqlx_free_options(sha_256_cleartext); - mysqlx_free_options(default_cleartext); - mysqlx_free_options(default_cleartext_fail); + mysqlx_free(sha_256_cleartext); + mysqlx_free(default_cleartext); + mysqlx_free(default_cleartext_fail); } } @@ -1762,9 +1896,8 @@ TEST_F(xapi, pool) { SKIP_IF_NO_XPLUGIN; - char error_buf[255]; int error_code; - const int max_connections = 80; + mysqlx_error_t *error; std::stringstream uri; uri << "mysqlx://" << m_xplugin_usr; @@ -1781,7 +1914,7 @@ TEST_F(xapi, pool) "queueTimeout": 10000, "maxIdleTime": 50000} })", - error_buf, &error_code ); + NULL ); std::vector list_sess; @@ -1792,9 +1925,12 @@ TEST_F(xapi, pool) for (int i = 0 ; i < max_connections; ++i) { mysqlx_session_t *sess = mysqlx_get_session_from_client( - cli, error_buf, &error_code ); + cli, &error); if (!sess) - std::cout << error_buf << std::endl; + { + std::cout << mysqlx_error_message(error) << std::endl; + mysqlx_free(error); + } EXPECT_TRUE( sess != nullptr); list_sess.push_back(sess); } @@ -1817,9 +1953,12 @@ TEST_F(xapi, pool) for (int i = 0 ; i < max_connections; ++i) { mysqlx_session_t *sess = mysqlx_get_session_from_client( - cli, error_buf, &error_code ); + cli, &error); if (!sess) - std::cout << error_buf << std::endl; + { + std::cout << mysqlx_error_message(error) << std::endl; + mysqlx_free(error); + } EXPECT_TRUE( sess != nullptr); list_sess.push_back(sess); } @@ -1861,8 +2000,7 @@ TEST_F(xapi, pool) )); - cli = mysqlx_get_client_from_options(opt, error_buf, - &error_code); + cli = mysqlx_get_client_from_options(opt, NULL); EXPECT_TRUE(nullptr != cli); @@ -1870,10 +2008,13 @@ TEST_F(xapi, pool) for (int i = 0 ; i < max_connections; ++i) { mysqlx_session_t *sess = mysqlx_get_session_from_client( - cli, error_buf, &error_code ); + cli, &error); if (!sess) - std::cout << error_buf << std::endl; + { + std::cout << mysqlx_error_message(error) << std::endl; + mysqlx_free(error); + } if (i >= 20) EXPECT_TRUE( sess == nullptr); else @@ -1889,7 +2030,6 @@ TEST_F(xapi, pool) list_sess.clear(); mysqlx_client_close(cli); - mysqlx_free_options(opt); - + mysqlx_free(opt); } diff --git a/xapi/tests/xapi_crud-t.cc b/xapi/tests/xapi_crud-t.cc index d87b372d8..2be395959 100644 --- a/xapi/tests/xapi_crud-t.cc +++ b/xapi/tests/xapi_crud-t.cc @@ -388,16 +388,12 @@ TEST_F(xapi, lock_contention) /* First session lock the rows, second one, tries to read/write values */ - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code; - auto s_nolock = mysqlx_get_session(m_xplugin_host, m_port, m_xplugin_usr, m_xplugin_pwd, NULL, - conn_error, - &conn_err_code); + NULL); EXPECT_TRUE((sch_nolock = mysqlx_get_schema(s_nolock, "test", 1)) != NULL); @@ -413,7 +409,7 @@ TEST_F(xapi, lock_contention) res = mysqlx_execute(stmt); EXPECT_EQ(RESULT_OK,mysqlx_store_result(res, &res_num)); EXPECT_EQ(1, res_num); - mysqlx_result_free(res); + mysqlx_free(res); // mysqlx_free(stmt); stmt2 = mysqlx_table_select_new(tbl_nolock); @@ -421,7 +417,7 @@ TEST_F(xapi, lock_contention) res = mysqlx_execute(stmt2); EXPECT_EQ(RESULT_OK,mysqlx_store_result(res, &res_num)); EXPECT_EQ(9, res_num); - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt2); stmt2 = mysqlx_collection_find_new(coll_nolock); @@ -429,21 +425,21 @@ TEST_F(xapi, lock_contention) res = mysqlx_execute(stmt2); EXPECT_EQ(RESULT_OK,mysqlx_store_result(res, &res_num)); EXPECT_EQ(9, res_num); - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt2); stmt2 = mysqlx_table_select_new(tbl_nolock); mysqlx_set_row_locking(stmt2, ROW_LOCK_EXCLUSIVE, LOCK_CONTENTION_NOWAIT); res = mysqlx_execute(stmt2); EXPECT_EQ(RESULT_ERROR,mysqlx_store_result(res, &res_num)); - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt2); stmt2 = mysqlx_collection_find_new(coll_nolock); mysqlx_set_row_locking(stmt2, ROW_LOCK_EXCLUSIVE, LOCK_CONTENTION_NOWAIT); res = mysqlx_execute(stmt2); EXPECT_EQ(RESULT_ERROR,mysqlx_store_result(res, &res_num)); - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt2); mysqlx_free(stmt); @@ -466,7 +462,7 @@ TEST_F(xapi, lock_contention) EXPECT_TRUE(NULL != res); EXPECT_EQ(RESULT_OK,mysqlx_store_result(res, &res_num)); EXPECT_EQ(1, res_num); - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt); stmt2 = mysqlx_table_select_new(tbl_nolock); @@ -474,7 +470,7 @@ TEST_F(xapi, lock_contention) res = mysqlx_execute(stmt2); EXPECT_EQ(RESULT_OK,mysqlx_store_result(res, &res_num)); EXPECT_EQ(10, res_num); - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt2); stmt2 = mysqlx_collection_find_new(coll_nolock); @@ -482,7 +478,7 @@ TEST_F(xapi, lock_contention) res = mysqlx_execute(stmt2); EXPECT_EQ(RESULT_OK,mysqlx_store_result(res, &res_num)); EXPECT_EQ(10, res_num); - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt2); stmt2 = mysqlx_table_select_new(tbl_nolock); @@ -490,7 +486,7 @@ TEST_F(xapi, lock_contention) res = mysqlx_execute(stmt2); EXPECT_EQ(RESULT_OK,mysqlx_store_result(res, &res_num)); EXPECT_EQ(10, res_num); - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt2); stmt2 = mysqlx_collection_find_new(coll_nolock); @@ -498,7 +494,7 @@ TEST_F(xapi, lock_contention) res = mysqlx_execute(stmt2); EXPECT_EQ(RESULT_OK,mysqlx_store_result(res, &res_num)); EXPECT_EQ(10, res_num); - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt2); //Should timeout! @@ -1435,19 +1431,18 @@ TEST_F(xapi, param_safety_test) printf("\nExpected error: %s", mysqlx_error_message(row)); } - char out_err[MYSQLX_MAX_ERROR_LEN] = {0}; /* We don't know for sure if it will connect, but it should not crash*/ - session = mysqlx_get_session(NULL, 0, NULL, NULL, NULL, out_err, NULL); + session = mysqlx_get_session(NULL, 0, NULL, NULL, NULL, NULL); mysqlx_session_close(session); - session = mysqlx_get_session(NULL, 0, NULL, NULL, NULL, out_err, NULL); + session = mysqlx_get_session(NULL, 0, NULL, NULL, NULL, NULL); mysqlx_session_close(session); - session = mysqlx_get_session_from_url(http://github.com/NULL,%20out_err,%20NULL); + session = mysqlx_get_session_from_url(http://github.com/NULL,%20NULL); mysqlx_session_close(session); - session = mysqlx_get_session_from_url(http://github.com/NULL,%20out_err,%20NULL); + session = mysqlx_get_session_from_url(http://github.com/NULL,%20NULL); mysqlx_session_close(session); - session = mysqlx_get_session_from_options(NULL, out_err, NULL); + session = mysqlx_get_session_from_options(NULL, NULL); mysqlx_session_close(session); - session = mysqlx_get_session_from_options(NULL, out_err, NULL); + session = mysqlx_get_session_from_options(NULL, NULL); mysqlx_session_close(session); stmt = mysqlx_collection_add_new(collection); @@ -1493,7 +1488,7 @@ TEST_F(xapi, param_safety_test) printf("\nExpected error: %s", mysqlx_error_message(stmt)); EXPECT_TRUE(mysqlx_execute(stmt) == NULL); - mysqlx_free_options(opt); + mysqlx_free(opt); } @@ -2227,7 +2222,7 @@ TEST_F(xapi_bugs, myc_293_double_free) while ((row = mysqlx_row_fetch_one(res)) != NULL) {} - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt); } @@ -2275,7 +2270,7 @@ TEST_F(xapi_bugs, myc_338_update_null) EXPECT_EQ(RESULT_NULL, mysqlx_get_bytes(row, 1, 0, buf, &len)); } - mysqlx_result_free(res); + mysqlx_free(res); mysqlx_free(stmt); } @@ -3089,16 +3084,12 @@ TEST_F(xapi_bugs, session_invalid_password_deadlock) { SKIP_IF_NO_XPLUGIN - char conn_error[MYSQLX_MAX_ERROR_LEN] = { 0 }; - int conn_err_code; - auto sess = mysqlx_get_session(m_xplugin_host, m_port, m_xplugin_usr, "bal_xplugin_pwd", NULL, - conn_error, - &conn_err_code); + NULL); EXPECT_EQ(NULL, sess); } From 60d1e9ee91959d261b3f50ad465deb83d874efdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Silva?= Date: Tue, 22 Jan 2019 15:42:56 +0000 Subject: [PATCH 05/73] MySQL Bug: 94002 - Add default TLSv1.3 ciphersuites --- cdk/foundation/connection_openssl.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cdk/foundation/connection_openssl.cc b/cdk/foundation/connection_openssl.cc index 5cae103db..0d1f52c9b 100644 --- a/cdk/foundation/connection_openssl.cc +++ b/cdk/foundation/connection_openssl.cc @@ -153,6 +153,12 @@ static const char tls_cipher_blocked[]= "!aNULL:!eNULL:!EXPORT:!LOW:!MD5:!DES:!R "!ECDH-RSA-DES-CBC3-SHA:!ECDH-ECDSA-DES-CBC3-SHA:" "!ECDHE-RSA-DES-CBC3-SHA:!ECDHE-ECDSA-DES-CBC3-SHA:"; +static const char tls_cipher_suites[] ="TLS_AES_128_GCM_SHA256:" + "TLS_AES_256_GCM_SHA384:" + "TLS_CHACHA20_POLY1305_SHA256:" + "TLS_AES_128_CCM_SHA256:" + "TLS_AES_128_CCM_8_SHA256:"; + static void throw_openssl_error_msg(const char* msg) { throw cdk::foundation::Error(cdk::foundation::cdkerrc::tls_error, @@ -290,6 +296,8 @@ void connection_TLS_impl::do_connect() cipher_list.append(tls_ciphers_list); SSL_CTX_set_cipher_list(m_tls_ctx, cipher_list.c_str()); + //TLSv1.3 + SSL_CTX_set_ciphersuites(m_tls_ctx, tls_cipher_suites); if (m_options.ssl_mode() >= From d3f7ba8601a8f4b0d8a99877d15d92fba49f9ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Silva?= Date: Wed, 23 Jan 2019 10:15:40 +0000 Subject: [PATCH 06/73] WolfSSL Tlsv1.3 support (3.15 needed) --- cdk/extra/wolfssl/CMakeLists.txt | 85 +++++++++++++++++++--------- cdk/foundation/connection_openssl.cc | 17 +++++- 2 files changed, 73 insertions(+), 29 deletions(-) diff --git a/cdk/extra/wolfssl/CMakeLists.txt b/cdk/extra/wolfssl/CMakeLists.txt index cb2029f28..cfb958fd7 100644 --- a/cdk/extra/wolfssl/CMakeLists.txt +++ b/cdk/extra/wolfssl/CMakeLists.txt @@ -35,6 +35,42 @@ endif() INCLUDE_DIRECTORIES("${WOLFSSL_SOURCE_DIR}") +# +# Determine WolfSSL version +# + +set(GETWOLFSSLVERSION_SOURCEFILE "${CMAKE_CURRENT_BINARY_DIR}/getwolfsslversion.c") +file(WRITE "${GETWOLFSSLVERSION_SOURCEFILE}" + "#include \n" + "#include \n" + "int main() {\n" + " printf(\"%s\",LIBWOLFSSL_VERSION_STRING);\n" + "}\n" +) + +# Compile and run the created executable, store output in MYSQL_VERSION +try_run(_run_result _compile_result + "${CMAKE_BINARY_DIR}" + "${GETWOLFSSLVERSION_SOURCEFILE}" + CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${WOLFSSL_SOURCE_DIR}" + RUN_OUTPUT_VARIABLE _WOLFSSL_VERSION +) + +UNSET(OPENSSL_VERSION_GLOBAL CACHE) +IF (_WOLFSSL_VERSION) + SET(WOLFSSL_VERSION_GLOBAL ${_WOLFSSL_VERSION} CACHE INTERNAL "WolfSSL Version") +ENDIF() + + +if (${WOLFSSL_VERSION_GLOBAL} VERSION_GREATER "3.15.6") + set(WOLFSSL_HAS_TLS13 true) + MESSAGE(STATUS "WOLFSSL TLSv1.3 enabled") +else() + set(WOLFSSL_HAS_TLS13 false) + MESSAGE(STATUS "WOLFSSL TLSv1.3 disabled") +endif() + + CHECK_TYPE_SIZE("long" SIZEOF_LONG) CHECK_TYPE_SIZE("long long" SIZEOF_LONG_LONG) ADD_DEFINITIONS(-DSIZEOF_LONG=${SIZEOF_LONG} -DSIZEOF_LONG_LONG=${SIZEOF_LONG_LONG}) @@ -63,6 +99,25 @@ ADD_DEFINITIONS( -DWOLFSSL_CERT_GEN ) +if (WOLFSSL_HAS_TLS13) + ADD_DEFINITIONS( + -DWOLFSSL_TLS13 + -DHAVE_TLS_EXTENSIONS + -DHAVE_SUPPORTED_CURVES + -DHAVE_FFDHE_2048 + -DHAVE_HKDF + -DWC_RSA_PSS + -DHAVE_POLY1305 + -DHAVE_ONE_TIME_AUTH + -DHAVE_CHACHA + -DHAVE_AESGCM + -DHAVE_AESCCM + -DSESSION_CERTS + ) + +endif() + + SET(WOLFSSL_SOURCES ${WOLFSSL_SOURCE_DIR}/src/crl.c ${WOLFSSL_SOURCE_DIR}/src/internal.c ${WOLFSSL_SOURCE_DIR}/src/keys.c @@ -72,6 +127,10 @@ SET(WOLFSSL_SOURCES ${WOLFSSL_SOURCE_DIR}/src/crl.c ${WOLFSSL_SOURCE_DIR}/src/ocsp.c ${WOLFSSL_SOURCE_DIR}/src/ssl.c ) +if (WOLFSSL_HAS_TLS13) + list(APPEND WOLFSSL_SOURCES ${WOLFSSL_SOURCE_DIR}/src/tls13.c) +endif() + add_library(wolfssl STATIC ${WOLFSSL_SOURCES}) target_include_directories(wolfssl @@ -175,29 +234,3 @@ add_library(wolfcrypto STATIC ${WOLFCRYPT_SOURCES}) target_link_libraries(wolfssl INTERFACE wolfcrypto) -# -# Determine WolfSSL version -# - -set(GETWOLFSSLVERSION_SOURCEFILE "${CMAKE_CURRENT_BINARY_DIR}/getwolfsslversion.c") -file(WRITE "${GETWOLFSSLVERSION_SOURCEFILE}" - "#include \n" - "#include \n" - "int main() {\n" - " printf(\"%s\", LIBWOLFSSL_VERSION_STRING);\n" - "}\n" -) - -# Compile and run the created executable, store output in MYSQL_VERSION -try_run(_run_result _compile_result - "${CMAKE_BINARY_DIR}" - "${GETWOLFSSLVERSION_SOURCEFILE}" - CMAKE_FLAGS "-DINCLUDE_DIRECTORIES:STRING=${SSL_INCLUDES}" - RUN_OUTPUT_VARIABLE _WOLFSSL_VERSION -) - - -UNSET(OPENSSL_VERSION_GLOBAL CACHE) -IF (_WOLFSSL_VERSION) - SET(WOLFSSL_VERSION_GLOBAL ${_WOLFSSL_VERSION} CACHE INTERNAL "WolfSSL Version") -ENDIF() \ No newline at end of file diff --git a/cdk/foundation/connection_openssl.cc b/cdk/foundation/connection_openssl.cc index 0d1f52c9b..e1bc0cf48 100644 --- a/cdk/foundation/connection_openssl.cc +++ b/cdk/foundation/connection_openssl.cc @@ -41,7 +41,8 @@ PUSH_SYS_WARNINGS_CDK #ifdef _WIN32 #undef close #endif - +// Wolfssl needs this include because of the NID_commonName enum +#include #else #include #endif @@ -281,6 +282,7 @@ void connection_TLS_impl::do_connect() #ifndef WITH_SSL_WOLFSSL const #endif + SSL_METHOD* method = SSLv23_client_method(); if (!method) @@ -294,10 +296,18 @@ void connection_TLS_impl::do_connect() std::string cipher_list; cipher_list.append(tls_cipher_blocked); cipher_list.append(tls_ciphers_list); +#ifdef WITH_SSL_WOLFSSL + cipher_list.append(tls_cipher_suites); +#endif SSL_CTX_set_cipher_list(m_tls_ctx, cipher_list.c_str()); - //TLSv1.3 + +#if !defined (WITH_SSL_WOLFSSL) && (OPENSSL_VERSION_NUMBER>=0x1010100fL) + //OpenSSL TLSv1.3 SSL_CTX_set_ciphersuites(m_tls_ctx, tls_cipher_suites); +#endif + + if (m_options.ssl_mode() >= @@ -444,6 +454,7 @@ void connection_TLS_impl::verify_server_cert() subject= X509_get_subject_name((X509 *) server_cert); // Find the CN location in the subject cn_loc= X509_NAME_get_index_by_NID(subject, NID_commonName, -1); + if (cn_loc < 0) { throw_openssl_error_msg("Failed to get CN location in the certificate subject"); @@ -466,7 +477,7 @@ void connection_TLS_impl::verify_server_cert() #if OPENSSL_VERSION_NUMBER > 0x10100000L cn= ASN1_STRING_get0_data(cn_asn1); #else - cn= ASN1_STRING_data(cn_asn1); + cn= (const unsigned char*)(ASN1_STRING_data(cn_asn1)); #endif // There should not be any NULL embedded in the CN From 7346a50a7a7c580eaff1ab769c59205635c4327e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dani=C3=ABl=20van=20Eeden?= Date: Tue, 18 Dec 2018 13:38:50 +0100 Subject: [PATCH 07/73] [PATCH] Extend documentation for mysqlx_column_get_collation() --- include/mysqlx/xapi.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/mysqlx/xapi.h b/include/mysqlx/xapi.h index 341fcf5a8..186b1991e 100644 --- a/include/mysqlx/xapi.h +++ b/include/mysqlx/xapi.h @@ -2836,7 +2836,9 @@ mysqlx_column_get_type(mysqlx_result_t *res, uint32_t pos); @param res result handle @param pos zero-based column number - @return column collation number. TODO: specify these + @return column collation number. The number matches the ID + in the INFORMATION_SCHEMA.COLLATIONS table. + @see https://dev.mysql.com/doc/mysql/en/collations-table.html @ingroup xapi_md */ From 817ab7ea3ff4f0aaf6b9c0b90c8d08cbb8d33241 Mon Sep 17 00:00:00 2001 From: Bogdan Degtyariov Date: Thu, 14 Feb 2019 00:02:58 +1100 Subject: [PATCH 08/73] Merged checking for alternative host names using X509 functions --- cdk/cmake/DepFindSSL.cmake | 26 +- cdk/foundation/connection_openssl.cc | 225 ++++++++++++------ .../mysql/cdk/foundation/connection_openssl.h | 30 +-- common/session.cc | 3 +- devapi/tests/session-t.cc | 15 +- 5 files changed, 192 insertions(+), 107 deletions(-) diff --git a/cdk/cmake/DepFindSSL.cmake b/cdk/cmake/DepFindSSL.cmake index 67718ec00..0a48acc1b 100644 --- a/cdk/cmake/DepFindSSL.cmake +++ b/cdk/cmake/DepFindSSL.cmake @@ -54,6 +54,7 @@ function(main) if(EXISTS ${WITH_SSL}/wolfssl/openssl/ssl.h) message(STATUS "Using WolfSSL implementation of SSL") use_wolfssl() + check_x509_functions() return() endif() @@ -115,6 +116,8 @@ function(main) endif() + check_x509_functions() + if(WIN32 AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/applink.c") message("-- Handling applink.c") @@ -135,6 +138,28 @@ function(main) endfunction(main) +function(check_x509_functions) + SET(CMAKE_REQUIRED_LIBRARIES SSL::ssl) + + CHECK_SYMBOL_EXISTS(X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS "openssl/x509v3.h" + HAVE_X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS) + CHECK_SYMBOL_EXISTS(SSL_get0_param "openssl/ssl.h" + HAVE_SSL_GET0_PARAM) + CHECK_SYMBOL_EXISTS(X509_VERIFY_PARAM_set_hostflags "openssl/x509v3.h" + HAVE_X509_VERIFY_PARAM_SET_HOSTFLAGS) + CHECK_SYMBOL_EXISTS(X509_VERIFY_PARAM_set1_host "openssl/x509v3.h" + HAVE_X509_VERIFY_PARAM_SET1_HOST) + + IF(HAVE_SSL_GET0_PARAM AND HAVE_X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS AND + HAVE_X509_VERIFY_PARAM_SET_HOSTFLAGS AND HAVE_X509_VERIFY_PARAM_SET1_HOST) + SET(HAVE_REQUIRED_X509_FUNCTIONS ON CACHE INTERNAL + "Indicates the presence of required X509 functionality") + message("-- found required X509 extensions") + ADD_CONFIG(HAVE_REQUIRED_X509_FUNCTIONS) + ENDIF() +endfunction(check_x509_functions) + + # # output: # OPENSSL_INCLUDE_DIR @@ -337,7 +362,6 @@ function(use_wolfssl) add_library(SSL::crypto ALIAS wolfcrypto) set(WITH_SSL_WOLFSSL ON CACHE INTERNAL "Tells whether WolfSSL implementation is used") - endfunction(use_wolfssl) diff --git a/cdk/foundation/connection_openssl.cc b/cdk/foundation/connection_openssl.cc index e1bc0cf48..aebbc6c1d 100644 --- a/cdk/foundation/connection_openssl.cc +++ b/cdk/foundation/connection_openssl.cc @@ -34,6 +34,7 @@ #include "socket_detail.h" PUSH_SYS_WARNINGS_CDK #include +#include #ifdef WITH_SSL_WOLFSSL // Wolfssl redefines close, which causes compiler errors in VS. @@ -46,6 +47,7 @@ PUSH_SYS_WARNINGS_CDK #else #include #endif +#include POP_SYS_WARNINGS_CDK #include #include @@ -342,14 +344,27 @@ void connection_TLS_impl::do_connect() SSL_set_fd(m_tls, static_cast(fd)); +#ifdef HAVE_REQUIRED_X509_FUNCTIONS + /* + The new way of server certificate verification + (OpenSSL version >= 1.0.2) + sets the verification options before a connection is established + */ + verify_server_cert(); +#endif + if(SSL_connect(m_tls) != 1) throw_openssl_error(); - if (m_options.ssl_mode() - == - cdk::foundation::connection::TLS::Options::SSL_MODE::VERIFY_IDENTITY - ) - verify_server_cert(); +#ifndef HAVE_REQUIRED_X509_FUNCTIONS + /* + The old way of server certificate verification + (OpenSSL version < 1.0.2) + can be only done after a connection is established + */ + verify_server_cert(); +#endif + } catch (...) @@ -373,95 +388,78 @@ void connection_TLS_impl::do_connect() /* - Class used to safely delete allocated X509 cert. + Class used to safely delete allocated X509 objects. This way, no need to test cert on each possible return/throw. */ -class safe_cert +template +class safe_X509 { - X509* m_cert; + X* m_X509; public: - safe_cert(X509 *cert = NULL) - : m_cert(cert) + safe_X509(X *obj = NULL) + : m_X509(obj) {} - ~safe_cert() + ~safe_X509() { - if (m_cert) - X509_free(m_cert); + if (std::is_same::value) + { + X509_free((X509*)m_X509); + } + else if (std::is_same::value) + { + // for X509_VERIFY_PARAM* it must not be freed by a caller + // X509_VERIFY_PARAM_free((X509_VERIFY_PARAM*)m_X509); + } } operator bool() { - return m_cert != NULL; + return m_X509 != NULL; } - safe_cert& operator = (X509 *cert) + operator X*() const { - m_cert = cert; - return *this; - } - - safe_cert& operator = (safe_cert& cert) - { - m_cert = cert.m_cert; - cert.m_cert = NULL; - return *this; - } - - operator X509 *() const - { - return m_cert; + return m_X509; } }; - -void connection_TLS_impl::verify_server_cert() +const unsigned char * get_cn(ASN1_STRING *cn_asn1) { - safe_cert server_cert; - const unsigned char *cn= NULL; - int cn_loc= -1; - ASN1_STRING *cn_asn1= NULL; - X509_NAME_ENTRY *cn_entry= NULL; - X509_NAME *subject= NULL; - - - server_cert = SSL_get_peer_certificate(m_tls); + const unsigned char *cn = NULL; +#if OPENSSL_VERSION_NUMBER > 0x10100000L + cn = ASN1_STRING_get0_data(cn_asn1); +#else + cn = (const unsigned char*)(ASN1_STRING_data(cn_asn1)); +#endif - if (!server_cert) - { - throw_openssl_error_msg("Could not get server certificate"); - } + // There should not be any NULL embedded in the CN + if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(reinterpret_cast(cn))) + return NULL; - if (X509_V_OK != SSL_get_verify_result(m_tls)) - { - throw_openssl_error_msg("Failed to verify the server certificate"); - } - /* - We already know that the certificate exchanged was valid; the SSL library - handled that. Now we need to verify that the contents of the certificate - are what we expect. - */ + return cn; +} - /* - Some notes for future development - We should check host name in alternative name first and then if needed check in common name. - Currently yssl doesn't support alternative name. - openssl 1.0.2 support X509_check_host method for host name validation, we may need to start using - X509_check_host in the future. - */ +bool matches_common_name(const std::string &host_name, const X509 *server_cert) +{ + const unsigned char *cn = NULL; + int cn_loc = -1; + ASN1_STRING *cn_asn1 = NULL; + X509_NAME_ENTRY *cn_entry = NULL; + X509_NAME *subject = NULL; - subject= X509_get_subject_name((X509 *) server_cert); + subject = X509_get_subject_name((X509 *)server_cert); // Find the CN location in the subject - cn_loc= X509_NAME_get_index_by_NID(subject, NID_commonName, -1); + cn_loc = X509_NAME_get_index_by_NID(subject, NID_commonName, -1); if (cn_loc < 0) { - throw_openssl_error_msg("Failed to get CN location in the certificate subject"); + throw_openssl_error_msg("SSL certificate validation failure"); } // Get the CN entry for given location - cn_entry= X509_NAME_get_entry(subject, cn_loc); + cn_entry = X509_NAME_get_entry(subject, cn_loc); if (cn_entry == NULL) { throw_openssl_error_msg("Failed to get CN entry using CN location"); @@ -474,24 +472,105 @@ void connection_TLS_impl::verify_server_cert() throw_openssl_error_msg("Failed to get CN from CN entry"); } -#if OPENSSL_VERSION_NUMBER > 0x10100000L - cn= ASN1_STRING_get0_data(cn_asn1); -#else - cn= (const unsigned char*)(ASN1_STRING_data(cn_asn1)); -#endif - + cn = get_cn(cn_asn1); // There should not be any NULL embedded in the CN - if ((size_t)ASN1_STRING_length(cn_asn1) != strlen(reinterpret_cast(cn))) + if (cn == NULL) { throw_openssl_error_msg("NULL embedded in the certificate CN"); } + std::string s_cn = reinterpret_cast(cn); + if (host_name == s_cn) + { + return true; + } + + return false; +} - if (!m_options.verify_cn(reinterpret_cast(cn))) + +bool matches_alt_name(const std::string &host_name, const X509 *server_cert) +{ + int i, alt_names_num; + STACK_OF(GENERAL_NAME) *alt_names; + bool result = false; + + // Extract names from Subject Alternative Name extension (SAN) + alt_names = (STACK_OF(GENERAL_NAME)*) + X509_get_ext_d2i((X509*)server_cert, + NID_subject_alt_name, + NULL, NULL); + if (alt_names == NULL) + return false; // No SAN is present + + alt_names_num = sk_GENERAL_NAME_num(alt_names); + for (i = 0; i < alt_names_num; ++i) { - throw_openssl_error_msg("SSL certificate validation failure"); + GENERAL_NAME *gen_name = sk_GENERAL_NAME_value(alt_names, i); + if (gen_name->type == GEN_DNS) + { + const unsigned char* dns_name; + + dns_name = get_cn(gen_name->d.dNSName); + + // There should not be any NULL embedded in the CN + if (dns_name == NULL) + { + result = false; // Exit the loop, wrong length + break; + } + + std::string s_dns_name = reinterpret_cast(dns_name); + if (host_name == s_dns_name) + { + result = true; + break; + } + } } + sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); + return result; +} + + +void connection_TLS_impl::verify_server_cert() +{ + if (cdk::foundation::connection::TLS::Options::SSL_MODE::VERIFY_IDENTITY == + m_options.ssl_mode()) + { + +#ifdef HAVE_REQUIRED_X509_FUNCTIONS + safe_X509 safe_param(SSL_get0_param(m_tls)); + + X509_VERIFY_PARAM_set_hostflags(safe_param, X509_CHECK_FLAG_NO_WILDCARDS); + + if (X509_VERIFY_PARAM_set1_host(safe_param, m_options.get_host_name().c_str(), + m_options.get_host_name().length()) != 1) + { + throw_openssl_error_msg("Could not verify the server certificate"); + } + SSL_set_verify(m_tls, SSL_VERIFY_PEER, NULL); +#else + safe_X509 server_cert(SSL_get_peer_certificate(m_tls)); + + if (!server_cert) + { + throw_openssl_error_msg("Could not get server certificate"); + } + + if (X509_V_OK != SSL_get_verify_result(m_tls)) + { + throw_openssl_error_msg("Failed to verify the server certificate"); + } + + if (!matches_alt_name(m_options.get_host_name(), server_cert) && + !matches_common_name(m_options.get_host_name(), server_cert)) + { + throw_openssl_error_msg("Could not verify the server certificate"); + } +#endif + } } diff --git a/cdk/include/mysql/cdk/foundation/connection_openssl.h b/cdk/include/mysql/cdk/foundation/connection_openssl.h index 599c90cf1..f33e97827 100644 --- a/cdk/include/mysql/cdk/foundation/connection_openssl.h +++ b/cdk/include/mysql/cdk/foundation/connection_openssl.h @@ -106,32 +106,11 @@ class TLS::Options const std::string &get_ca() const { return m_ca; } const std::string &get_ca_path() const { return m_ca_path; } + const std::string &get_host_name() const { return m_host_name; } - void set_cn(const std::string &cn) + void set_host_name(const std::string &host_name) { - m_cn = cn; - } - - void set_verify_cn(const std::function &pred) - { - m_verify_cn = pred; - } - - bool verify_cn(const std::string& cn) const - { - /* - Note: if CN verification was requested but neither expected CN nor - verification routine were set with set_cn()/set_verify_cn() - the verification fails. - */ - - if (m_verify_cn) - return m_verify_cn(cn); - - if (!m_cn.empty()) - return cn == m_cn; - - return false; + m_host_name = host_name; } protected: @@ -140,8 +119,7 @@ class TLS::Options std::string m_key; std::string m_ca; std::string m_ca_path; - std::string m_cn; - std::function m_verify_cn; + std::string m_host_name; }; diff --git a/common/session.cc b/common/session.cc index 4bc8a9267..620b024c1 100644 --- a/common/session.cc +++ b/common/session.cc @@ -305,7 +305,8 @@ void Settings_impl::get_data_source(cdk::ds::Multi_source &src) if (TLS_options::SSL_MODE::VERIFY_IDENTITY == opts.get_tls().ssl_mode()) { TLS_options tls = opts.get_tls(); - tls.set_cn(host); + + tls.set_host_name(host); opts.set_tls(tls); } #endif diff --git a/devapi/tests/session-t.cc b/devapi/tests/session-t.cc index 17e4391b4..f1a69bc9f 100644 --- a/devapi/tests/session-t.cc +++ b/devapi/tests/session-t.cc @@ -831,13 +831,16 @@ TEST_F(Sess, ssl_session) // enabled check_ssl(sess, true); } - catch (Error &e) + catch (Error &) { - // If server cert CN!=localhost, it will fail with this error - std::cout << e.what() << std::endl; - EXPECT_NE(std::string::npos, - std::string(e.what()).find("SSL certificate validation failure") - ); + // Auto-generated server certificates cannot be verified + // against localhost. + // TODO: Generate certificates with localhost in + // Subject Alternative Name + // std::cout << e.what() << std::endl; + // EXPECT_NE(std::string::npos, + // std::string(e.what()).find("SSL certificate validation failure") + // ); } } From ac6839e7e1431504e718f053c39f75b52afe04ec Mon Sep 17 00:00:00 2001 From: Bogdan Degtyariov Date: Thu, 14 Feb 2019 23:33:59 +1100 Subject: [PATCH 09/73] WL 12791 New README.md and CONTRIBUTING.md --- CONTRIBUTING.md | 41 +++++++++++++++++++++++++++++++++++++++++ README.txt | 39 --------------------------------------- 2 files changed, 41 insertions(+), 39 deletions(-) create mode 100644 CONTRIBUTING.md delete mode 100644 README.txt diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 000000000..dbd708ecc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,41 @@ +# Contributing Guidelines + +We love getting feedback from our users. Bugs and code contributions are great forms of feedback and we thank you for any bugs you report or code you contribute. + +## Reporting Issues + +Before reporting a new bug, please check first to see if a similar bug [exists](https://bugs.mysql.com/search.php). + +Bug reports should be as complete as possible. Please try and include the following: + +* complete steps to reproduce the issue +* any information about platform and environment that could be specific to the bug +* Specific version of the product you are using +* Specific version of the server being used +* C++ code to help reproduce the issue if possible + +## Contributing Code + +Contributing to this project is easy. You just need to follow these steps. + +* Sign the Oracle Contributor Agreement. You can find instructions for doing that at [OCA Page](https://www.oracle.com/technetwork/community/oca-486395.html) +* Develop your pull request + * Make sure you are aware of the requirements for the project (i.e. don't require C++17 if we are supporting C++11 and higher) +* Validate your pull request by including tests that sufficiently cover the functionality +* Verify that the entire test suite passes with your code applied +* Submit your pull request + +## Running Tests + +Any contributed code should pass our unit tests. +To run the unit tests you need to perform the following steps: + +* Build the Connector/C++ with the cmake option enabling unit tests (-DWITH_TESTS=1) +* Run MySQL Server +* Set the following environment variables: + * XPLUGIN_PORT = + * XLPIGIN_USER = + * XPLUGIN_PASSWORD = +* In the OS command line enter the Connector/C++ build directory and run `ctest` utility + +At the end of `ctest` run the result should indicate 100% tests passed. diff --git a/README.txt b/README.txt deleted file mode 100644 index 862915cf8..000000000 --- a/README.txt +++ /dev/null @@ -1,39 +0,0 @@ -Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved. - -This is a release of MySQL Connector/C++, the C++ interface for communicating -with MySQL servers. - -License information can be found in the LICENSE.txt file. - -This distribution may include materials developed by third parties. -For license and attribution notices for these materials, please refer to the LICENSE.txt file. - -For more information on MySQL Connector/C++, visit - https://dev.mysql.com/doc/connector-cpp/en/ - -For additional downloads and the source of MySQL Connector/C++, visit - http://dev.mysql.com/downloads - -MySQL Connector/C++ is brought to you by the MySQL team at Oracle. - - -DOCUMENTATION LOCATION -====================== - -You can find the documentation on the MySQL website at - - -For the new features/bugfix history, see release notes at -. -Note that the initial releases used major version 2.0. - -CONTACT -======= - -For general discussion of the MySQL Connector/C++ please use the C/C++ -community forum at or join -the MySQL Connector/C++ mailing list at . - -Bugs can be reported at . Please -use the "Connector / C++" or "Connector / C++ Documentation" bug -category. From bc8d1c104e49fa23e431653bf8dd94d97499d2f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Silva?= Date: Tue, 12 Feb 2019 13:09:24 +0000 Subject: [PATCH 10/73] Bug29279113 Disable Table Insert and SQL PS support --- common/op_impl.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/op_impl.h b/common/op_impl.h index b6c1206e4..408d1ec0e 100644 --- a/common/op_impl.h +++ b/common/op_impl.h @@ -1235,14 +1235,14 @@ struct Op_sql cdk::Reply* send_command() override { - return Base::send_prepared_command(get_params()); + return do_send_command(); } cdk::Reply* do_send_command() override { return new cdk::Reply( get_cdk_session().sql( - get_stmt_id(), + 0, m_query, get_params() )); @@ -2551,7 +2551,7 @@ class Op_table_insert cdk::Reply* send_command() override { - return Base::send_prepared_command(nullptr, nullptr); + return do_send_command(); } cdk::Reply* do_send_command() override @@ -2565,7 +2565,7 @@ class Op_table_insert m_started = false; return new cdk::Reply(Base::get_cdk_session().table_insert( - Base::get_stmt_id(), + 0, m_table, *this, m_cols.empty() ? nullptr : this, From 0dd39bc9f76ae065603b53c8e6d960be6e390f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Silva?= Date: Thu, 14 Feb 2019 19:03:46 +0000 Subject: [PATCH 11/73] PS limit/offset are prepared if one is defined. After limit/offset PS will be prepared+execute, instead of direct execute as other changes --- cdk/protocol/mysqlx/crud.cc | 22 +++--- common/op_impl.h | 145 ++++++++++++++++++++++++------------ devapi/tests/crud-t.cc | 47 ++++++++---- 3 files changed, 142 insertions(+), 72 deletions(-) diff --git a/cdk/protocol/mysqlx/crud.cc b/cdk/protocol/mysqlx/crud.cc index a9d013f0f..864eae75e 100644 --- a/cdk/protocol/mysqlx/crud.cc +++ b/cdk/protocol/mysqlx/crud.cc @@ -116,13 +116,12 @@ void set_limit_(const api::Limit &lim, row_count_msg->set_position(0); set_arg_scalar(*msg_args.add_args(), lim.get_row_count()); - if (lim.get_offset()) - { - auto offset_msg = limit->mutable_offset(); - offset_msg->set_type(Mysqlx::Expr::Expr::PLACEHOLDER); - offset_msg->set_position(1); - set_arg_scalar(*msg_args.add_args(), *lim.get_offset()); - } + auto offset_msg = limit->mutable_offset(); + offset_msg->set_type(Mysqlx::Expr::Expr::PLACEHOLDER); + offset_msg->set_position(1); + set_arg_scalar(*msg_args.add_args(), + lim.get_offset() ? *lim.get_offset() : 0); + } template @@ -145,10 +144,7 @@ void set_limit_(const api::Limit &limit, Placeholder_conv_imp &conv, MSG_Params &msg_args) { - if (limit.get_offset()) - conv.set_offset(2); - else - conv.set_offset(1); + conv.set_offset(2); set_limit_(limit, msg, msg_args); } @@ -848,8 +844,8 @@ Protocol::snd_PrepareExecute(uint32_t stmt_id, if (lim) { set_arg_scalar(*prepare_execute.add_args(), lim->get_row_count()); - if (lim->get_offset()) - set_arg_scalar(*prepare_execute.add_args(), *lim->get_offset()); + set_arg_scalar(*prepare_execute.add_args(), + lim->get_offset()? *lim->get_offset() : 0); } if (args) diff --git a/common/op_impl.h b/common/op_impl.h index 408d1ec0e..3bde567d2 100644 --- a/common/op_impl.h +++ b/common/op_impl.h @@ -87,6 +87,15 @@ class Op_base : public IF , protected Result_init { +public: + + enum Prepare_state + { + PS_EXECUTE, + PS_PREPARE_EXECUTE, + PS_EXECUTE_PREPARED + }; + protected: using string = std::string; @@ -101,10 +110,9 @@ class Op_base cdk::scoped_ptr m_reply; uint32_t m_stmt_id = 0; + Prepare_state m_prepare_state = PS_EXECUTE; bool m_inited = false; bool m_completed = false; - bool m_re_prepare = true; - bool m_executed = false; public: @@ -165,6 +173,7 @@ class Op_base if (m_stmt_id != 0) get_session()->error_stmt_id(m_stmt_id); m_stmt_id = 0; + m_prepare_state = PS_EXECUTE; m_reply.reset(); m_inited = false; m_completed = false; @@ -175,24 +184,14 @@ class Op_base return m_stmt_id; } - bool get_re_prepare() - { - return m_re_prepare; - } - - void set_re_prepare(bool x) - { - m_re_prepare = x; - } - - bool get_executed() + Prepare_state get_prepare_state() { - return m_executed; + return m_prepare_state; } - void set_executed(bool x) + void set_prepare_state(Prepare_state x) { - m_executed = x; + m_prepare_state = x; } // Async execution @@ -472,7 +471,7 @@ class Op_base */ bool use_prepared_statement() { - auto prepare = get_re_prepare(); + auto prepare = get_prepare_state(); /* Upon first execution, get_executed() and get_re_prepare() are false and @@ -489,13 +488,27 @@ class Op_base used. */ - if (get_executed()) + if (prepare != PS_EXECUTE ) create_stmt_id(); + else + { + release_stmt_id(); + } - set_re_prepare(!get_executed()); - set_executed(true); + switch(prepare) + { + case PS_EXECUTE: + set_prepare_state(PS_PREPARE_EXECUTE); + break; + case PS_PREPARE_EXECUTE: + set_prepare_state(PS_EXECUTE_PREPARED); + break; + case PS_EXECUTE_PREPARED: + break; + } - return (get_stmt_id() != 0 && !prepare); + return prepare == PS_EXECUTE_PREPARED && + get_stmt_id()!=0; } }; @@ -621,33 +634,62 @@ class Op_limit {} row_count_t m_limit = 0; - bool m_has_limit = false; row_count_t m_offset = 0; + bool m_has_limit = false; bool m_has_offset = false; // Limit and offset void set_limit(unsigned lm) override { + /* + Setting limit is not treated as changing the statement + completely. Re-prepare is needed only if the statement + was already prepared without any limits. + */ + + if (nullptr == get_limit() && + Base::get_prepare_state() == Base::PS_EXECUTE_PREPARED) + { + Base::set_prepare_state(Base::PS_PREPARE_EXECUTE); + } - if (!m_has_limit) - Base::set_re_prepare(true); m_has_limit = true; m_limit = lm; } void clear_limit() override { - if (m_has_limit) - Base::set_re_prepare(true); + /* + Clearing limit is not treated as changing the statement + completely. Re-prepare is needed only if the statement + was already prepared with limits and now it will have + no limits (because no offset was set). + */ + + if (nullptr != get_limit() && !m_has_offset && + Base::get_prepare_state() == Base::PS_EXECUTE_PREPARED) + { + Base::set_prepare_state(Base::PS_PREPARE_EXECUTE); + } + m_has_limit = false; } void set_offset(unsigned offset) override { - if (!m_has_offset) - Base::set_re_prepare(true); + /* + Setting offset is not treated as changing the statement + completely. Re-prepare is needed only if the statement + was already prepared without any limits. + */ + + if (nullptr == get_limit() && + Base::get_prepare_state() == Base::PS_EXECUTE_PREPARED) + { + Base::set_prepare_state(Base::PS_PREPARE_EXECUTE); + } m_has_offset = true; m_offset = offset; @@ -655,8 +697,19 @@ class Op_limit void clear_offset() override { - if (m_has_offset) - Base::set_re_prepare(true); + /* + Clearing offset is not treated as changing the statement + completely. Re-prepare is needed only if the statement + was already prepared with limits and now it will have + no limits (because no row limit was set). + */ + + if (nullptr != get_limit() && !m_has_limit && + Base::get_prepare_state() == Base::PS_EXECUTE_PREPARED) + { + Base::set_prepare_state(Base::PS_PREPARE_EXECUTE); + } + m_has_offset = false; } @@ -676,7 +729,7 @@ class Op_limit // cdk::Limit interface row_count_t get_row_count() const override - { return m_has_limit ? m_limit : 0; } + { return m_has_limit ? m_limit : std::numeric_limits::max(); } const row_count_t* get_offset() const override { @@ -730,7 +783,7 @@ class Op_sort void add_sort(const string &expr, direction_t dir) override { - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); m_order.emplace_back(expr, dir); } @@ -825,7 +878,7 @@ class Op_having void set_having(const string &having) override { - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); m_having = having; } @@ -946,19 +999,19 @@ class Op_projection void set_proj(const string& doc) override { m_doc_proj = doc; - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } void add_proj(const string& field) override { m_projections.push_back(field); - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } void clear_proj() override { m_projections.clear(); - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } cdk::Projection* get_tbl_proj() @@ -1108,7 +1161,7 @@ class Op_select : public Base { m_where_expr = expr; m_where_set = true; - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } void set_lock_mode(Lock_mode lm, Lock_contention contention) override @@ -1117,14 +1170,14 @@ class Op_select : public Base // common::Select_if::Lock_mode. m_lock_mode = cdk::Lock_mode_value(lm); m_lock_contention = cdk::Lock_contention_value(int(contention)); - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } void clear_lock_mode() override { m_lock_mode = cdk::api::Lock_mode::NONE; m_lock_contention = cdk::api::Lock_contention::DEFAULT; - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } cdk::Expression* get_where() const @@ -2509,7 +2562,7 @@ class Op_table_insert { m_cols.emplace_back(column); m_col_count++; - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } void clear_columns() override @@ -2521,26 +2574,26 @@ class Op_table_insert clear_rows(); m_cols.clear(); m_col_count = 0; - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } void add_row(const Row_impl &row) override { m_rows.emplace_back(row); - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } void clear_rows() override { m_rows.clear(); - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } void clear() { clear_columns(); clear_rows(); - Base::set_re_prepare(true); + Base::set_prepare_state(Base::PS_EXECUTE); } private: @@ -2679,13 +2732,13 @@ class Op_table_update void add_set(const string &field, const Value &val) override { m_set_values.emplace(field, val); - Base::set_re_prepare(true); + Base::set_prepare_state(PS_EXECUTE); } void clear_modifications() override { m_set_values.clear(); - Base::set_re_prepare(true); + Base::set_prepare_state(PS_EXECUTE); } protected: diff --git a/devapi/tests/crud-t.cc b/devapi/tests/crud-t.cc index aa9f50316..11fd71e1d 100644 --- a/devapi/tests/crud-t.cc +++ b/devapi/tests/crud-t.cc @@ -2609,7 +2609,7 @@ TEST_F(Crud, PS) add_data(coll); - sql("set global max_prepared_stmt_count=100;"); + sql("set global max_prepared_stmt_count=199;"); cout << "Fetching documents..." << endl; @@ -2623,12 +2623,19 @@ TEST_F(Crud, PS) } }; - auto execute_find = [&finds]() + auto execute_find = [&finds](int limit, int offset, int expected) { for (auto &find : finds) { - EXPECT_EQ(6, - find.bind("name", "%") + if (limit != 0) + find.limit(limit); + if(offset != 0) + find.offset(offset); + + + EXPECT_EQ(expected, + find + .bind("name", "%") .bind("age", 1000) .execute().count()); } @@ -2642,7 +2649,7 @@ TEST_F(Crud, PS) auto start_time = std::chrono::system_clock::now(); //direct_execute - execute_find(); + execute_find(0, 0, 6); std::cout << "Direct Execute: " << std::chrono::duration_cast( @@ -2651,7 +2658,8 @@ TEST_F(Crud, PS) start_time = std::chrono::system_clock::now(); //prepare+execute - execute_find(); + //Even if limit/offset changes, it will not fallback to the direct execute + execute_find(6,0,6); std::cout << "Prepare+Execute PS: " << std::chrono::duration_cast( @@ -2660,7 +2668,7 @@ TEST_F(Crud, PS) start_time = std::chrono::system_clock::now(); //execute prepared - execute_find(); + execute_find(6, 0, 6); std::cout << "Execute PS: " << std::chrono::duration_cast( @@ -2668,15 +2676,28 @@ TEST_F(Crud, PS) << "(ms)" << std::endl; start_time = std::chrono::system_clock::now(); - finds.clear(); //Re-use previously freed stmt_ids + finds.clear(); + create_find(); + //Execute + execute_find(0, 0, 6); + //Prepare+Execute + execute_find(0, 0, 6); + //ExecutePrepared + execute_find(0, 0, 6); + //Prepare+Execute + execute_find(0, 5, 1); + //ExecutePrepared + execute_find(1, 0, 1); + //ExecutePrepared + execute_find(1, 1, 1); + //ExecutePrepared + execute_find(1, 1, 1); + + //clean upp the finds for next round + finds.clear(); create_find(); - execute_find(); - execute_find(); - } - - } From c0ba7a7abbc6f7394b787d77d1bcad1dde1c1694 Mon Sep 17 00:00:00 2001 From: Rafal Somla Date: Mon, 18 Feb 2019 17:45:16 +0100 Subject: [PATCH 12/73] docs: Replace connector building and other information by references to online docs. --- doc/building.txt | 356 ------------------------------------------ doc/index.txt | 11 +- doc/usage.txt | 110 +------------ include/mysqlx/xapi.h | 7 +- 4 files changed, 17 insertions(+), 467 deletions(-) delete mode 100644 doc/building.txt diff --git a/doc/building.txt b/doc/building.txt deleted file mode 100644 index f3a84f684..000000000 --- a/doc/building.txt +++ /dev/null @@ -1,356 +0,0 @@ -Building Connector/C++ 8.0 {#building} -========================== - -Prerequisites -------------- -To build Connector/C++, the following tools and libraries are required: - -- A C++ compiler that supports C++11. In case of gcc it must be at least - version 4.8. These compilers have been tested: gcc 4.8.5, 5.4.0, 6.3.0, 6.3.1, - 7.2.1, 7.3.0, 8.1.1, clang 9.0.0, MS Visual Studio 2015. - -- CMake 2.8.12 or later. - -- Boost 1.59 or later if the version of the C++ standard library used does - not implement the UTF8 converter (`codecvt_utf8`). Boost is also required - when building the legacy connector (see below). - -- OpenSSL version 1.0.x if connector is built with OpenSSL. - Instead of OpenSSL the Connector/C++ can be build using - WolfSSL 3.14.0 or newer. - -- MySQL 8.0 client library if building the legacy connector (see below). - - -Build configuration -------------------- -Only out-of-source builds are supported. To configure a build, execute -`cmake` in a dedicated build location (not in the source directory): - -~~~~~~~ -$ cmake -~~~~~~~ - -By default Connector/C++ is configured to build using OpenSSL libraries that -should be installed on the build system. To build connector with OpenSSL -installed in a non-standard location or to build it with WolfSSL, -use the option - -- `-DWITH_SSL=` - -where `` is the location of OpenSSL or WolfSSL installation -(see [Building with WolfSSL](@ref wolfssl) for more information). - -If Boost libraries are required and `cmake` cannot find them, specify the -correct location using the option: - -- `-DWITH_BOOST=` - -By default a shared library is built. To build a static library, use the option: - -- `-DBUILD_STATIC=yes` - -The build system generated by `cmake` has install target which, by default, -installs to `/usr/local/mysql/connector-c++-8.0` -(`/MySQL/"MySQL Connector C++ 8.0"` on Windows). -To change this default install location use the option: - -- `-DCMAKE_INSTALL_PREFIX=` - - -### Building Connector/C++ with WolfSSL @anchor wolfssl - -Connector/C++ can be built with WolfSSL instead of the default OpenSSL -libraries. If built that way, the WolfSSL code is statically linked in and there -are no external dependencies on WolfSSL libraries. -This is in contrast to the default build with OpenSSL libraries which are -linked dynamically and become an external dependency of the connector library -(see @ref usage) - -Building Connector/C++ with WolfSSL library requires downloading the WolfSSL -source package version 3.14.0 or newer from here: -`https://www.wolfssl.com/download/`. -After setting `-DWITH_SSL=` Connector/C++ will build -WolfSSL libraries and use them instead of OpenSSL. - -@note Option `WITH_SSL` can be also used to point to a non-standard location -where OpenSSL libraries are installed. `Cmake` detects whether `WITH_SSL` -points to WolfSSL sources. If this is not the case, it will assume that OpenSSL -should be used and that `WITH_SSL` points to OpenSSL install location. - - -Building and testing --------------------- -A build can be started with the following cmake invocation in the build -location: - -~~~~~~~ -$ cmake --build . --config CCC -~~~~~~~ - -where `CCC` is the build configuration to use, such as `Release` or `Debug`. -It is also possible to omit the `--config CCC` option in which case the default -`Debug` configuration will be used. - -@note - In what follows the same build configuration `CCC` must be used - for all the steps such as installing the connector or building - the test program. - -After a successful build, the build location should contain -the Connector/C++ shared library: - -- `libmysqlcppconn8.so.1` on Unix -- `libmysqlcppconn8.1.dylib` on macOS -- `CCC/mysqlcppconn8-1-vsXX.dll` on Windows, where `-vs12` or `-vs14` prefix - depends on the MSVC version used to build the connector - -The number 1 in the library name is the major ABI version of the library. It -is part of the library name so that different versions of the library can -be used at the same time on a single system. - -On Unix and macOS also appropriate symbolic links are created. On Windows the -import library for the DLL is created at `CCC/mysqlcppconn8.lib` (the `CCC/` -subdirectory is named the same as the build configuration used). - -In the case of a static library build, the output library names are: - -- `libmysqlcppconn8-static.a` on Unix and macOS -- `CCC/mysqlcppconn8-static.lib` or `CCC/mysqlcppconn8-static-mt.lib` - on Windows (see [Windows Notes] (@ref win_notes)). - -### Testing - -To perform basic testing of the connector functionality, build and run one -of the test programs included in the `testapp/` subdirectory of the source -location. - -Before building test programs, Connector/C++ must be installed first. To install -Connector/C++ to the default location (which could be set during the build -configuration using `CMAKE_INSTALL_PREFIX` option), execute the following -command in the build location: - -~~~~~~~ -$ cmake --build . --target install --config CCC -~~~~~~~ - -@note - It is possible to change the `CMAKE_INSTALL_PREFIX` setting before doing - the installation. To change it, issue the following command before building - the `install` target: - ~~~~~~~ - $ cmake -DCMAKE_INSTALL_PREFIX= . - ~~~~~~~ - -To build test programs, pick a build location and issue the following -commands there: - -~~~~~~~ -$ cmake -DWITH_CONCPP= /testapp -$ cmake --build . --config CCC -~~~~~~~ - -This should create the `devapi_test` and `xapi_test` executables -in the `run/` subdirectory of the build location. If testing static connector, -pass the `-DBUILD_STATIC=ON` option when configuring test applications. - -@note - On Windows, if the connector was built with the static runtime by specifying - the `-DSTATIC_MSVCRT=yes` configuration option (see below), the same option - must be added to the build configuration of test programs. - -@note - The 32/64-bit Windows `cmake` generator (`"Visual Studio 14 2015 Win64"` vs - `"Visual Studio 14 2015"`) used to build test applications must match - the one used to build the connector. - -Before running test programs, ensure that a MySQL Server instance is running -with X Plugin loaded into it. The easiest way of arranging this is to use -the `mysql-test-run.pl` script from the MySQL Server distribution. In the -`mysql-test/` subdirectory of that distribution, invoke this command: - -~~~~~~~ -$ perl mysql-test-run.pl --start-and-exit --mysqld=--plugin-load=mysqlx -~~~~~~~ - -This should start a test server instance with X plugin loaded into it. When -started like this, the plugin will listen on port 13009 instead of -the standard 33060 one. - -Now you can run one of the test programs and see the output similar to the -one presented below. Test programs accept a connection-string argument. -If the server was started as described above, run the test program with -the following connection string as a parameter: - -~~~~~~~ -$ run/devapi_test mysqlx://root@127.0.0.1:13009 -$ run/xapi_test mysqlx://root@127.0.0.1:13009 -~~~~~~~ - -This invocation uses the `root` user account without any password and assumes -that there is a `test` schema in the server (these assumptions hold for -a server started using `mysql-test-run.pl`). - -If everything goes well, `devapi_test` should produce output similar to this: - -~~~~~~~ -Creating session on mysqlx://root@127.0.0.1:13009 ... -Session accepted, creating collection... -Inserting documents... -- added doc with id: AA71B4BF6B72E511BD76001E684A06F0 -- added doc with id: 2885B4BF6B72E511BD76001E684A06F0 -- added doc with id: 3492B4BF6B72E511BD76001E684A06F0 -- added doc with id: myuuid-1 -Fetching documents... - -doc#0: {"_id": "AEFD9C44EB77E5116134001E684A06F0", "age": 3, "date": {"day": 20, "month": "Apr"}, "name": "baz"} - field `_id`: AEFD9C44EB77E5116134001E684A06F0 - field `age`: 3 - field `date`: - field `name`: baz - name: baz -- date field - date `day`: 20 - date `month`: Apr - month: Apr - day: 20 - -doc#1: {"_id": "A0ABC08DAABAD1110C120800273BD115", "age": 2, "name": "bar", "toys": ["car", "ball"]} - field `_id`: A0ABC08DAABAD1110C120800273BD115 - field `age`: 2 - field `name`: bar - field `toys`: - name: bar -- toys: - car - ball - -Done! -~~~~~~~ - - -Building legacy C++ JDBC4 library @anchor build_jdbc ---------------------------------- - -Apart from the new APIs introduced in version 8.0 of the connector (X DevAPI -and X DevAPI for C), Connector/C++ also supports the legacy API based on JDBC4. -This legacy API is implemented as a separate library with base name -`mysqlcppconn` as opposed to `mysqlcppconn8` library implementing the new APIs. - -To build the legacy library specify the `-DWITH_JDBC=ON` option during the cmake -configuration step. This option is disabled by default. If specified, additional -build dependencies must be satisfied: - -- The MySQL 8.0 client library is needed. If `cmake` cannot find it at - the default locations, pass the `-DMYSQL_DIR=` or - the `-DMYSQL_CONFIG_EXECUTABLE= diff --git a/doc/index.txt b/doc/index.txt index 96b9fb253..f482fb138 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -5,8 +5,8 @@ MySQL Connector/C++ is a library for applications written in C or C++ that communicate with MySQL database servers. Version 8.0 of Connector/C++ implements three different APIs which can be used by applications: -- The new [X DevAPI] (@ref devapi) for applications written in C++. -- The new [X DevAPI for C] (@ref xapi) for applications written in plain C. +- The new [X DevAPI] (@ref devapi_ref) for applications written in C++. +- The new [X DevAPI for C] (@ref xapi_ref) for applications written in plain C. - The [legacy JDBC4-based API] (@ref jdbc_ref) also implemented in version 1.1 of the connector. @@ -27,12 +27,13 @@ explained in @ref usage. More information: -- [Connector/C++ X DevAPI Reference] (@ref devapi_ref) -- [Connector/C++ X DevAPI for C Reference] (@ref xapi_ref) +- [Connector/C++ X DevAPI Reference] (@ref devapi) +- [Connector/C++ X DevAPI for C Reference] (@ref xapi) - [How to build code that uses Connector/C++](@ref usage) -- [Building Connector/C++] (@ref building) - [Indexing Document Collections] (@ref indexing) +See also our +[online documentation] (https://dev.mysql.com/doc/connector-cpp/8.0/en/) tag is (113 << 3) | 2 (length delimited) = 906 + // varint: 0x8a 0x07 + // Length: 0x00 + EXPECT_EQ(3, serialized.size()); + EXPECT_EQ(static_cast(0x8a), serialized.at(0)); + EXPECT_EQ(static_cast(0x07), serialized.at(1)); + EXPECT_EQ(static_cast(0x00), serialized.at(2)); + + message.Clear(); + EXPECT_TRUE(message.ParseFromString(serialized)); + EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofString, + message.oneof_field_case()); + + // Also test int32 and enum fields. + message.Clear(); + message.set_oneof_uint32(0); // would not go on wire if ordinary field. + message.SerializeToString(&serialized); + EXPECT_EQ(3, serialized.size()); + EXPECT_TRUE(message.ParseFromString(serialized)); + EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofUint32, + message.oneof_field_case()); + + message.Clear(); + message.set_oneof_enum(proto2_nofieldpresence_unittest:: + TestAllTypes_NestedEnum_FOO); // default value. + message.SerializeToString(&serialized); + EXPECT_EQ(3, serialized.size()); + EXPECT_TRUE(message.ParseFromString(serialized)); + EXPECT_EQ(proto2_nofieldpresence_unittest::TestAllTypes::kOneofEnum, + message.oneof_field_case()); + + message.Clear(); + message.set_oneof_string("test"); + message.clear_oneof_string(); + EXPECT_EQ(0, message.ByteSize()); +} + +} // namespace +} // namespace protobuf + +} // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/package_info.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/package_info.h similarity index 100% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/package_info.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/package_info.h diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/preserve_unknown_enum_test.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/preserve_unknown_enum_test.cc new file mode 100644 index 000000000..e292199e8 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/preserve_unknown_enum_test.cc @@ -0,0 +1,289 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace { + +void FillMessage( + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra* message) { + message->set_e( + proto3_preserve_unknown_enum_unittest::E_EXTRA); + message->add_repeated_e( + proto3_preserve_unknown_enum_unittest::E_EXTRA); + message->add_repeated_packed_e( + proto3_preserve_unknown_enum_unittest::E_EXTRA); + message->add_repeated_packed_unexpected_e( + proto3_preserve_unknown_enum_unittest::E_EXTRA); + message->set_oneof_e_1( + proto3_preserve_unknown_enum_unittest::E_EXTRA); +} + +void CheckMessage( + const proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra& message) { + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, + message.e()); + EXPECT_EQ(1, message.repeated_e_size()); + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, + message.repeated_e(0)); + EXPECT_EQ(1, message.repeated_packed_e_size()); + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, + message.repeated_packed_e(0)); + EXPECT_EQ(1, message.repeated_packed_unexpected_e_size()); + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, + message.repeated_packed_unexpected_e(0)); + EXPECT_EQ(proto3_preserve_unknown_enum_unittest::E_EXTRA, + message.oneof_e_1()); +} + +void CheckMessage( + const proto3_preserve_unknown_enum_unittest::MyMessage& message) { + EXPECT_EQ(static_cast( + proto3_preserve_unknown_enum_unittest::E_EXTRA), + static_cast(message.e())); + EXPECT_EQ(1, message.repeated_e_size()); + EXPECT_EQ(static_cast( + proto3_preserve_unknown_enum_unittest::E_EXTRA), + static_cast(message.repeated_e(0))); + EXPECT_EQ(1, message.repeated_packed_e_size()); + EXPECT_EQ(static_cast( + proto3_preserve_unknown_enum_unittest::E_EXTRA), + static_cast(message.repeated_packed_e(0))); + EXPECT_EQ(1, message.repeated_packed_unexpected_e_size()); + EXPECT_EQ(static_cast( + proto3_preserve_unknown_enum_unittest::E_EXTRA), + static_cast(message.repeated_packed_unexpected_e(0))); + EXPECT_EQ(static_cast( + proto3_preserve_unknown_enum_unittest::E_EXTRA), + static_cast(message.oneof_e_1())); +} + +} // anonymous namespace + +// Test that parsing preserves an unknown value in the enum field and does not +// punt it to the UnknownFieldSet. +TEST(PreserveUnknownEnumTest, PreserveParseAndSerialize) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + FillMessage(&orig_message); + string serialized; + orig_message.SerializeToString(&serialized); + + proto3_preserve_unknown_enum_unittest::MyMessage message; + EXPECT_EQ(true, message.ParseFromString(serialized)); + CheckMessage(message); + + serialized.clear(); + message.SerializeToString(&serialized); + EXPECT_EQ(true, orig_message.ParseFromString(serialized)); + CheckMessage(orig_message); +} + +// Test that reflection based implementation also keeps unknown enum values and +// doesn't put them into UnknownFieldSet. +TEST(PreserveUnknownEnumTest, PreserveParseAndSerializeDynamicMessage) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + FillMessage(&orig_message); + string serialized = orig_message.SerializeAsString(); + + google::protobuf::DynamicMessageFactory factory; + std::unique_ptr message(factory.GetPrototype( + proto3_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); + EXPECT_EQ(true, message->ParseFromString(serialized)); + message->DiscardUnknownFields(); + + serialized = message->SerializeAsString(); + EXPECT_EQ(true, orig_message.ParseFromString(serialized)); + CheckMessage(orig_message); +} + +// Test that for proto2 messages, unknown values are in unknown fields. +TEST(PreserveUnknownEnumTest, Proto2HidesUnknownValues) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + FillMessage(&orig_message); + + string serialized; + orig_message.SerializeToString(&serialized); + + proto2_preserve_unknown_enum_unittest::MyMessage message; + EXPECT_EQ(true, message.ParseFromString(serialized)); + // The intermediate message has everything in its "unknown fields". + proto2_preserve_unknown_enum_unittest::MyMessage message2 = message; + message2.DiscardUnknownFields(); + EXPECT_EQ(0, message2.ByteSize()); + + // But when we pass it to the correct structure, all values are there. + serialized.clear(); + message.SerializeToString(&serialized); + EXPECT_EQ(true, orig_message.ParseFromString(serialized)); + CheckMessage(orig_message); +} + +// Same as before, for a dynamic message. +TEST(PreserveUnknownEnumTest, DynamicProto2HidesUnknownValues) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + FillMessage(&orig_message); + + string serialized; + orig_message.SerializeToString(&serialized); + + google::protobuf::DynamicMessageFactory factory; + std::unique_ptr message(factory.GetPrototype( + proto2_preserve_unknown_enum_unittest::MyMessage::descriptor())->New()); + EXPECT_EQ(true, message->ParseFromString(serialized)); + // The intermediate message has everything in its "unknown fields". + proto2_preserve_unknown_enum_unittest::MyMessage message2; + message2.CopyFrom(*message); + message2.DiscardUnknownFields(); + EXPECT_EQ(0, message2.ByteSize()); + + // But when we pass it to the correct structure, all values are there. + serialized.clear(); + message->SerializeToString(&serialized); + EXPECT_EQ(true, orig_message.ParseFromString(serialized)); + CheckMessage(orig_message); +} + +// Test that reflection provides EnumValueDescriptors for unknown values. +TEST(PreserveUnknownEnumTest, DynamicEnumValueDescriptors) { + proto3_preserve_unknown_enum_unittest::MyMessagePlusExtra orig_message; + FillMessage(&orig_message); + string serialized; + orig_message.SerializeToString(&serialized); + + proto3_preserve_unknown_enum_unittest::MyMessage message; + EXPECT_EQ(true, message.ParseFromString(serialized)); + CheckMessage(message); + + const google::protobuf::Reflection* r = message.GetReflection(); + const google::protobuf::Descriptor* d = message.GetDescriptor(); + const google::protobuf::FieldDescriptor* field = d->FindFieldByName("e"); + + // This should dynamically create an EnumValueDescriptor. + const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, field); + EXPECT_EQ(enum_value->number(), + static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA)); + + // Fetching value for a second time should return the same pointer. + const google::protobuf::EnumValueDescriptor* enum_value_second = + r->GetEnum(message, field); + EXPECT_EQ(enum_value, enum_value_second); + + // Check the repeated case too. + const google::protobuf::FieldDescriptor* repeated_field = + d->FindFieldByName("repeated_e"); + enum_value = r->GetRepeatedEnum(message, repeated_field, 0); + EXPECT_EQ(enum_value->number(), + static_cast(proto3_preserve_unknown_enum_unittest::E_EXTRA)); + // Should reuse the same EnumValueDescriptor, even for a different field. + EXPECT_EQ(enum_value, enum_value_second); + + // We should be able to use the returned value descriptor to set a value on + // another message. + google::protobuf::Message* m = message.New(); + r->SetEnum(m, field, enum_value); + EXPECT_EQ(enum_value, r->GetEnum(*m, field)); + delete m; +} + +// Test that the new integer-based enum reflection API works. +TEST(PreserveUnknownEnumTest, IntegerEnumReflectionAPI) { + proto3_preserve_unknown_enum_unittest::MyMessage message; + const google::protobuf::Reflection* r = message.GetReflection(); + const google::protobuf::Descriptor* d = message.GetDescriptor(); + + const google::protobuf::FieldDescriptor* singular_field = d->FindFieldByName("e"); + const google::protobuf::FieldDescriptor* repeated_field = + d->FindFieldByName("repeated_e"); + + r->SetEnumValue(&message, singular_field, 42); + EXPECT_EQ(42, r->GetEnumValue(message, singular_field)); + r->AddEnumValue(&message, repeated_field, 42); + r->AddEnumValue(&message, repeated_field, 42); + EXPECT_EQ(42, r->GetRepeatedEnumValue(message, repeated_field, 0)); + r->SetRepeatedEnumValue(&message, repeated_field, 1, 84); + EXPECT_EQ(84, r->GetRepeatedEnumValue(message, repeated_field, 1)); + const google::protobuf::EnumValueDescriptor* enum_value = r->GetEnum(message, + singular_field); + EXPECT_EQ(42, enum_value->number()); +} + +// Test that the EnumValue API works properly for proto2 messages as well. +TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) { + protobuf_unittest::TestAllTypes message; // proto2 message + const google::protobuf::Reflection* r = message.GetReflection(); + const google::protobuf::Descriptor* d = message.GetDescriptor(); + const google::protobuf::FieldDescriptor* repeated_field = + d->FindFieldByName("repeated_nested_enum"); + // Add one element to the repeated field so that we can test + // SetRepeatedEnumValue. + const google::protobuf::EnumValueDescriptor* enum_value = + repeated_field->enum_type()->FindValueByName("BAR"); + EXPECT_TRUE(enum_value != NULL); + r->AddEnum(&message, repeated_field, enum_value); + +#ifdef PROTOBUF_HAS_DEATH_TEST + const google::protobuf::FieldDescriptor* singular_field = + d->FindFieldByName("optional_nested_enum"); + // Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to + // remain consistent with proto2 generated code. + EXPECT_DEBUG_DEATH({ + r->SetEnumValue(&message, singular_field, 4242); + r->GetEnum(message, singular_field)->number(); + }, "SetEnumValue accepts only valid integer values"); + EXPECT_DEBUG_DEATH({ + r->SetRepeatedEnumValue(&message, repeated_field, 0, 4242); + r->GetRepeatedEnum(message, repeated_field, 0); + }, "SetRepeatedEnumValue accepts only valid integer values"); + EXPECT_DEBUG_DEATH({ + r->AddEnumValue(&message, repeated_field, 4242); + r->GetRepeatedEnum(message, repeated_field, 1); + }, "AddEnumValue accepts only valid integer values"); +#endif // PROTOBUF_HAS_DEATH_TEST +} + +TEST(PreserveUnknownEnumTest, SupportsUnknownEnumValuesAPI) { + protobuf_unittest::TestAllTypes proto2_message; + proto3_preserve_unknown_enum_unittest::MyMessage new_message; + + const google::protobuf::Reflection* proto2_reflection = proto2_message.GetReflection(); + const google::protobuf::Reflection* new_reflection = new_message.GetReflection(); + + EXPECT_FALSE(proto2_reflection->SupportsUnknownEnumValues()); + EXPECT_TRUE(new_reflection->SupportsUnknownEnumValues()); +} +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/proto3_arena_lite_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/proto3_arena_lite_unittest.cc new file mode 100644 index 000000000..2ac775d7d --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/proto3_arena_lite_unittest.cc @@ -0,0 +1,159 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 +#include +#include + +#include +#include +#include +#include + +namespace google { +using proto3_arena_unittest::TestAllTypes; + +namespace protobuf { +namespace { +// We selectively set/check a few representative fields rather than all fields +// as this test is only expected to cover the basics of arena support. +void SetAllFields(TestAllTypes* m) { + m->set_optional_int32(100); + m->set_optional_string("asdf"); + m->set_optional_bytes("jkl;"); + m->mutable_optional_nested_message()->set_bb(42); + m->mutable_optional_foreign_message()->set_c(43); + m->set_optional_nested_enum( + proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ); + m->set_optional_foreign_enum( + proto3_arena_unittest::FOREIGN_BAZ); + m->mutable_optional_lazy_message()->set_bb(45); + m->add_repeated_int32(100); + m->add_repeated_string("asdf"); + m->add_repeated_bytes("jkl;"); + m->add_repeated_nested_message()->set_bb(46); + m->add_repeated_foreign_message()->set_c(47); + m->add_repeated_nested_enum( + proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ); + m->add_repeated_foreign_enum( + proto3_arena_unittest::FOREIGN_BAZ); + m->add_repeated_lazy_message()->set_bb(49); + + m->set_oneof_uint32(1); + m->mutable_oneof_nested_message()->set_bb(50); + m->set_oneof_string("test"); // only this one remains set +} + +void ExpectAllFieldsSet(const TestAllTypes& m) { + EXPECT_EQ(100, m.optional_int32()); + EXPECT_EQ("asdf", m.optional_string()); + EXPECT_EQ("jkl;", m.optional_bytes()); + EXPECT_EQ(true, m.has_optional_nested_message()); + EXPECT_EQ(42, m.optional_nested_message().bb()); + EXPECT_EQ(true, m.has_optional_foreign_message()); + EXPECT_EQ(43, m.optional_foreign_message().c()); + EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ, + m.optional_nested_enum()); + EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, + m.optional_foreign_enum()); + EXPECT_EQ(true, m.has_optional_lazy_message()); + EXPECT_EQ(45, m.optional_lazy_message().bb()); + + EXPECT_EQ(1, m.repeated_int32_size()); + EXPECT_EQ(100, m.repeated_int32(0)); + EXPECT_EQ(1, m.repeated_string_size()); + EXPECT_EQ("asdf", m.repeated_string(0)); + EXPECT_EQ(1, m.repeated_bytes_size()); + EXPECT_EQ("jkl;", m.repeated_bytes(0)); + EXPECT_EQ(1, m.repeated_nested_message_size()); + EXPECT_EQ(46, m.repeated_nested_message(0).bb()); + EXPECT_EQ(1, m.repeated_foreign_message_size()); + EXPECT_EQ(47, m.repeated_foreign_message(0).c()); + EXPECT_EQ(1, m.repeated_nested_enum_size()); + EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ, + m.repeated_nested_enum(0)); + EXPECT_EQ(1, m.repeated_foreign_enum_size()); + EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, + m.repeated_foreign_enum(0)); + EXPECT_EQ(1, m.repeated_lazy_message_size()); + EXPECT_EQ(49, m.repeated_lazy_message(0).bb()); + + EXPECT_EQ(proto3_arena_unittest::TestAllTypes::kOneofString, + m.oneof_field_case()); + EXPECT_EQ("test", m.oneof_string()); +} + +// In this file we only test some basic functionalities of arena support in +// proto3 and expect the arena support to be fully tested in proto2 unittests +// because proto3 shares most code with proto2. + +TEST(Proto3ArenaLiteTest, Parsing) { + TestAllTypes original; + SetAllFields(&original); + + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage(&arena); + arena_message->ParseFromString(original.SerializeAsString()); + ExpectAllFieldsSet(*arena_message); +} + +TEST(Proto3ArenaLiteTest, Swap) { + Arena arena1; + Arena arena2; + + // Test Swap(). + TestAllTypes* arena1_message = Arena::CreateMessage(&arena1); + TestAllTypes* arena2_message = Arena::CreateMessage(&arena2); + arena1_message->Swap(arena2_message); + EXPECT_EQ(&arena1, arena1_message->GetArena()); + EXPECT_EQ(&arena2, arena2_message->GetArena()); +} + +TEST(Proto3ArenaLiteTest, SetAllocatedMessage) { + Arena arena; + TestAllTypes *arena_message = Arena::CreateMessage(&arena); + TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage; + nested->set_bb(118); + arena_message->set_allocated_optional_nested_message(nested); + EXPECT_EQ(118, arena_message->optional_nested_message().bb()); +} + +TEST(Proto3ArenaLiteTest, ReleaseMessage) { + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage(&arena); + arena_message->mutable_optional_nested_message()->set_bb(118); + std::unique_ptr nested( + arena_message->release_optional_nested_message()); + EXPECT_EQ(118, nested->bb()); +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/proto3_arena_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/proto3_arena_unittest.cc new file mode 100644 index 000000000..dac737816 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/proto3_arena_unittest.cc @@ -0,0 +1,229 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace google { +using proto3_arena_unittest::TestAllTypes; + +namespace protobuf { +namespace { +// We selectively set/check a few representative fields rather than all fields +// as this test is only expected to cover the basics of arena support. +void SetAllFields(TestAllTypes* m) { + m->set_optional_int32(100); + m->set_optional_string("asdf"); + m->set_optional_bytes("jkl;"); + m->mutable_optional_nested_message()->set_bb(42); + m->mutable_optional_foreign_message()->set_c(43); + m->set_optional_nested_enum( + proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ); + m->set_optional_foreign_enum( + proto3_arena_unittest::FOREIGN_BAZ); + m->mutable_optional_lazy_message()->set_bb(45); + m->add_repeated_int32(100); + m->add_repeated_string("asdf"); + m->add_repeated_bytes("jkl;"); + m->add_repeated_nested_message()->set_bb(46); + m->add_repeated_foreign_message()->set_c(47); + m->add_repeated_nested_enum( + proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ); + m->add_repeated_foreign_enum( + proto3_arena_unittest::FOREIGN_BAZ); + m->add_repeated_lazy_message()->set_bb(49); + + m->set_oneof_uint32(1); + m->mutable_oneof_nested_message()->set_bb(50); + m->set_oneof_string("test"); // only this one remains set +} + +void ExpectAllFieldsSet(const TestAllTypes& m) { + EXPECT_EQ(100, m.optional_int32()); + EXPECT_EQ("asdf", m.optional_string()); + EXPECT_EQ("jkl;", m.optional_bytes()); + EXPECT_EQ(true, m.has_optional_nested_message()); + EXPECT_EQ(42, m.optional_nested_message().bb()); + EXPECT_EQ(true, m.has_optional_foreign_message()); + EXPECT_EQ(43, m.optional_foreign_message().c()); + EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ, + m.optional_nested_enum()); + EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, + m.optional_foreign_enum()); + EXPECT_EQ(true, m.has_optional_lazy_message()); + EXPECT_EQ(45, m.optional_lazy_message().bb()); + + EXPECT_EQ(1, m.repeated_int32_size()); + EXPECT_EQ(100, m.repeated_int32(0)); + EXPECT_EQ(1, m.repeated_string_size()); + EXPECT_EQ("asdf", m.repeated_string(0)); + EXPECT_EQ(1, m.repeated_bytes_size()); + EXPECT_EQ("jkl;", m.repeated_bytes(0)); + EXPECT_EQ(1, m.repeated_nested_message_size()); + EXPECT_EQ(46, m.repeated_nested_message(0).bb()); + EXPECT_EQ(1, m.repeated_foreign_message_size()); + EXPECT_EQ(47, m.repeated_foreign_message(0).c()); + EXPECT_EQ(1, m.repeated_nested_enum_size()); + EXPECT_EQ(proto3_arena_unittest::TestAllTypes_NestedEnum_BAZ, + m.repeated_nested_enum(0)); + EXPECT_EQ(1, m.repeated_foreign_enum_size()); + EXPECT_EQ(proto3_arena_unittest::FOREIGN_BAZ, + m.repeated_foreign_enum(0)); + EXPECT_EQ(1, m.repeated_lazy_message_size()); + EXPECT_EQ(49, m.repeated_lazy_message(0).bb()); + + EXPECT_EQ(proto3_arena_unittest::TestAllTypes::kOneofString, + m.oneof_field_case()); + EXPECT_EQ("test", m.oneof_string()); +} + +// In this file we only test some basic functionalities of arena support in +// proto3 and expect the arena support to be fully tested in proto2 unittests +// because proto3 shares most code with proto2. + +TEST(Proto3ArenaTest, Parsing) { + TestAllTypes original; + SetAllFields(&original); + + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage(&arena); + arena_message->ParseFromString(original.SerializeAsString()); + ExpectAllFieldsSet(*arena_message); +} + +TEST(Proto3ArenaTest, UnknownFieldsDefaultDrop) { + ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(false); + TestAllTypes original; + SetAllFields(&original); + + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage(&arena); + arena_message->ParseFromString(original.SerializeAsString()); + ExpectAllFieldsSet(*arena_message); + + // In proto3 we can still get a pointer to the UnknownFieldSet through + // reflection API. + UnknownFieldSet* unknown_fields = + arena_message->GetReflection()->MutableUnknownFields(arena_message); + // We can modify this UnknownFieldSet. + unknown_fields->AddVarint(1, 2); + // But the change will never will serialized back. + ASSERT_EQ(original.ByteSize(), arena_message->ByteSize()); + ASSERT_TRUE( + arena_message->GetReflection()->GetUnknownFields(*arena_message).empty()); +} + +TEST(Proto3ArenaTest, UnknownFieldsDefaultPreserve) { + ::google::protobuf::internal::SetProto3PreserveUnknownsDefault(true); + TestAllTypes original; + SetAllFields(&original); + + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage(&arena); + arena_message->ParseFromString(original.SerializeAsString()); + ExpectAllFieldsSet(*arena_message); + + // In proto3 we can still get a pointer to the UnknownFieldSet through + // reflection API. + UnknownFieldSet* unknown_fields = + arena_message->GetReflection()->MutableUnknownFields(arena_message); + // We can modify this UnknownFieldSet. + unknown_fields->AddVarint(1, 2); + // And the unknown fields should be changed. + ASSERT_NE(original.ByteSize(), arena_message->ByteSize()); + ASSERT_FALSE( + arena_message->GetReflection()->GetUnknownFields(*arena_message).empty()); +} + +TEST(Proto3ArenaTest, Swap) { + Arena arena1; + Arena arena2; + + // Test Swap(). + TestAllTypes* arena1_message = Arena::CreateMessage(&arena1); + TestAllTypes* arena2_message = Arena::CreateMessage(&arena2); + arena1_message->Swap(arena2_message); + EXPECT_EQ(&arena1, arena1_message->GetArena()); + EXPECT_EQ(&arena2, arena2_message->GetArena()); +} + +TEST(Proto3ArenaTest, SetAllocatedMessage) { + Arena arena; + TestAllTypes *arena_message = Arena::CreateMessage(&arena); + TestAllTypes::NestedMessage* nested = new TestAllTypes::NestedMessage; + nested->set_bb(118); + arena_message->set_allocated_optional_nested_message(nested); + EXPECT_EQ(118, arena_message->optional_nested_message().bb()); +} + +TEST(Proto3ArenaTest, ReleaseMessage) { + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage(&arena); + arena_message->mutable_optional_nested_message()->set_bb(118); + std::unique_ptr nested( + arena_message->release_optional_nested_message()); + EXPECT_EQ(118, nested->bb()); +} + +TEST(Proto3ArenaTest, MessageFieldClear) { + // GitHub issue #310: https://github.com/google/protobuf/issues/310 + Arena arena; + TestAllTypes* arena_message = Arena::CreateMessage(&arena); + arena_message->mutable_optional_nested_message()->set_bb(118); + // This should not crash, but prior to the bugfix, it tried to use `operator + // delete` the nested message (which is on the arena): + arena_message->Clear(); +} + +TEST(Proto3ArenaTest, MessageFieldClearViaReflection) { + Arena arena; + TestAllTypes* message = Arena::CreateMessage(&arena); + const Reflection* r = message->GetReflection(); + const Descriptor* d = message->GetDescriptor(); + const FieldDescriptor* msg_field = d->FindFieldByName( + "optional_nested_message"); + + message->mutable_optional_nested_message()->set_bb(1); + r->ClearField(message, msg_field); + EXPECT_FALSE(message->has_optional_nested_message()); + EXPECT_EQ(0, message->optional_nested_message().bb()); +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/proto3_lite_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/proto3_lite_unittest.cc new file mode 100644 index 000000000..8b2c57421 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/proto3_lite_unittest.cc @@ -0,0 +1,140 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 +#include +#include + +#include +#include +#include +#include + +namespace google { +using proto3_lite_unittest::TestAllTypes; + +namespace protobuf { +namespace { +// We selectively set/check a few representative fields rather than all fields +// as this test is only expected to cover the basics of lite support. +void SetAllFields(TestAllTypes* m) { + m->set_optional_int32(100); + m->set_optional_string("asdf"); + m->set_optional_bytes("jkl;"); + m->mutable_optional_nested_message()->set_bb(42); + m->mutable_optional_foreign_message()->set_c(43); + m->set_optional_nested_enum( + proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ); + m->set_optional_foreign_enum( + proto3_lite_unittest::FOREIGN_BAZ); + m->mutable_optional_lazy_message()->set_bb(45); + m->add_repeated_int32(100); + m->add_repeated_string("asdf"); + m->add_repeated_bytes("jkl;"); + m->add_repeated_nested_message()->set_bb(46); + m->add_repeated_foreign_message()->set_c(47); + m->add_repeated_nested_enum( + proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ); + m->add_repeated_foreign_enum( + proto3_lite_unittest::FOREIGN_BAZ); + m->add_repeated_lazy_message()->set_bb(49); + + m->set_oneof_uint32(1); + m->mutable_oneof_nested_message()->set_bb(50); + m->set_oneof_string("test"); // only this one remains set +} + +void ExpectAllFieldsSet(const TestAllTypes& m) { + EXPECT_EQ(100, m.optional_int32()); + EXPECT_EQ("asdf", m.optional_string()); + EXPECT_EQ("jkl;", m.optional_bytes()); + EXPECT_EQ(true, m.has_optional_nested_message()); + EXPECT_EQ(42, m.optional_nested_message().bb()); + EXPECT_EQ(true, m.has_optional_foreign_message()); + EXPECT_EQ(43, m.optional_foreign_message().c()); + EXPECT_EQ(proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ, + m.optional_nested_enum()); + EXPECT_EQ(proto3_lite_unittest::FOREIGN_BAZ, + m.optional_foreign_enum()); + EXPECT_EQ(true, m.has_optional_lazy_message()); + EXPECT_EQ(45, m.optional_lazy_message().bb()); + + EXPECT_EQ(1, m.repeated_int32_size()); + EXPECT_EQ(100, m.repeated_int32(0)); + EXPECT_EQ(1, m.repeated_string_size()); + EXPECT_EQ("asdf", m.repeated_string(0)); + EXPECT_EQ(1, m.repeated_bytes_size()); + EXPECT_EQ("jkl;", m.repeated_bytes(0)); + EXPECT_EQ(1, m.repeated_nested_message_size()); + EXPECT_EQ(46, m.repeated_nested_message(0).bb()); + EXPECT_EQ(1, m.repeated_foreign_message_size()); + EXPECT_EQ(47, m.repeated_foreign_message(0).c()); + EXPECT_EQ(1, m.repeated_nested_enum_size()); + EXPECT_EQ(proto3_lite_unittest::TestAllTypes_NestedEnum_BAZ, + m.repeated_nested_enum(0)); + EXPECT_EQ(1, m.repeated_foreign_enum_size()); + EXPECT_EQ(proto3_lite_unittest::FOREIGN_BAZ, + m.repeated_foreign_enum(0)); + EXPECT_EQ(1, m.repeated_lazy_message_size()); + EXPECT_EQ(49, m.repeated_lazy_message(0).bb()); + + EXPECT_EQ(proto3_lite_unittest::TestAllTypes::kOneofString, + m.oneof_field_case()); + EXPECT_EQ("test", m.oneof_string()); +} + +// In this file we only test some basic functionalities of in proto3 and expect +// the rest is fully tested in proto2 unittests because proto3 shares most code +// with proto2. + +TEST(Proto3LiteTest, Parsing) { + TestAllTypes original; + SetAllFields(&original); + + TestAllTypes msg; + msg.ParseFromString(original.SerializeAsString()); + ExpectAllFieldsSet(msg); +} + +TEST(Proto3LiteTest, Swap) { + // Test Swap(). + TestAllTypes msg1; + TestAllTypes msg2; + msg1.set_optional_string("123"); + msg2.set_optional_string("3456"); + msg1.Swap(&msg2); + EXPECT_EQ("3456", msg1.optional_string()); + EXPECT_EQ("123", msg2.optional_string()); + EXPECT_EQ(msg1.ByteSize(), msg2.ByteSize() + 1); +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection.h new file mode 100644 index 000000000..5d0fc42b8 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection.h @@ -0,0 +1,610 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// This header defines the RepeatedFieldRef class template used to access +// repeated fields with protobuf reflection API. +#ifndef GOOGLE_PROTOBUF_REFLECTION_H__ +#define GOOGLE_PROTOBUF_REFLECTION_H__ + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +template +struct RefTypeTraits; +} // namespace internal + +template +RepeatedFieldRef Reflection::GetRepeatedFieldRef( + const Message& message, const FieldDescriptor* field) const { + return RepeatedFieldRef(message, field); +} + +template +MutableRepeatedFieldRef Reflection::GetMutableRepeatedFieldRef( + Message* message, const FieldDescriptor* field) const { + return MutableRepeatedFieldRef(message, field); +} + +// RepeatedFieldRef definition for non-message types. +template +class RepeatedFieldRef< + T, typename std::enable_if::value>::type> { + typedef typename internal::RefTypeTraits::iterator IteratorType; + typedef typename internal::RefTypeTraits::AccessorType AccessorType; + + public: + bool empty() const { + return accessor_->IsEmpty(data_); + } + int size() const { + return accessor_->Size(data_); + } + T Get(int index) const { + return accessor_->template Get(data_, index); + } + + typedef IteratorType iterator; + typedef IteratorType const_iterator; + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef int size_type; + typedef ptrdiff_t difference_type; + + iterator begin() const { + return iterator(data_, accessor_, true); + } + iterator end() const { + return iterator(data_, accessor_, false); + } + + private: + friend class Reflection; + RepeatedFieldRef( + const Message& message, + const FieldDescriptor* field) { + const Reflection* reflection = message.GetReflection(); + data_ = reflection->RepeatedFieldData( + const_cast(&message), field, + internal::RefTypeTraits::cpp_type, NULL); + accessor_ = reflection->RepeatedFieldAccessor(field); + } + + const void* data_; + const AccessorType* accessor_; +}; + +// MutableRepeatedFieldRef definition for non-message types. +template +class MutableRepeatedFieldRef< + T, typename std::enable_if::value>::type> { + typedef typename internal::RefTypeTraits::AccessorType AccessorType; + + public: + bool empty() const { + return accessor_->IsEmpty(data_); + } + int size() const { + return accessor_->Size(data_); + } + T Get(int index) const { + return accessor_->template Get(data_, index); + } + + void Set(int index, const T& value) const { + accessor_->template Set(data_, index, value); + } + void Add(const T& value) const { + accessor_->template Add(data_, value); + } + void RemoveLast() const { + accessor_->RemoveLast(data_); + } + void SwapElements(int index1, int index2) const { + accessor_->SwapElements(data_, index1, index2); + } + void Clear() const { + accessor_->Clear(data_); + } + + void Swap(const MutableRepeatedFieldRef& other) const { + accessor_->Swap(data_, other.accessor_, other.data_); + } + + template + void MergeFrom(const Container& container) const { + typedef typename Container::const_iterator Iterator; + for (Iterator it = container.begin(); it != container.end(); ++it) { + Add(*it); + } + } + template + void CopyFrom(const Container& container) const { + Clear(); + MergeFrom(container); + } + + private: + friend class Reflection; + MutableRepeatedFieldRef( + Message* message, + const FieldDescriptor* field) { + const Reflection* reflection = message->GetReflection(); + data_ = reflection->RepeatedFieldData( + message, field, internal::RefTypeTraits::cpp_type, NULL); + accessor_ = reflection->RepeatedFieldAccessor(field); + } + + void* data_; + const AccessorType* accessor_; +}; + +// RepeatedFieldRef definition for message types. +template +class RepeatedFieldRef< + T, typename std::enable_if::value>::type> { + typedef typename internal::RefTypeTraits::iterator IteratorType; + typedef typename internal::RefTypeTraits::AccessorType AccessorType; + + public: + bool empty() const { + return accessor_->IsEmpty(data_); + } + int size() const { + return accessor_->Size(data_); + } + // This method returns a reference to the underlying message object if it + // exists. If a message object doesn't exist (e.g., data stored in serialized + // form), scratch_space will be filled with the data and a reference to it + // will be returned. + // + // Example: + // RepeatedFieldRef h = ... + // unique_ptr scratch_space(h.NewMessage()); + // const Message& item = h.Get(index, scratch_space.get()); + const T& Get(int index, T* scratch_space) const { + return *static_cast(accessor_->Get(data_, index, scratch_space)); + } + // Create a new message of the same type as the messages stored in this + // repeated field. Caller takes ownership of the returned object. + T* NewMessage() const { + return static_cast(default_instance_->New()); + } + + typedef IteratorType iterator; + typedef IteratorType const_iterator; + typedef T value_type; + typedef T& reference; + typedef const T& const_reference; + typedef int size_type; + typedef ptrdiff_t difference_type; + + iterator begin() const { + return iterator(data_, accessor_, true, NewMessage()); + } + iterator end() const { + // The end iterator must not be dereferenced, no need for scratch space. + return iterator(data_, accessor_, false, nullptr); + } + + private: + friend class Reflection; + RepeatedFieldRef( + const Message& message, + const FieldDescriptor* field) { + const Reflection* reflection = message.GetReflection(); + data_ = reflection->RepeatedFieldData( + const_cast(&message), field, + internal::RefTypeTraits::cpp_type, + internal::RefTypeTraits::GetMessageFieldDescriptor()); + accessor_ = reflection->RepeatedFieldAccessor(field); + default_instance_ = + reflection->GetMessageFactory()->GetPrototype(field->message_type()); + } + + const void* data_; + const AccessorType* accessor_; + const Message* default_instance_; +}; + +// MutableRepeatedFieldRef definition for message types. +template +class MutableRepeatedFieldRef< + T, typename std::enable_if::value>::type> { + typedef typename internal::RefTypeTraits::AccessorType AccessorType; + + public: + bool empty() const { + return accessor_->IsEmpty(data_); + } + int size() const { + return accessor_->Size(data_); + } + // See comments for RepeatedFieldRef::Get() + const T& Get(int index, T* scratch_space) const { + return *static_cast(accessor_->Get(data_, index, scratch_space)); + } + // Create a new message of the same type as the messages stored in this + // repeated field. Caller takes ownership of the returned object. + T* NewMessage() const { + return static_cast(default_instance_->New()); + } + + void Set(int index, const T& value) const { + accessor_->Set(data_, index, &value); + } + void Add(const T& value) const { + accessor_->Add(data_, &value); + } + void RemoveLast() const { + accessor_->RemoveLast(data_); + } + void SwapElements(int index1, int index2) const { + accessor_->SwapElements(data_, index1, index2); + } + void Clear() const { + accessor_->Clear(data_); + } + + void Swap(const MutableRepeatedFieldRef& other) const { + accessor_->Swap(data_, other.accessor_, other.data_); + } + + template + void MergeFrom(const Container& container) const { + typedef typename Container::const_iterator Iterator; + for (Iterator it = container.begin(); it != container.end(); ++it) { + Add(*it); + } + } + template + void CopyFrom(const Container& container) const { + Clear(); + MergeFrom(container); + } + + private: + friend class Reflection; + MutableRepeatedFieldRef( + Message* message, + const FieldDescriptor* field) { + const Reflection* reflection = message->GetReflection(); + data_ = reflection->RepeatedFieldData( + message, field, internal::RefTypeTraits::cpp_type, + internal::RefTypeTraits::GetMessageFieldDescriptor()); + accessor_ = reflection->RepeatedFieldAccessor(field); + default_instance_ = + reflection->GetMessageFactory()->GetPrototype(field->message_type()); + } + + void* data_; + const AccessorType* accessor_; + const Message* default_instance_; +}; + +namespace internal { +// Interfaces used to implement reflection RepeatedFieldRef API. +// Reflection::GetRepeatedAccessor() should return a pointer to an singleton +// object that implements the below interface. +// +// This interface passes/returns values using void pointers. The actual type +// of the value depends on the field's cpp_type. Following is a mapping from +// cpp_type to the type that should be used in this interface: +// +// field->cpp_type() T Actual type of void* +// CPPTYPE_INT32 int32 int32 +// CPPTYPE_UINT32 uint32 uint32 +// CPPTYPE_INT64 int64 int64 +// CPPTYPE_UINT64 uint64 uint64 +// CPPTYPE_DOUBLE double double +// CPPTYPE_FLOAT float float +// CPPTYPE_BOOL bool bool +// CPPTYPE_ENUM generated enum type int32 +// CPPTYPE_STRING string string +// CPPTYPE_MESSAGE generated message type google::protobuf::Message +// or google::protobuf::Message +// +// Note that for enums we use int32 in the interface. +// +// You can map from T to the actual type using RefTypeTraits: +// typedef RefTypeTraits::AccessorValueType ActualType; +class LIBPROTOBUF_EXPORT RepeatedFieldAccessor { + public: + // Typedefs for clarity. + typedef void Field; + typedef void Value; + typedef void Iterator; + + virtual ~RepeatedFieldAccessor(); + virtual bool IsEmpty(const Field* data) const = 0; + virtual int Size(const Field* data) const = 0; + // Depends on the underlying representation of the repeated field, this + // method can return a pointer to the underlying object if such an object + // exists, or fill the data into scratch_space and return scratch_space. + // Callers of this method must ensure scratch_space is a valid pointer + // to a mutable object of the correct type. + virtual const Value* Get( + const Field* data, int index, Value* scratch_space) const = 0; + + virtual void Clear(Field* data) const = 0; + virtual void Set(Field* data, int index, const Value* value) const = 0; + virtual void Add(Field* data, const Value* value) const = 0; + virtual void RemoveLast(Field* data) const = 0; + virtual void SwapElements(Field* data, int index1, int index2) const = 0; + virtual void Swap(Field* data, const RepeatedFieldAccessor* other_mutator, + Field* other_data) const = 0; + + // Create an iterator that points at the beginning of the repeated field. + virtual Iterator* BeginIterator(const Field* data) const = 0; + // Create an iterator that points at the end of the repeated field. + virtual Iterator* EndIterator(const Field* data) const = 0; + // Make a copy of an iterator and return the new copy. + virtual Iterator* CopyIterator(const Field* data, + const Iterator* iterator) const = 0; + // Move an iterator to point to the next element. + virtual Iterator* AdvanceIterator(const Field* data, + Iterator* iterator) const = 0; + // Compare whether two iterators point to the same element. + virtual bool EqualsIterator(const Field* data, const Iterator* a, + const Iterator* b) const = 0; + // Delete an iterator created by BeginIterator(), EndIterator() and + // CopyIterator(). + virtual void DeleteIterator(const Field* data, Iterator* iterator) const = 0; + // Like Get() but for iterators. + virtual const Value* GetIteratorValue(const Field* data, + const Iterator* iterator, + Value* scratch_space) const = 0; + + // Templated methods that make using this interface easier for non-message + // types. + template + T Get(const Field* data, int index) const { + typedef typename RefTypeTraits::AccessorValueType ActualType; + ActualType scratch_space; + return static_cast( + *reinterpret_cast( + Get(data, index, static_cast(&scratch_space)))); + } + + template + void Set(Field* data, int index, const ValueType& value) const { + typedef typename RefTypeTraits::AccessorValueType ActualType; + // In this RepeatedFieldAccessor interface we pass/return data using + // raw pointers. Type of the data these raw pointers point to should + // be ActualType. Here we have a ValueType object and want a ActualType + // pointer. We can't cast a ValueType pointer to an ActualType pointer + // directly because their type might be different (for enums ValueType + // may be a generated enum type while ActualType is int32). To be safe + // we make a copy to get a temporary ActualType object and use it. + ActualType tmp = static_cast(value); + Set(data, index, static_cast(&tmp)); + } + + template + void Add(Field* data, const ValueType& value) const { + typedef typename RefTypeTraits::AccessorValueType ActualType; + // In this RepeatedFieldAccessor interface we pass/return data using + // raw pointers. Type of the data these raw pointers point to should + // be ActualType. Here we have a ValueType object and want a ActualType + // pointer. We can't cast a ValueType pointer to an ActualType pointer + // directly because their type might be different (for enums ValueType + // may be a generated enum type while ActualType is int32). To be safe + // we make a copy to get a temporary ActualType object and use it. + ActualType tmp = static_cast(value); + Add(data, static_cast(&tmp)); + } +}; + +// Implement (Mutable)RepeatedFieldRef::iterator +template +class RepeatedFieldRefIterator + : public std::iterator { + typedef typename RefTypeTraits::AccessorValueType AccessorValueType; + typedef typename RefTypeTraits::IteratorValueType IteratorValueType; + typedef typename RefTypeTraits::IteratorPointerType IteratorPointerType; + + public: + // Constructor for non-message fields. + RepeatedFieldRefIterator(const void* data, + const RepeatedFieldAccessor* accessor, bool begin) + : data_(data), + accessor_(accessor), + iterator_(begin ? accessor->BeginIterator(data) + : accessor->EndIterator(data)), + // The end iterator must not be dereferenced, no need for scratch space. + scratch_space_(begin ? new AccessorValueType : nullptr) {} + // Constructor for message fields. + RepeatedFieldRefIterator(const void* data, + const RepeatedFieldAccessor* accessor, + bool begin, + AccessorValueType* scratch_space) + : data_(data), accessor_(accessor), + iterator_(begin ? accessor->BeginIterator(data) : + accessor->EndIterator(data)), + scratch_space_(scratch_space) { + } + ~RepeatedFieldRefIterator() { + accessor_->DeleteIterator(data_, iterator_); + } + RepeatedFieldRefIterator operator++(int) { + RepeatedFieldRefIterator tmp(*this); + iterator_ = accessor_->AdvanceIterator(data_, iterator_); + return tmp; + } + RepeatedFieldRefIterator& operator++() { + iterator_ = accessor_->AdvanceIterator(data_, iterator_); + return *this; + } + IteratorValueType operator*() const { + return static_cast( + *static_cast( + accessor_->GetIteratorValue( + data_, iterator_, scratch_space_.get()))); + } + IteratorPointerType operator->() const { + return static_cast( + accessor_->GetIteratorValue( + data_, iterator_, scratch_space_.get())); + } + bool operator!=(const RepeatedFieldRefIterator& other) const { + assert(data_ == other.data_); + assert(accessor_ == other.accessor_); + return !accessor_->EqualsIterator(data_, iterator_, other.iterator_); + } + bool operator==(const RepeatedFieldRefIterator& other) const { + return !this->operator!=(other); + } + + RepeatedFieldRefIterator(const RepeatedFieldRefIterator& other) + : data_(other.data_), accessor_(other.accessor_), + iterator_(accessor_->CopyIterator(data_, other.iterator_)) { + } + RepeatedFieldRefIterator& operator=(const RepeatedFieldRefIterator& other) { + if (this != &other) { + accessor_->DeleteIterator(data_, iterator_); + data_ = other.data_; + accessor_ = other.accessor_; + iterator_ = accessor_->CopyIterator(data_, other.iterator_); + } + return *this; + } + + protected: + const void* data_; + const RepeatedFieldAccessor* accessor_; + void* iterator_; + std::unique_ptr scratch_space_; +}; + +// TypeTraits that maps the type parameter T of RepeatedFieldRef or +// MutableRepeatedFieldRef to corresponding iterator type, +// RepeatedFieldAccessor type, etc. +template +struct PrimitiveTraits { + static const bool is_primitive = false; +}; +#define DEFINE_PRIMITIVE(TYPE, type) \ + template<> struct PrimitiveTraits { \ + static const bool is_primitive = true; \ + static const FieldDescriptor::CppType cpp_type = \ + FieldDescriptor::CPPTYPE_ ## TYPE; \ + }; +DEFINE_PRIMITIVE(INT32, int32) +DEFINE_PRIMITIVE(UINT32, uint32) +DEFINE_PRIMITIVE(INT64, int64) +DEFINE_PRIMITIVE(UINT64, uint64) +DEFINE_PRIMITIVE(FLOAT, float) +DEFINE_PRIMITIVE(DOUBLE, double) +DEFINE_PRIMITIVE(BOOL, bool) +#undef DEFINE_PRIMITIVE + +template +struct RefTypeTraits< + T, typename std::enable_if::is_primitive>::type> { + typedef RepeatedFieldRefIterator iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef T AccessorValueType; + typedef T IteratorValueType; + typedef T* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + PrimitiveTraits::cpp_type; + static const Descriptor* GetMessageFieldDescriptor() { + return NULL; + } +}; + +template +struct RefTypeTraits< + T, typename std::enable_if::value>::type> { + typedef RepeatedFieldRefIterator iterator; + typedef RepeatedFieldAccessor AccessorType; + // We use int32 for repeated enums in RepeatedFieldAccessor. + typedef int32 AccessorValueType; + typedef T IteratorValueType; + typedef int32* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_ENUM; + static const Descriptor* GetMessageFieldDescriptor() { + return NULL; + } +}; + +template +struct RefTypeTraits< + T, typename std::enable_if::value>::type> { + typedef RepeatedFieldRefIterator iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef string AccessorValueType; + typedef const string IteratorValueType; + typedef const string* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_STRING; + static const Descriptor* GetMessageFieldDescriptor() { + return NULL; + } +}; + +template +struct MessageDescriptorGetter { + static const Descriptor* get() { + return T::default_instance().GetDescriptor(); + } +}; +template<> +struct MessageDescriptorGetter { + static const Descriptor* get() { + return NULL; + } +}; + +template +struct RefTypeTraits< + T, typename std::enable_if::value>::type> { + typedef RepeatedFieldRefIterator iterator; + typedef RepeatedFieldAccessor AccessorType; + typedef Message AccessorValueType; + typedef const T& IteratorValueType; + typedef const T* IteratorPointerType; + static const FieldDescriptor::CppType cpp_type = + FieldDescriptor::CPPTYPE_MESSAGE; + static const Descriptor* GetMessageFieldDescriptor() { + return MessageDescriptorGetter::get(); + } +}; +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_REFLECTION_H__ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_internal.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_internal.h new file mode 100644 index 000000000..fcb424715 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_internal.h @@ -0,0 +1,378 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +#ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ +#define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +// A base class for RepeatedFieldAccessor implementations that can support +// random-access efficiently. All iterator methods delegates the work to +// corresponding random-access methods. +class RandomAccessRepeatedFieldAccessor : public RepeatedFieldAccessor { + public: + virtual ~RandomAccessRepeatedFieldAccessor() {} + + virtual Iterator* BeginIterator(const Field* data) const { + return PositionToIterator(0); + } + virtual Iterator* EndIterator(const Field* data) const { + return PositionToIterator(this->Size(data)); + } + virtual Iterator* CopyIterator(const Field* data, + const Iterator* iterator) const { + return const_cast(iterator); + } + virtual Iterator* AdvanceIterator(const Field* data, + Iterator* iterator) const { + return PositionToIterator(IteratorToPosition(iterator) + 1); + } + virtual bool EqualsIterator(const Field* data, + const Iterator* a, + const Iterator* b) const { + return a == b; + } + virtual void DeleteIterator(const Field* data, Iterator* iterator) const { + } + virtual const Value* GetIteratorValue(const Field* data, + const Iterator* iterator, + Value* scratch_space) const { + return Get(data, static_cast(IteratorToPosition(iterator)), + scratch_space); + } + + private: + static intptr_t IteratorToPosition(const Iterator* iterator) { + return reinterpret_cast(iterator); + } + static Iterator* PositionToIterator(intptr_t position) { + return reinterpret_cast(position); + } +}; + +// Base class for RepeatedFieldAccessor implementations that manipulates +// RepeatedField. +template +class RepeatedFieldWrapper : public RandomAccessRepeatedFieldAccessor { + public: + RepeatedFieldWrapper() {} + virtual ~RepeatedFieldWrapper() {} + virtual bool IsEmpty(const Field* data) const { + return GetRepeatedField(data)->empty(); + } + virtual int Size(const Field* data) const { + return GetRepeatedField(data)->size(); + } + virtual const Value* Get(const Field* data, int index, + Value* scratch_space) const { + return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); + } + virtual void Clear(Field* data) const { + MutableRepeatedField(data)->Clear(); + } + virtual void Set(Field* data, int index, const Value* value) const { + MutableRepeatedField(data)->Set(index, ConvertToT(value)); + } + virtual void Add(Field* data, const Value* value) const { + MutableRepeatedField(data)->Add(ConvertToT(value)); + } + virtual void RemoveLast(Field* data) const { + MutableRepeatedField(data)->RemoveLast(); + } + virtual void SwapElements(Field* data, int index1, int index2) const { + MutableRepeatedField(data)->SwapElements(index1, index2); + } + + protected: + typedef RepeatedField RepeatedFieldType; + static const RepeatedFieldType* GetRepeatedField(const Field* data) { + return reinterpret_cast(data); + } + static RepeatedFieldType* MutableRepeatedField(Field* data) { + return reinterpret_cast(data); + } + + // Convert an object recevied by this accessor to an object to be stored in + // the underlying RepeatedField. + virtual T ConvertToT(const Value* value) const = 0; + + // Convert an object stored in RepeatedPtrField to an object that will be + // returned by this accessor. If the two objects have the same type (true + // for string fields with ctype=STRING), a pointer to the source object can + // be returned directly. Otherwise, data should be copied from value to + // scratch_space and scratch_space should be returned. + virtual const Value* ConvertFromT(const T& value, + Value* scratch_space) const = 0; +}; + +// Base class for RepeatedFieldAccessor implementations that manipulates +// RepeatedPtrField. +template +class RepeatedPtrFieldWrapper : public RandomAccessRepeatedFieldAccessor { + public: + RepeatedPtrFieldWrapper() {} + virtual ~RepeatedPtrFieldWrapper() {} + virtual bool IsEmpty(const Field* data) const { + return GetRepeatedField(data)->empty(); + } + virtual int Size(const Field* data) const { + return GetRepeatedField(data)->size(); + } + virtual const Value* Get(const Field* data, int index, + Value* scratch_space) const { + return ConvertFromT(GetRepeatedField(data)->Get(index), scratch_space); + } + virtual void Clear(Field* data) const { + MutableRepeatedField(data)->Clear(); + } + virtual void Set(Field* data, int index, const Value* value) const { + ConvertToT(value, MutableRepeatedField(data)->Mutable(index)); + } + virtual void Add(Field* data, const Value* value) const { + T* allocated = New(value); + ConvertToT(value, allocated); + MutableRepeatedField(data)->AddAllocated(allocated); + } + virtual void RemoveLast(Field* data) const { + MutableRepeatedField(data)->RemoveLast(); + } + virtual void SwapElements(Field* data, int index1, int index2) const { + MutableRepeatedField(data)->SwapElements(index1, index2); + } + + protected: + typedef RepeatedPtrField RepeatedFieldType; + static const RepeatedFieldType* GetRepeatedField(const Field* data) { + return reinterpret_cast(data); + } + static RepeatedFieldType* MutableRepeatedField(Field* data) { + return reinterpret_cast(data); + } + + // Create a new T instance. For repeated message fields, T can be specified + // as google::protobuf::Message so we can't use "new T()" directly. In that case, value + // should be a message of the same type (it's ensured by the caller) and a + // new message object will be created using it. + virtual T* New(const Value* value) const = 0; + + // Convert an object received by this accessor to an object that will be + // stored in the underlying RepeatedPtrField. + virtual void ConvertToT(const Value* value, T* result) const = 0; + + // Convert an object stored in RepeatedPtrField to an object that will be + // returned by this accessor. If the two objects have the same type (true + // for string fields with ctype=STRING), a pointer to the source object can + // be returned directly. Otherwise, data should be copied from value to + // scratch_space and scratch_space should be returned. + virtual const Value* ConvertFromT(const T& value, + Value* scratch_space) const = 0; +}; + +// An implementation of RandomAccessRepeatedFieldAccessor that manipulates +// MapFieldBase. +class MapFieldAccessor : public RandomAccessRepeatedFieldAccessor { + public: + MapFieldAccessor() {} + virtual ~MapFieldAccessor() {} + virtual bool IsEmpty(const Field* data) const { + return GetRepeatedField(data)->empty(); + } + virtual int Size(const Field* data) const { + return GetRepeatedField(data)->size(); + } + virtual const Value* Get(const Field* data, int index, + Value* scratch_space) const { + return ConvertFromEntry(GetRepeatedField(data)->Get(index), scratch_space); + } + virtual void Clear(Field* data) const { + MutableRepeatedField(data)->Clear(); + } + virtual void Set(Field* data, int index, const Value* value) const { + ConvertToEntry(value, MutableRepeatedField(data)->Mutable(index)); + } + virtual void Add(Field* data, const Value* value) const { + Message* allocated = New(value); + ConvertToEntry(value, allocated); + MutableRepeatedField(data)->AddAllocated(allocated); + } + virtual void RemoveLast(Field* data) const { + MutableRepeatedField(data)->RemoveLast(); + } + virtual void SwapElements(Field* data, int index1, int index2) const { + MutableRepeatedField(data)->SwapElements(index1, index2); + } + virtual void Swap( + Field* data, + const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const { + GOOGLE_CHECK(this == other_mutator); + MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); + } + + protected: + typedef RepeatedPtrField RepeatedFieldType; + static const RepeatedFieldType* GetRepeatedField(const Field* data) { + return reinterpret_cast( + (&reinterpret_cast(data)->GetRepeatedField())); + } + static RepeatedFieldType* MutableRepeatedField(Field* data) { + return reinterpret_cast( + reinterpret_cast(data)->MutableRepeatedField()); + } + virtual Message* New(const Value* value) const { + return static_cast(value)->New(); + } + // Convert an object received by this accessor to an MapEntry message to be + // stored in the underlying MapFieldBase. + virtual void ConvertToEntry(const Value* value, Message* result) const { + result->CopyFrom(*static_cast(value)); + } + // Convert a MapEntry message stored in the underlying MapFieldBase to an + // object that will be returned by this accessor. + virtual const Value* ConvertFromEntry(const Message& value, + Value* scratch_space) const { + return static_cast(&value); + } +}; + +// Default implementations of RepeatedFieldAccessor for primitive types. +template +class RepeatedFieldPrimitiveAccessor : public RepeatedFieldWrapper { + typedef void Field; + typedef void Value; + using RepeatedFieldWrapper::MutableRepeatedField; + + public: + RepeatedFieldPrimitiveAccessor() {} + virtual ~RepeatedFieldPrimitiveAccessor() {} + virtual void Swap( + Field* data, + const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const { + // Currently RepeatedFieldPrimitiveAccessor is the only implementation of + // RepeatedFieldAccessor for primitive types. As we are using singletons + // for these accessors, here "other_mutator" must be "this". + GOOGLE_CHECK(this == other_mutator); + MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); + } + + protected: + virtual T ConvertToT(const Value* value) const { + return *static_cast(value); + } + virtual const Value* ConvertFromT(const T& value, + Value* scratch_space) const { + return static_cast(&value); + } +}; + +// Default implementation of RepeatedFieldAccessor for string fields with +// ctype=STRING. +class RepeatedPtrFieldStringAccessor : public RepeatedPtrFieldWrapper { + typedef void Field; + typedef void Value; + using RepeatedFieldAccessor::Add; + + public: + RepeatedPtrFieldStringAccessor() {} + virtual ~RepeatedPtrFieldStringAccessor() {} + virtual void Swap( + Field* data, + const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const { + if (this == other_mutator) { + MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); + } else { + RepeatedPtrField tmp; + tmp.Swap(MutableRepeatedField(data)); + int other_size = other_mutator->Size(other_data); + for (int i = 0; i < other_size; ++i) { + Add(data, other_mutator->Get(other_data, i)); + } + int size = Size(data); + other_mutator->Clear(other_data); + for (int i = 0; i < size; ++i) { + other_mutator->Add(other_data, tmp.Get(i)); + } + } + } + + protected: + virtual string* New(const Value*) const { + return new string(); + } + virtual void ConvertToT(const Value* value, string* result) const { + *result = *static_cast(value); + } + virtual const Value* ConvertFromT(const string& value, + Value* scratch_space) const { + return static_cast(&value); + } +}; + + +class RepeatedPtrFieldMessageAccessor + : public RepeatedPtrFieldWrapper { + typedef void Field; + typedef void Value; + + public: + RepeatedPtrFieldMessageAccessor() {} + virtual ~RepeatedPtrFieldMessageAccessor() {} + virtual void Swap( + Field* data, + const internal::RepeatedFieldAccessor* other_mutator, + Field* other_data) const { + GOOGLE_CHECK(this == other_mutator); + MutableRepeatedField(data)->Swap(MutableRepeatedField(other_data)); + } + + protected: + virtual Message* New(const Value* value) const { + return static_cast(value)->New(); + } + virtual void ConvertToT(const Value* value, Message* result) const { + result->CopyFrom(*static_cast(value)); + } + virtual const Value* ConvertFromT(const Message& value, + Value* scratch_space) const { + return static_cast(&value); + } +}; +} // namespace internal +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__ diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/reflection_ops.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_ops.cc similarity index 81% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/reflection_ops.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_ops.cc index 4629dec25..3cd503404 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/reflection_ops.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_ops.cc @@ -31,13 +31,16 @@ // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include #include #include -#include -#include +#include +#include #include +#include +#include #include #include @@ -45,6 +48,17 @@ namespace google { namespace protobuf { namespace internal { +static const Reflection* GetReflectionOrDie(const Message& m) { + const Reflection* r = m.GetReflection(); + if (r == nullptr) { + const Descriptor* d = m.GetDescriptor(); + const string& mtype = d ? d->name() : "unknown"; + // RawMessage is one known type for which GetReflection() returns nullptr. + GOOGLE_LOG(FATAL) << "Message does not support reflection (type " << mtype << ")."; + } + return r; +} + void ReflectionOps::Copy(const Message& from, Message* to) { if (&from == to) return; Clear(to); @@ -60,10 +74,10 @@ void ReflectionOps::Merge(const Message& from, Message* to) { << "(merge " << descriptor->full_name() << " to " << to->GetDescriptor()->full_name() << ")"; - const Reflection* from_reflection = from.GetReflection(); - const Reflection* to_reflection = to->GetReflection(); + const Reflection* from_reflection = GetReflectionOrDie(from); + const Reflection* to_reflection = GetReflectionOrDie(*to); - vector fields; + std::vector fields; from_reflection->ListFields(from, &fields); for (int i = 0; i < fields.size(); i++) { const FieldDescriptor* field = fields[i]; @@ -127,9 +141,9 @@ void ReflectionOps::Merge(const Message& from, Message* to) { } void ReflectionOps::Clear(Message* message) { - const Reflection* reflection = message->GetReflection(); + const Reflection* reflection = GetReflectionOrDie(*message); - vector fields; + std::vector fields; reflection->ListFields(*message, &fields); for (int i = 0; i < fields.size(); i++) { reflection->ClearField(message, fields[i]); @@ -140,7 +154,7 @@ void ReflectionOps::Clear(Message* message) { bool ReflectionOps::IsInitialized(const Message& message) { const Descriptor* descriptor = message.GetDescriptor(); - const Reflection* reflection = message.GetReflection(); + const Reflection* reflection = GetReflectionOrDie(message); // Check required fields of this message. for (int i = 0; i < descriptor->field_count(); i++) { @@ -152,12 +166,33 @@ bool ReflectionOps::IsInitialized(const Message& message) { } // Check that sub-messages are initialized. - vector fields; + std::vector fields; reflection->ListFields(message, &fields); for (int i = 0; i < fields.size(); i++) { const FieldDescriptor* field = fields[i]; if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + if (field->is_map()) { + const FieldDescriptor* value_field = field->message_type()->field(1); + if (value_field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + MapFieldBase* map_field = + reflection->MapData(const_cast(&message), field); + if (map_field->IsMapValid()) { + MapIterator iter(const_cast(&message), field); + MapIterator end(const_cast(&message), field); + for (map_field->MapBegin(&iter), map_field->MapEnd(&end); + iter != end; ++iter) { + if (!iter.GetValueRef().GetMessageValue().IsInitialized()) { + return false; + } + } + continue; + } + } else { + continue; + } + } + if (field->is_repeated()) { int size = reflection->FieldSize(message, field); @@ -179,11 +214,11 @@ bool ReflectionOps::IsInitialized(const Message& message) { } void ReflectionOps::DiscardUnknownFields(Message* message) { - const Reflection* reflection = message->GetReflection(); + const Reflection* reflection = GetReflectionOrDie(*message); reflection->MutableUnknownFields(message)->Clear(); - vector fields; + std::vector fields; reflection->ListFields(*message, &fields); for (int i = 0; i < fields.size(); i++) { const FieldDescriptor* field = fields[i]; @@ -224,9 +259,9 @@ static string SubMessagePrefix(const string& prefix, void ReflectionOps::FindInitializationErrors( const Message& message, const string& prefix, - vector* errors) { + std::vector* errors) { const Descriptor* descriptor = message.GetDescriptor(); - const Reflection* reflection = message.GetReflection(); + const Reflection* reflection = GetReflectionOrDie(message); // Check required fields of this message. for (int i = 0; i < descriptor->field_count(); i++) { @@ -238,7 +273,7 @@ void ReflectionOps::FindInitializationErrors( } // Check sub-messages. - vector fields; + std::vector fields; reflection->ListFields(message, &fields); for (int i = 0; i < fields.size(); i++) { const FieldDescriptor* field = fields[i]; diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/reflection_ops.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_ops.h similarity index 98% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/reflection_ops.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_ops.h index 4775911e8..45d8c650e 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/reflection_ops.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_ops.h @@ -67,7 +67,7 @@ class LIBPROTOBUF_EXPORT ReflectionOps { // the front of each name. static void FindInitializationErrors(const Message& message, const string& prefix, - vector* errors); + std::vector* errors); private: // All methods are static. No need to construct. diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/reflection_ops_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_ops_unittest.cc similarity index 99% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/reflection_ops_unittest.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_ops_unittest.cc index 32740ea46..9cedb3422 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/reflection_ops_unittest.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/reflection_ops_unittest.cc @@ -37,9 +37,11 @@ #include #include +#include #include #include #include + #include namespace google { @@ -418,7 +420,7 @@ TEST(ReflectionOpsTest, OneofIsInitialized) { } static string FindInitializationErrors(const Message& message) { - vector errors; + std::vector errors; ReflectionOps::FindInitializationErrors(message, "", &errors); return Join(errors, ","); } diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field.cc new file mode 100644 index 000000000..310000aab --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field.cc @@ -0,0 +1,126 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#include + +#include +#include +#include + +namespace google { +namespace protobuf { + +namespace internal { + +void** RepeatedPtrFieldBase::InternalExtend(int extend_amount) { + int new_size = current_size_ + extend_amount; + if (total_size_ >= new_size) { + // N.B.: rep_ is non-NULL because extend_amount is always > 0, hence + // total_size must be non-zero since it is lower-bounded by new_size. + return &rep_->elements[current_size_]; + } + Rep* old_rep = rep_; + Arena* arena = GetArenaNoVirtual(); + new_size = std::max(kMinRepeatedFieldAllocationSize, + std::max(total_size_ * 2, new_size)); + GOOGLE_CHECK_LE(new_size, + (std::numeric_limits::max() - kRepHeaderSize) / + sizeof(old_rep->elements[0])) + << "Requested size is too large to fit into size_t."; + size_t bytes = kRepHeaderSize + sizeof(old_rep->elements[0]) * new_size; + if (arena == NULL) { + rep_ = reinterpret_cast(::operator new(bytes)); + } else { + rep_ = reinterpret_cast( + ::google::protobuf::Arena::CreateArray(arena, bytes)); + } +#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) + const int old_total_size = total_size_; +#endif + total_size_ = new_size; + if (old_rep && old_rep->allocated_size > 0) { + memcpy(rep_->elements, old_rep->elements, + old_rep->allocated_size * sizeof(rep_->elements[0])); + rep_->allocated_size = old_rep->allocated_size; + } else { + rep_->allocated_size = 0; + } + if (arena == NULL) { +#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) + const size_t old_size = + old_total_size * sizeof(rep_->elements[0]) + kRepHeaderSize; + ::operator delete(static_cast(old_rep), old_size); +#else + ::operator delete(static_cast(old_rep)); +#endif + } + return &rep_->elements[current_size_]; +} + +void RepeatedPtrFieldBase::Reserve(int new_size) { + if (new_size > current_size_) { + InternalExtend(new_size - current_size_); + } +} + +void RepeatedPtrFieldBase::CloseGap(int start, int num) { + if (rep_ == NULL) return; + // Close up a gap of "num" elements starting at offset "start". + for (int i = start + num; i < rep_->allocated_size; ++i) + rep_->elements[i - num] = rep_->elements[i]; + current_size_ -= num; + rep_->allocated_size -= num; +} + +google::protobuf::MessageLite* RepeatedPtrFieldBase::AddWeak( + const google::protobuf::MessageLite* prototype) { + if (rep_ != NULL && current_size_ < rep_->allocated_size) { + return reinterpret_cast( + rep_->elements[current_size_++]); + } + if (!rep_ || rep_->allocated_size == total_size_) { + Reserve(total_size_ + 1); + } + ++rep_->allocated_size; + google::protobuf::MessageLite* result = prototype ? prototype->New(arena_) : + Arena::CreateMessage(arena_); + rep_->elements[current_size_++] = result; + return result; +} + +} // namespace internal + + +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field.h new file mode 100644 index 000000000..b47ea9948 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field.h @@ -0,0 +1,2630 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// RepeatedField and RepeatedPtrField are used by generated protocol message +// classes to manipulate repeated fields. These classes are very similar to +// STL's vector, but include a number of optimizations found to be useful +// specifically in the case of Protocol Buffers. RepeatedPtrField is +// particularly different from STL vector as it manages ownership of the +// pointers that it contains. +// +// Typically, clients should not need to access RepeatedField objects directly, +// but should instead use the accessor functions generated automatically by the +// protocol compiler. + +#ifndef GOOGLE_PROTOBUF_REPEATED_FIELD_H__ +#define GOOGLE_PROTOBUF_REPEATED_FIELD_H__ + +#ifdef _MSC_VER +// This is required for min/max on VS2013 only. +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// Forward-declare these so that we can make them friends. +namespace google { +namespace upb { +namespace google_opensource { +class GMR_Handlers; +} // namespace google_opensource +} // namespace upb + +namespace protobuf { + +class Message; + +namespace internal { + +class MergePartialFromCodedStreamHelper; + +static const int kMinRepeatedFieldAllocationSize = 4; + +// A utility function for logging that doesn't need any template types. +void LogIndexOutOfBounds(int index, int size); + +template +inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) { + return static_cast(std::distance(begin, end)); +} + +template +inline int CalculateReserve(Iter /*begin*/, Iter /*end*/, + std::input_iterator_tag /*unused*/) { + return -1; +} + +template +inline int CalculateReserve(Iter begin, Iter end) { + typedef typename std::iterator_traits::iterator_category Category; + return CalculateReserve(begin, end, Category()); +} +} // namespace internal + + +// RepeatedField is used to represent repeated fields of a primitive type (in +// other words, everything except strings and nested Messages). Most users will +// not ever use a RepeatedField directly; they will use the get-by-index, +// set-by-index, and add accessors that are generated for all repeated fields. +template +class RepeatedField final { + public: + RepeatedField(); + explicit RepeatedField(Arena* arena); + RepeatedField(const RepeatedField& other); + template + RepeatedField(Iter begin, const Iter& end); + ~RepeatedField(); + + RepeatedField& operator=(const RepeatedField& other); + + RepeatedField(RepeatedField&& other) noexcept; + RepeatedField& operator=(RepeatedField&& other) noexcept; + + bool empty() const; + int size() const; + + const Element& Get(int index) const; + Element* Mutable(int index); + + const Element& operator[](int index) const { return Get(index); } + Element& operator[](int index) { return *Mutable(index); } + + void Set(int index, const Element& value); + void Add(const Element& value); + // Appends a new element and return a pointer to it. + // The new element is uninitialized if |Element| is a POD type. + Element* Add(); + // Remove the last element in the array. + void RemoveLast(); + + // Extract elements with indices in "[start .. start+num-1]". + // Copy them into "elements[0 .. num-1]" if "elements" is not NULL. + // Caution: implementation also moves elements with indices [start+num ..]. + // Calling this routine inside a loop can cause quadratic behavior. + void ExtractSubrange(int start, int num, Element* elements); + + void Clear(); + void MergeFrom(const RepeatedField& other); + void CopyFrom(const RepeatedField& other); + + // Reserve space to expand the field to at least the given size. If the + // array is grown, it will always be at least doubled in size. + void Reserve(int new_size); + + // Resize the RepeatedField to a new, smaller size. This is O(1). + void Truncate(int new_size); + + void AddAlreadyReserved(const Element& value); + // Appends a new element and return a pointer to it. + // The new element is uninitialized if |Element| is a POD type. + // Should be called only if Capacity() > Size(). + Element* AddAlreadyReserved(); + Element* AddNAlreadyReserved(int elements); + int Capacity() const; + + // Like STL resize. Uses value to fill appended elements. + // Like Truncate() if new_size <= size(), otherwise this is + // O(new_size - size()). + void Resize(int new_size, const Element& value); + + // Gets the underlying array. This pointer is possibly invalidated by + // any add or remove operation. + Element* mutable_data(); + const Element* data() const; + + // Swap entire contents with "other". If they are separate arenas then, copies + // data between each other. + void Swap(RepeatedField* other); + + // Swap entire contents with "other". Should be called only if the caller can + // guarantee that both repeated fields are on the same arena or are on the + // heap. Swapping between different arenas is disallowed and caught by a + // GOOGLE_DCHECK (see API docs for details). + void UnsafeArenaSwap(RepeatedField* other); + + // Swap two elements. + void SwapElements(int index1, int index2); + + // STL-like iterator support + typedef Element* iterator; + typedef const Element* const_iterator; + typedef Element value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef int size_type; + typedef ptrdiff_t difference_type; + + iterator begin(); + const_iterator begin() const; + const_iterator cbegin() const; + iterator end(); + const_iterator end() const; + const_iterator cend() const; + + // Reverse iterator support + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + reverse_iterator rbegin() { + return reverse_iterator(end()); + } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { + return reverse_iterator(begin()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + // Returns the number of bytes used by the repeated field, excluding + // sizeof(*this) + size_t SpaceUsedExcludingSelfLong() const; + + int SpaceUsedExcludingSelf() const { + return internal::ToIntSize(SpaceUsedExcludingSelfLong()); + } + + // Removes the element referenced by position. + // + // Returns an iterator to the element immediately following the removed + // element. + // + // Invalidates all iterators at or after the removed element, including end(). + iterator erase(const_iterator position); + + // Removes the elements in the range [first, last). + // + // Returns an iterator to the element immediately following the removed range. + // + // Invalidates all iterators at or after the removed range, including end(). + iterator erase(const_iterator first, const_iterator last); + + // Get the Arena on which this RepeatedField stores its elements. + ::google::protobuf::Arena* GetArena() const { + return GetArenaNoVirtual(); + } + + // For internal use only. + // + // This is public due to it being called by generated code. + inline void InternalSwap(RepeatedField* other); + + private: + static const int kInitialSize = 0; + // A note on the representation here (see also comment below for + // RepeatedPtrFieldBase's struct Rep): + // + // We maintain the same sizeof(RepeatedField) as before we added arena support + // so that we do not degrade performance by bloating memory usage. Directly + // adding an arena_ element to RepeatedField is quite costly. By using + // indirection in this way, we keep the same size when the RepeatedField is + // empty (common case), and add only an 8-byte header to the elements array + // when non-empty. We make sure to place the size fields directly in the + // RepeatedField class to avoid costly cache misses due to the indirection. + int current_size_; + int total_size_; + struct Rep { + Arena* arena; + Element elements[1]; + }; + // We can not use sizeof(Rep) - sizeof(Element) due to the trailing padding on + // the struct. We can not use sizeof(Arena*) as well because there might be + // a "gap" after the field arena and before the field elements (e.g., when + // Element is double and pointer is 32bit). + static const size_t kRepHeaderSize; + + // We reuse the Rep* for an Arena* when total_size == 0, to avoid having to do + // an allocation in the constructor when we have an Arena. + union Pointer { + Pointer(Arena* a) : arena(a) {} + Arena* arena; // When total_size_ == 0. + Rep* rep; // When total_size_ != 0. + } ptr_; + + Rep* rep() const { + GOOGLE_DCHECK_GT(total_size_, 0); + return ptr_.rep; + } + + friend class Arena; + typedef void InternalArenaConstructable_; + + + // Move the contents of |from| into |to|, possibly clobbering |from| in the + // process. For primitive types this is just a memcpy(), but it could be + // specialized for non-primitive types to, say, swap each element instead. + void MoveArray(Element* to, Element* from, int size); + + // Copy the elements of |from| into |to|. + void CopyArray(Element* to, const Element* from, int size); + + // Internal helper expected by Arena methods. + inline Arena* GetArenaNoVirtual() const { + return (total_size_ == 0) ? ptr_.arena : ptr_.rep->arena; + } + + // Internal helper to delete all elements and deallocate the storage. + // If Element has a trivial destructor (for example, if it's a fundamental + // type, like int32), the loop will be removed by the optimizer. + void InternalDeallocate(Rep* rep, int size) { + if (rep != NULL) { + Element* e = &rep->elements[0]; + Element* limit = &rep->elements[size]; + for (; e < limit; e++) { + e->~Element(); + } + if (rep->arena == NULL) { +#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) + const size_t bytes = size * sizeof(*e) + kRepHeaderSize; + ::operator delete(static_cast(rep), bytes); +#else + ::operator delete(static_cast(rep)); +#endif + } + } + } + + friend class internal::WireFormatLite; + const Element* unsafe_data() const; +}; + +template +const size_t RepeatedField::kRepHeaderSize = + reinterpret_cast(&reinterpret_cast(16)->elements[0]) - 16; + +namespace internal { +template class RepeatedPtrIterator; +template class RepeatedPtrOverPtrsIterator; +} // namespace internal + +namespace internal { + +// This is a helper template to copy an array of elements efficiently when they +// have a trivial copy constructor, and correctly otherwise. This really +// shouldn't be necessary, but our compiler doesn't optimize std::copy very +// effectively. +template ::value> +struct ElementCopier { + void operator()(Element* to, const Element* from, int array_size); +}; + +} // namespace internal + +namespace internal { + +// type-traits helper for RepeatedPtrFieldBase: we only want to invoke +// arena-related "copy if on different arena" behavior if the necessary methods +// exist on the contained type. In particular, we rely on MergeFrom() existing +// as a general proxy for the fact that a copy will work, and we also provide a +// specific override for string*. +template +struct TypeImplementsMergeBehaviorProbeForMergeFrom { + typedef char HasMerge; + typedef long HasNoMerge; + + // We accept either of: + // - void MergeFrom(const T& other) + // - bool MergeFrom(const T& other) + // + // We mangle these names a bit to avoid compatibility issues in 'unclean' + // include environments that may have, e.g., "#define test ..." (yes, this + // exists). + template + struct CheckType; + template static HasMerge Check( + CheckType*); + template static HasMerge Check( + CheckType*); + template static HasNoMerge Check(...); + + // Resolves to either std::true_type or std::false_type. + typedef std::integral_constant(0)) == sizeof(HasMerge))> type; +}; + +template +struct TypeImplementsMergeBehavior : + TypeImplementsMergeBehaviorProbeForMergeFrom {}; + + +template <> +struct TypeImplementsMergeBehavior< ::std::string> { + typedef std::true_type type; +}; + +// This is the common base class for RepeatedPtrFields. It deals only in void* +// pointers. Users should not use this interface directly. +// +// The methods of this interface correspond to the methods of RepeatedPtrField, +// but may have a template argument called TypeHandler. Its signature is: +// class TypeHandler { +// public: +// typedef MyType Type; +// // WeakType is almost always the same as MyType, but we use it in +// // ImplicitWeakTypeHandler. +// typedef MyType WeakType; +// static Type* New(); +// static WeakType* NewFromPrototype(const WeakType* prototype, +// ::google::protobuf::Arena* arena); +// static void Delete(Type*); +// static void Clear(Type*); +// static void Merge(const Type& from, Type* to); +// +// // Only needs to be implemented if SpaceUsedExcludingSelf() is called. +// static int SpaceUsedLong(const Type&); +// }; +class LIBPROTOBUF_EXPORT RepeatedPtrFieldBase { + protected: + RepeatedPtrFieldBase(); + explicit RepeatedPtrFieldBase(::google::protobuf::Arena* arena); + ~RepeatedPtrFieldBase() {} + + // Must be called from destructor. + template + void Destroy(); + + bool empty() const; + int size() const; + + template + typename TypeHandler::Type* Mutable(int index); + template + void Delete(int index); + template + typename TypeHandler::Type* Add(typename TypeHandler::Type* prototype = NULL); + + public: + // The next few methods are public so that they can be called from generated + // code when implicit weak fields are used, but they should never be called by + // application code. + + template + const typename TypeHandler::WeakType& Get(int index) const; + + // Creates and adds an element using the given prototype, without introducing + // a link-time dependency on the concrete message type. This method is used to + // implement implicit weak fields. The prototype may be NULL, in which case an + // ImplicitWeakMessage will be used as a placeholder. + google::protobuf::MessageLite* AddWeak(const google::protobuf::MessageLite* prototype); + + template + void Clear(); + + template + void MergeFrom(const RepeatedPtrFieldBase& other); + + inline void InternalSwap(RepeatedPtrFieldBase* other); + + protected: + template + void Add(typename TypeHandler::Type&& value, + std::enable_if* dummy = NULL); + + template + void RemoveLast(); + template + void CopyFrom(const RepeatedPtrFieldBase& other); + + void CloseGap(int start, int num); + + void Reserve(int new_size); + + int Capacity() const; + + // Used for constructing iterators. + void* const* raw_data() const; + void** raw_mutable_data() const; + + template + typename TypeHandler::Type** mutable_data(); + template + const typename TypeHandler::Type* const* data() const; + + template GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE + void Swap(RepeatedPtrFieldBase* other); + + void SwapElements(int index1, int index2); + + template + size_t SpaceUsedExcludingSelfLong() const; + + // Advanced memory management -------------------------------------- + + // Like Add(), but if there are no cleared objects to use, returns NULL. + template + typename TypeHandler::Type* AddFromCleared(); + + template + void AddAllocated(typename TypeHandler::Type* value) { + typename TypeImplementsMergeBehavior::type t; + AddAllocatedInternal(value, t); + } + + template + void UnsafeArenaAddAllocated(typename TypeHandler::Type* value); + + template + typename TypeHandler::Type* ReleaseLast() { + typename TypeImplementsMergeBehavior::type t; + return ReleaseLastInternal(t); + } + + // Releases last element and returns it, but does not do out-of-arena copy. + // And just returns the raw pointer to the contained element in the arena. + template + typename TypeHandler::Type* UnsafeArenaReleaseLast(); + + int ClearedCount() const; + template + void AddCleared(typename TypeHandler::Type* value); + template + typename TypeHandler::Type* ReleaseCleared(); + + template + void AddAllocatedInternal(typename TypeHandler::Type* value, std::true_type); + template + void AddAllocatedInternal(typename TypeHandler::Type* value, std::false_type); + + template GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE + void AddAllocatedSlowWithCopy(typename TypeHandler::Type* value, + Arena* value_arena, + Arena* my_arena); + template GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE + void AddAllocatedSlowWithoutCopy(typename TypeHandler::Type* value); + + template + typename TypeHandler::Type* ReleaseLastInternal(std::true_type); + template + typename TypeHandler::Type* ReleaseLastInternal(std::false_type); + + template GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE + void SwapFallback(RepeatedPtrFieldBase* other); + + inline Arena* GetArenaNoVirtual() const { + return arena_; + } + + private: + static const int kInitialSize = 0; + // A few notes on internal representation: + // + // We use an indirected approach, with struct Rep, to keep + // sizeof(RepeatedPtrFieldBase) equivalent to what it was before arena support + // was added, namely, 3 8-byte machine words on x86-64. An instance of Rep is + // allocated only when the repeated field is non-empty, and it is a + // dynamically-sized struct (the header is directly followed by elements[]). + // We place arena_ and current_size_ directly in the object to avoid cache + // misses due to the indirection, because these fields are checked frequently. + // Placing all fields directly in the RepeatedPtrFieldBase instance costs + // significant performance for memory-sensitive workloads. + Arena* arena_; + int current_size_; + int total_size_; + struct Rep { + int allocated_size; + void* elements[1]; + }; + static const size_t kRepHeaderSize = sizeof(Rep) - sizeof(void*); + // Contains arena ptr and the elements array. We also keep the invariant that + // if rep_ is NULL, then arena is NULL. + Rep* rep_; + + template + static inline typename TypeHandler::Type* cast(void* element) { + return reinterpret_cast(element); + } + template + static inline const typename TypeHandler::Type* cast(const void* element) { + return reinterpret_cast(element); + } + + // Non-templated inner function to avoid code duplication. Takes a function + // pointer to the type-specific (templated) inner allocate/merge loop. + void MergeFromInternal( + const RepeatedPtrFieldBase& other, + void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int)); + + template + void MergeFromInnerLoop( + void** our_elems, void** other_elems, int length, int already_allocated); + + // Internal helper: extend array space if necessary to contain |extend_amount| + // more elements, and return a pointer to the element immediately following + // the old list of elements. This interface factors out common behavior from + // Reserve() and MergeFrom() to reduce code size. |extend_amount| must be > 0. + void** InternalExtend(int extend_amount); + + // The reflection implementation needs to call protected methods directly, + // reinterpreting pointers as being to Message instead of a specific Message + // subclass. + friend class GeneratedMessageReflection; + + // ExtensionSet stores repeated message extensions as + // RepeatedPtrField, but non-lite ExtensionSets need to implement + // SpaceUsedLong(), and thus need to call SpaceUsedExcludingSelfLong() + // reinterpreting MessageLite as Message. ExtensionSet also needs to make use + // of AddFromCleared(), which is not part of the public interface. + friend class ExtensionSet; + + // The MapFieldBase implementation needs to call protected methods directly, + // reinterpreting pointers as being to Message instead of a specific Message + // subclass. + friend class MapFieldBase; + + // The table-driven MergePartialFromCodedStream implementation needs to + // operate on RepeatedPtrField. + friend class MergePartialFromCodedStreamHelper; + + // To parse directly into a proto2 generated class, the upb class GMR_Handlers + // needs to be able to modify a RepeatedPtrFieldBase directly. + friend class upb::google_opensource::GMR_Handlers; + + friend class AccessorHelper; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPtrFieldBase); +}; + +template +class GenericTypeHandler { + public: + typedef GenericType Type; + typedef GenericType WeakType; + static const bool Moveable = false; + + static inline GenericType* New(Arena* arena) { + return ::google::protobuf::Arena::CreateMaybeMessage(arena); + } + static inline GenericType* NewFromPrototype( + const GenericType* prototype, ::google::protobuf::Arena* arena = NULL); + static inline void Delete(GenericType* value, Arena* arena) { + if (arena == NULL) { + delete value; + } + } + static inline ::google::protobuf::Arena* GetArena(GenericType* value) { + return ::google::protobuf::Arena::GetArena(value); + } + static inline void* GetMaybeArenaPointer(GenericType* value) { + return ::google::protobuf::Arena::GetArena(value); + } + + static inline void Clear(GenericType* value) { value->Clear(); } + GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE + static void Merge(const GenericType& from, GenericType* to); + static inline size_t SpaceUsedLong(const GenericType& value) { + return value.SpaceUsedLong(); + } +}; + +template +GenericType* GenericTypeHandler::NewFromPrototype( + const GenericType* /* prototype */, ::google::protobuf::Arena* arena) { + return New(arena); +} +template +void GenericTypeHandler::Merge(const GenericType& from, + GenericType* to) { + to->MergeFrom(from); +} + +// NewFromPrototype() and Merge() are not defined inline here, as we will need +// to do a virtual function dispatch anyways to go from Message* to call +// New/Merge. +template<> +MessageLite* GenericTypeHandler::NewFromPrototype( + const MessageLite* prototype, google::protobuf::Arena* arena); +template<> +inline google::protobuf::Arena* GenericTypeHandler::GetArena( + MessageLite* value) { + return value->GetArena(); +} +template<> +inline void* GenericTypeHandler::GetMaybeArenaPointer( + MessageLite* value) { + return value->GetMaybeArenaPointer(); +} +template <> +void GenericTypeHandler::Merge(const MessageLite& from, + MessageLite* to); +template<> +inline void GenericTypeHandler::Clear(string* value) { + value->clear(); +} +template<> +void GenericTypeHandler::Merge(const string& from, + string* to); + +// Declarations of the specialization as we cannot define them here, as the +// header that defines ProtocolMessage depends on types defined in this header. +#define DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(TypeName) \ + template<> \ + TypeName* GenericTypeHandler::NewFromPrototype( \ + const TypeName* prototype, google::protobuf::Arena* arena); \ + template<> \ + google::protobuf::Arena* GenericTypeHandler::GetArena( \ + TypeName* value); \ + template<> \ + void* GenericTypeHandler::GetMaybeArenaPointer( \ + TypeName* value); + +// Message specialization bodies defined in message.cc. This split is necessary +// to allow proto2-lite (which includes this header) to be independent of +// Message. +DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message) + + +#undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES + +class StringTypeHandler { + public: + typedef string Type; + typedef string WeakType; + static const bool Moveable = std::is_move_constructible::value && + std::is_move_assignable::value; + + static inline string* New(Arena* arena) { + return Arena::Create(arena); + } + static inline string* New(Arena* arena, string&& value) { + return Arena::Create(arena, std::move(value)); + } + static inline string* NewFromPrototype(const string*, + ::google::protobuf::Arena* arena) { + return New(arena); + } + static inline ::google::protobuf::Arena* GetArena(string*) { + return NULL; + } + static inline void* GetMaybeArenaPointer(string* /* value */) { + return NULL; + } + static inline void Delete(string* value, Arena* arena) { + if (arena == NULL) { + delete value; + } + } + static inline void Clear(string* value) { value->clear(); } + static inline void Merge(const string& from, string* to) { *to = from; } + static size_t SpaceUsedLong(const string& value) { + return sizeof(value) + StringSpaceUsedExcludingSelfLong(value); + } +}; + +} // namespace internal + +// RepeatedPtrField is like RepeatedField, but used for repeated strings or +// Messages. +template +class RepeatedPtrField final : private internal::RepeatedPtrFieldBase { + public: + RepeatedPtrField(); + explicit RepeatedPtrField(::google::protobuf::Arena* arena); + + RepeatedPtrField(const RepeatedPtrField& other); + template + RepeatedPtrField(Iter begin, const Iter& end); + ~RepeatedPtrField(); + + RepeatedPtrField& operator=(const RepeatedPtrField& other); + + RepeatedPtrField(RepeatedPtrField&& other) noexcept; + RepeatedPtrField& operator=(RepeatedPtrField&& other) noexcept; + + bool empty() const; + int size() const; + + const Element& Get(int index) const; + Element* Mutable(int index); + Element* Add(); + void Add(Element&& value); + + const Element& operator[](int index) const { return Get(index); } + Element& operator[](int index) { return *Mutable(index); } + + // Remove the last element in the array. + // Ownership of the element is retained by the array. + void RemoveLast(); + + // Delete elements with indices in the range [start .. start+num-1]. + // Caution: implementation moves all elements with indices [start+num .. ]. + // Calling this routine inside a loop can cause quadratic behavior. + void DeleteSubrange(int start, int num); + + void Clear(); + void MergeFrom(const RepeatedPtrField& other); + void CopyFrom(const RepeatedPtrField& other); + + // Reserve space to expand the field to at least the given size. This only + // resizes the pointer array; it doesn't allocate any objects. If the + // array is grown, it will always be at least doubled in size. + void Reserve(int new_size); + + int Capacity() const; + + // Gets the underlying array. This pointer is possibly invalidated by + // any add or remove operation. + Element** mutable_data(); + const Element* const* data() const; + + // Swap entire contents with "other". If they are on separate arenas, then + // copies data. + void Swap(RepeatedPtrField* other); + + // Swap entire contents with "other". Caller should guarantee that either both + // fields are on the same arena or both are on the heap. Swapping between + // different arenas with this function is disallowed and is caught via + // GOOGLE_DCHECK. + void UnsafeArenaSwap(RepeatedPtrField* other); + + // Swap two elements. + void SwapElements(int index1, int index2); + + // STL-like iterator support + typedef internal::RepeatedPtrIterator iterator; + typedef internal::RepeatedPtrIterator const_iterator; + typedef Element value_type; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef int size_type; + typedef ptrdiff_t difference_type; + + iterator begin(); + const_iterator begin() const; + const_iterator cbegin() const; + iterator end(); + const_iterator end() const; + const_iterator cend() const; + + // Reverse iterator support + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + reverse_iterator rbegin() { + return reverse_iterator(end()); + } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(end()); + } + reverse_iterator rend() { + return reverse_iterator(begin()); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } + + // Custom STL-like iterator that iterates over and returns the underlying + // pointers to Element rather than Element itself. + typedef internal::RepeatedPtrOverPtrsIterator + pointer_iterator; + typedef internal::RepeatedPtrOverPtrsIterator + const_pointer_iterator; + pointer_iterator pointer_begin(); + const_pointer_iterator pointer_begin() const; + pointer_iterator pointer_end(); + const_pointer_iterator pointer_end() const; + + // Returns (an estimate of) the number of bytes used by the repeated field, + // excluding sizeof(*this). + size_t SpaceUsedExcludingSelfLong() const; + + int SpaceUsedExcludingSelf() const { + return internal::ToIntSize(SpaceUsedExcludingSelfLong()); + } + + // Advanced memory management -------------------------------------- + // When hardcore memory management becomes necessary -- as it sometimes + // does here at Google -- the following methods may be useful. + + // Add an already-allocated object, passing ownership to the + // RepeatedPtrField. + // + // Note that some special behavior occurs with respect to arenas: + // + // (i) if this field holds submessages, the new submessage will be copied if + // the original is in an arena and this RepeatedPtrField is either in a + // different arena, or on the heap. + // (ii) if this field holds strings, the passed-in string *must* be + // heap-allocated, not arena-allocated. There is no way to dynamically check + // this at runtime, so User Beware. + void AddAllocated(Element* value); + + // Remove the last element and return it, passing ownership to the caller. + // Requires: size() > 0 + // + // If this RepeatedPtrField is on an arena, an object copy is required to pass + // ownership back to the user (for compatible semantics). Use + // UnsafeArenaReleaseLast() if this behavior is undesired. + Element* ReleaseLast(); + + // Add an already-allocated object, skipping arena-ownership checks. The user + // must guarantee that the given object is in the same arena as this + // RepeatedPtrField. + // It is also useful in legacy code that uses temporary ownership to avoid + // copies. Example: + // RepeatedPtrField temp_field; + // temp_field.AddAllocated(new T); + // ... // Do something with temp_field + // temp_field.ExtractSubrange(0, temp_field.size(), nullptr); + // If you put temp_field on the arena this fails, because the ownership + // transfers to the arena at the "AddAllocated" call and is not released + // anymore causing a double delete. UnsafeArenaAddAllocated prevents this. + void UnsafeArenaAddAllocated(Element* value); + + // Remove the last element and return it. Works only when operating on an + // arena. The returned pointer is to the original object in the arena, hence + // has the arena's lifetime. + // Requires: current_size_ > 0 + Element* UnsafeArenaReleaseLast(); + + // Extract elements with indices in the range "[start .. start+num-1]". + // The caller assumes ownership of the extracted elements and is responsible + // for deleting them when they are no longer needed. + // If "elements" is non-NULL, then pointers to the extracted elements + // are stored in "elements[0 .. num-1]" for the convenience of the caller. + // If "elements" is NULL, then the caller must use some other mechanism + // to perform any further operations (like deletion) on these elements. + // Caution: implementation also moves elements with indices [start+num ..]. + // Calling this routine inside a loop can cause quadratic behavior. + // + // Memory copying behavior is identical to ReleaseLast(), described above: if + // this RepeatedPtrField is on an arena, an object copy is performed for each + // returned element, so that all returned element pointers are to + // heap-allocated copies. If this copy is not desired, the user should call + // UnsafeArenaExtractSubrange(). + void ExtractSubrange(int start, int num, Element** elements); + + // Identical to ExtractSubrange() described above, except that when this + // repeated field is on an arena, no object copies are performed. Instead, the + // raw object pointers are returned. Thus, if on an arena, the returned + // objects must not be freed, because they will not be heap-allocated objects. + void UnsafeArenaExtractSubrange(int start, int num, Element** elements); + + // When elements are removed by calls to RemoveLast() or Clear(), they + // are not actually freed. Instead, they are cleared and kept so that + // they can be reused later. This can save lots of CPU time when + // repeatedly reusing a protocol message for similar purposes. + // + // Hardcore programs may choose to manipulate these cleared objects + // to better optimize memory management using the following routines. + + // Get the number of cleared objects that are currently being kept + // around for reuse. + int ClearedCount() const; + // Add an element to the pool of cleared objects, passing ownership to + // the RepeatedPtrField. The element must be cleared prior to calling + // this method. + // + // This method cannot be called when the repeated field is on an arena or when + // |value| is; both cases will trigger a GOOGLE_DCHECK-failure. + void AddCleared(Element* value); + // Remove a single element from the cleared pool and return it, passing + // ownership to the caller. The element is guaranteed to be cleared. + // Requires: ClearedCount() > 0 + // + // + // This method cannot be called when the repeated field is on an arena; doing + // so will trigger a GOOGLE_DCHECK-failure. + Element* ReleaseCleared(); + + // Removes the element referenced by position. + // + // Returns an iterator to the element immediately following the removed + // element. + // + // Invalidates all iterators at or after the removed element, including end(). + iterator erase(const_iterator position); + + // Removes the elements in the range [first, last). + // + // Returns an iterator to the element immediately following the removed range. + // + // Invalidates all iterators at or after the removed range, including end(). + iterator erase(const_iterator first, const_iterator last); + + // Gets the arena on which this RepeatedPtrField stores its elements. + ::google::protobuf::Arena* GetArena() const { + return GetArenaNoVirtual(); + } + + // For internal use only. + // + // This is public due to it being called by generated code. + using RepeatedPtrFieldBase::InternalSwap; + + private: + // Note: RepeatedPtrField SHOULD NOT be subclassed by users. + class TypeHandler; + + // Internal arena accessor expected by helpers in Arena. + inline Arena* GetArenaNoVirtual() const; + + // Implementations for ExtractSubrange(). The copying behavior must be + // included only if the type supports the necessary operations (e.g., + // MergeFrom()), so we must resolve this at compile time. ExtractSubrange() + // uses SFINAE to choose one of the below implementations. + void ExtractSubrangeInternal(int start, int num, Element** elements, + std::true_type); + void ExtractSubrangeInternal(int start, int num, Element** elements, + std::false_type); + + friend class Arena; + friend class MessageLite; + + typedef void InternalArenaConstructable_; + +}; + +// implementation ==================================================== + +template +inline RepeatedField::RepeatedField() + : current_size_(0), + total_size_(0), + ptr_(NULL) { +} + +template +inline RepeatedField::RepeatedField(Arena* arena) + : current_size_(0), + total_size_(0), + ptr_(arena) { +} + +template +inline RepeatedField::RepeatedField(const RepeatedField& other) + : current_size_(0), + total_size_(0), + ptr_(NULL) { + if (other.current_size_ != 0) { + Reserve(other.size()); + AddNAlreadyReserved(other.size()); + CopyArray(Mutable(0), &other.Get(0), other.size()); + } +} + +template +template +RepeatedField::RepeatedField(Iter begin, const Iter& end) + : current_size_(0), + total_size_(0), + ptr_(NULL) { + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + Reserve(reserve); + for (; begin != end; ++begin) { + AddAlreadyReserved(*begin); + } + } else { + for (; begin != end; ++begin) { + Add(*begin); + } + } +} + +template +RepeatedField::~RepeatedField() { + if (total_size_ > 0) { + InternalDeallocate(rep(), total_size_); + } +} + +template +inline RepeatedField& +RepeatedField::operator=(const RepeatedField& other) { + if (this != &other) + CopyFrom(other); + return *this; +} + +template +inline RepeatedField::RepeatedField(RepeatedField&& other) noexcept + : RepeatedField() { + // We don't just call Swap(&other) here because it would perform 3 copies if + // the two fields are on different arenas. + if (other.GetArenaNoVirtual()) { + CopyFrom(other); + } else { + InternalSwap(&other); + } +} + +template +inline RepeatedField& RepeatedField::operator=( + RepeatedField&& other) noexcept { + // We don't just call Swap(&other) here because it would perform 3 copies if + // the two fields are on different arenas. + if (this != &other) { + if (this->GetArenaNoVirtual() != other.GetArenaNoVirtual()) { + CopyFrom(other); + } else { + InternalSwap(&other); + } + } + return *this; +} + +template +inline bool RepeatedField::empty() const { + return current_size_ == 0; +} + +template +inline int RepeatedField::size() const { + return current_size_; +} + +template +inline int RepeatedField::Capacity() const { + return total_size_; +} + +template +inline void RepeatedField::AddAlreadyReserved(const Element& value) { + GOOGLE_DCHECK_LT(current_size_, total_size_); + rep()->elements[current_size_++] = value; +} + +template +inline Element* RepeatedField::AddAlreadyReserved() { + GOOGLE_DCHECK_LT(current_size_, total_size_); + return &rep()->elements[current_size_++]; +} + +template +inline Element* RepeatedField::AddNAlreadyReserved(int elements) { + GOOGLE_DCHECK_LE(current_size_ + elements, total_size_); + // Warning: total_size_ can be NULL if elements == 0 && current_size_ == 0. + // Existing callers depend on this behavior. :( + Element* ret = &ptr_.rep->elements[current_size_]; + current_size_ += elements; + return ret; +} + +template +inline void RepeatedField::Resize(int new_size, const Element& value) { + GOOGLE_DCHECK_GE(new_size, 0); + if (new_size > current_size_) { + Reserve(new_size); + std::fill(&rep()->elements[current_size_], + &rep()->elements[new_size], value); + } + current_size_ = new_size; +} + +template +inline const Element& RepeatedField::Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + return rep()->elements[index]; +} + +template +inline Element* RepeatedField::Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + return &rep()->elements[index]; +} + +template +inline void RepeatedField::Set(int index, const Element& value) { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + rep()->elements[index] = value; +} + +template +inline void RepeatedField::Add(const Element& value) { + if (current_size_ == total_size_) Reserve(total_size_ + 1); + rep()->elements[current_size_++] = value; +} + +template +inline Element* RepeatedField::Add() { + if (current_size_ == total_size_) Reserve(total_size_ + 1); + return &rep()->elements[current_size_++]; +} + +template +inline void RepeatedField::RemoveLast() { + GOOGLE_DCHECK_GT(current_size_, 0); + current_size_--; +} + +template +void RepeatedField::ExtractSubrange( + int start, int num, Element* elements) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, this->current_size_); + + // Save the values of the removed elements if requested. + if (elements != NULL) { + for (int i = 0; i < num; ++i) + elements[i] = this->Get(i + start); + } + + // Slide remaining elements down to fill the gap. + if (num > 0) { + for (int i = start + num; i < this->current_size_; ++i) + this->Set(i - num, this->Get(i)); + this->Truncate(this->current_size_ - num); + } +} + +template +inline void RepeatedField::Clear() { + current_size_ = 0; +} + +template +inline void RepeatedField::MergeFrom(const RepeatedField& other) { + GOOGLE_DCHECK_NE(&other, this); + if (other.current_size_ != 0) { + int existing_size = size(); + Reserve(existing_size + other.size()); + AddNAlreadyReserved(other.size()); + CopyArray(Mutable(existing_size), &other.Get(0), other.size()); + } +} + +template +inline void RepeatedField::CopyFrom(const RepeatedField& other) { + if (&other == this) return; + Clear(); + MergeFrom(other); +} + +template +inline typename RepeatedField::iterator RepeatedField::erase( + const_iterator position) { + return erase(position, position + 1); +} + +template +inline typename RepeatedField::iterator RepeatedField::erase( + const_iterator first, const_iterator last) { + size_type first_offset = first - cbegin(); + if (first != last) { + Truncate(std::copy(last, cend(), begin() + first_offset) - cbegin()); + } + return begin() + first_offset; +} + +template +inline Element* RepeatedField::mutable_data() { + return total_size_ > 0 ? rep()->elements : NULL; +} + +template +inline const Element* RepeatedField::data() const { + return total_size_ > 0 ? rep()->elements : NULL; +} + +template +inline const Element* RepeatedField::unsafe_data() const { + return rep()->elements; +} + +template +inline void RepeatedField::InternalSwap(RepeatedField* other) { + GOOGLE_DCHECK(this != other); + GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + + std::swap(ptr_, other->ptr_); + std::swap(current_size_, other->current_size_); + std::swap(total_size_, other->total_size_); +} + +template +void RepeatedField::Swap(RepeatedField* other) { + if (this == other) return; + if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { + InternalSwap(other); + } else { + RepeatedField temp(other->GetArenaNoVirtual()); + temp.MergeFrom(*this); + CopyFrom(*other); + other->UnsafeArenaSwap(&temp); + } +} + +template +void RepeatedField::UnsafeArenaSwap(RepeatedField* other) { + if (this == other) return; + InternalSwap(other); +} + +template +void RepeatedField::SwapElements(int index1, int index2) { + using std::swap; // enable ADL with fallback + swap(rep()->elements[index1], rep()->elements[index2]); +} + +template +inline typename RepeatedField::iterator +RepeatedField::begin() { + return total_size_ > 0 ? rep()->elements : NULL; +} +template +inline typename RepeatedField::const_iterator +RepeatedField::begin() const { + return total_size_ > 0 ? rep()->elements : NULL; +} +template +inline typename RepeatedField::const_iterator +RepeatedField::cbegin() const { + return total_size_ > 0 ? rep()->elements : NULL; +} +template +inline typename RepeatedField::iterator +RepeatedField::end() { + return total_size_ > 0 ? rep()->elements + current_size_ : NULL; +} +template +inline typename RepeatedField::const_iterator +RepeatedField::end() const { + return total_size_ > 0 ? rep()->elements + current_size_ : NULL; +} +template +inline typename RepeatedField::const_iterator +RepeatedField::cend() const { + return total_size_ > 0 ? rep()->elements + current_size_ : NULL; +} + +template +inline size_t RepeatedField::SpaceUsedExcludingSelfLong() const { + return total_size_ > 0 ? (total_size_ * sizeof(Element) + kRepHeaderSize) : 0; +} + +// Avoid inlining of Reserve(): new, copy, and delete[] lead to a significant +// amount of code bloat. +template +void RepeatedField::Reserve(int new_size) { + if (total_size_ >= new_size) return; + Rep* old_rep = total_size_ > 0 ? rep() : NULL; + Arena* arena = GetArenaNoVirtual(); + new_size = std::max(google::protobuf::internal::kMinRepeatedFieldAllocationSize, + std::max(total_size_ * 2, new_size)); + GOOGLE_DCHECK_LE( + static_cast(new_size), + (std::numeric_limits::max() - kRepHeaderSize) / sizeof(Element)) + << "Requested size is too large to fit into size_t."; + size_t bytes = kRepHeaderSize + sizeof(Element) * static_cast(new_size); + if (arena == NULL) { + ptr_.rep = static_cast(::operator new(bytes)); + } else { + ptr_.rep = reinterpret_cast( + ::google::protobuf::Arena::CreateArray(arena, bytes)); + } + ptr_.rep->arena = arena; + int old_total_size = total_size_; + total_size_ = new_size; + // Invoke placement-new on newly allocated elements. We shouldn't have to do + // this, since Element is supposed to be POD, but a previous version of this + // code allocated storage with "new Element[size]" and some code uses + // RepeatedField with non-POD types, relying on constructor invocation. If + // Element has a trivial constructor (e.g., int32), gcc (tested with -O2) + // completely removes this loop because the loop body is empty, so this has no + // effect unless its side-effects are required for correctness. + // Note that we do this before MoveArray() below because Element's copy + // assignment implementation will want an initialized instance first. + Element* e = &rep()->elements[0]; + Element* limit = e + total_size_; + for (; e < limit; e++) { + new (e) Element; + } + if (current_size_ > 0) { + MoveArray(&rep()->elements[0], old_rep->elements, current_size_); + } + + // Likewise, we need to invoke destructors on the old array. + InternalDeallocate(old_rep, old_total_size); + +} + +template +inline void RepeatedField::Truncate(int new_size) { + GOOGLE_DCHECK_LE(new_size, current_size_); + if (current_size_ > 0) { + current_size_ = new_size; + } +} + +template +inline void RepeatedField::MoveArray( + Element* to, Element* from, int array_size) { + CopyArray(to, from, array_size); +} + +template +inline void RepeatedField::CopyArray( + Element* to, const Element* from, int array_size) { + internal::ElementCopier()(to, from, array_size); +} + +namespace internal { + +template +void ElementCopier::operator()( + Element* to, const Element* from, int array_size) { + std::copy(from, from + array_size, to); +} + +template +struct ElementCopier { + void operator()(Element* to, const Element* from, int array_size) { + memcpy(to, from, static_cast(array_size) * sizeof(Element)); + } +}; + +} // namespace internal + + +// ------------------------------------------------------------------- + +namespace internal { + +inline RepeatedPtrFieldBase::RepeatedPtrFieldBase() + : arena_(NULL), + current_size_(0), + total_size_(0), + rep_(NULL) { +} + +inline RepeatedPtrFieldBase::RepeatedPtrFieldBase(::google::protobuf::Arena* arena) + : arena_(arena), + current_size_(0), + total_size_(0), + rep_(NULL) { +} + +template +void RepeatedPtrFieldBase::Destroy() { + if (rep_ != NULL && arena_ == NULL) { + int n = rep_->allocated_size; + void* const* elements = rep_->elements; + for (int i = 0; i < n; i++) { + TypeHandler::Delete(cast(elements[i]), NULL); + } +#if defined(__GXX_DELETE_WITH_SIZE__) || defined(__cpp_sized_deallocation) + const size_t size = total_size_ * sizeof(elements[0]) + kRepHeaderSize; + ::operator delete(static_cast(rep_), size); +#else + ::operator delete(static_cast(rep_)); +#endif + } + rep_ = NULL; +} + +template +inline void RepeatedPtrFieldBase::Swap(RepeatedPtrFieldBase* other) { + if (other->GetArenaNoVirtual() == GetArenaNoVirtual()) { + InternalSwap(other); + } else { + SwapFallback(other); + } +} + +template +void RepeatedPtrFieldBase::SwapFallback(RepeatedPtrFieldBase* other) { + GOOGLE_DCHECK(other->GetArenaNoVirtual() != GetArenaNoVirtual()); + + // Copy semantics in this case. We try to improve efficiency by placing the + // temporary on |other|'s arena so that messages are copied cross-arena only + // once, not twice. + RepeatedPtrFieldBase temp(other->GetArenaNoVirtual()); + temp.MergeFrom(*this); + this->Clear(); + this->MergeFrom(*other); + other->Clear(); + other->InternalSwap(&temp); + temp.Destroy(); // Frees rep_ if `other` had no arena. +} + +inline bool RepeatedPtrFieldBase::empty() const { + return current_size_ == 0; +} + +inline int RepeatedPtrFieldBase::size() const { + return current_size_; +} + +template +inline const typename TypeHandler::WeakType& +RepeatedPtrFieldBase::Get(int index) const { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + return *cast(rep_->elements[index]); +} + +template +inline typename TypeHandler::Type* +RepeatedPtrFieldBase::Mutable(int index) { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + return cast(rep_->elements[index]); +} + +template +inline void RepeatedPtrFieldBase::Delete(int index) { + GOOGLE_DCHECK_GE(index, 0); + GOOGLE_DCHECK_LT(index, current_size_); + TypeHandler::Delete(cast(rep_->elements[index]), arena_); +} + +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::Add( + typename TypeHandler::Type* prototype) { + if (rep_ != NULL && current_size_ < rep_->allocated_size) { + return cast(rep_->elements[current_size_++]); + } + if (!rep_ || rep_->allocated_size == total_size_) { + Reserve(total_size_ + 1); + } + ++rep_->allocated_size; + typename TypeHandler::Type* result = + TypeHandler::NewFromPrototype(prototype, arena_); + rep_->elements[current_size_++] = result; + return result; +} + +template +inline void RepeatedPtrFieldBase::Add( + typename TypeHandler::Type&& value, + std::enable_if*) { + if (rep_ != NULL && current_size_ < rep_->allocated_size) { + *cast(rep_->elements[current_size_++]) = std::move(value); + return; + } + if (!rep_ || rep_->allocated_size == total_size_) { + Reserve(total_size_ + 1); + } + ++rep_->allocated_size; + typename TypeHandler::Type* result = + TypeHandler::New(arena_, std::move(value)); + rep_->elements[current_size_++] = result; +} + +template +inline void RepeatedPtrFieldBase::RemoveLast() { + GOOGLE_DCHECK_GT(current_size_, 0); + TypeHandler::Clear(cast(rep_->elements[--current_size_])); +} + +template +void RepeatedPtrFieldBase::Clear() { + const int n = current_size_; + GOOGLE_DCHECK_GE(n, 0); + if (n > 0) { + void* const* elements = rep_->elements; + int i = 0; + do { + TypeHandler::Clear(cast(elements[i++])); + } while (i < n); + current_size_ = 0; + } +} + +// To avoid unnecessary code duplication and reduce binary size, we use a +// layered approach to implementing MergeFrom(). The toplevel method is +// templated, so we get a small thunk per concrete message type in the binary. +// This calls a shared implementation with most of the logic, passing a function +// pointer to another type-specific piece of code that calls the object-allocate +// and merge handlers. +template +inline void RepeatedPtrFieldBase::MergeFrom(const RepeatedPtrFieldBase& other) { + GOOGLE_DCHECK_NE(&other, this); + if (other.current_size_ == 0) return; + MergeFromInternal( + other, &RepeatedPtrFieldBase::MergeFromInnerLoop); +} + +inline void RepeatedPtrFieldBase::MergeFromInternal( + const RepeatedPtrFieldBase& other, + void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int)) { + // Note: wrapper has already guaranteed that other.rep_ != NULL here. + int other_size = other.current_size_; + void** other_elements = other.rep_->elements; + void** new_elements = InternalExtend(other_size); + int allocated_elems = rep_->allocated_size - current_size_; + (this->*inner_loop)(new_elements, other_elements, + other_size, allocated_elems); + current_size_ += other_size; + if (rep_->allocated_size < current_size_) { + rep_->allocated_size = current_size_; + } +} + +// Merges other_elems to our_elems. +template +void RepeatedPtrFieldBase::MergeFromInnerLoop( + void** our_elems, void** other_elems, int length, int already_allocated) { + // Split into two loops, over ranges [0, allocated) and [allocated, length), + // to avoid a branch within the loop. + for (int i = 0; i < already_allocated && i < length; i++) { + // Already allocated: use existing element. + typename TypeHandler::WeakType* other_elem = + reinterpret_cast(other_elems[i]); + typename TypeHandler::WeakType* new_elem = + reinterpret_cast(our_elems[i]); + TypeHandler::Merge(*other_elem, new_elem); + } + Arena* arena = GetArenaNoVirtual(); + for (int i = already_allocated; i < length; i++) { + // Not allocated: alloc a new element first, then merge it. + typename TypeHandler::WeakType* other_elem = + reinterpret_cast(other_elems[i]); + typename TypeHandler::WeakType* new_elem = + TypeHandler::NewFromPrototype(other_elem, arena); + TypeHandler::Merge(*other_elem, new_elem); + our_elems[i] = new_elem; + } +} + +template +inline void RepeatedPtrFieldBase::CopyFrom(const RepeatedPtrFieldBase& other) { + if (&other == this) return; + RepeatedPtrFieldBase::Clear(); + RepeatedPtrFieldBase::MergeFrom(other); +} + +inline int RepeatedPtrFieldBase::Capacity() const { + return total_size_; +} + +inline void* const* RepeatedPtrFieldBase::raw_data() const { + return rep_ ? rep_->elements : NULL; +} + +inline void** RepeatedPtrFieldBase::raw_mutable_data() const { + return rep_ ? const_cast(rep_->elements) : NULL; +} + +template +inline typename TypeHandler::Type** RepeatedPtrFieldBase::mutable_data() { + // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this + // method entirely. + return reinterpret_cast(raw_mutable_data()); +} + +template +inline const typename TypeHandler::Type* const* +RepeatedPtrFieldBase::data() const { + // TODO(kenton): Breaks C++ aliasing rules. We should probably remove this + // method entirely. + return reinterpret_cast(raw_data()); +} + +inline void RepeatedPtrFieldBase::SwapElements(int index1, int index2) { + using std::swap; // enable ADL with fallback + swap(rep_->elements[index1], rep_->elements[index2]); +} + +template +inline size_t RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong() const { + size_t allocated_bytes = static_cast(total_size_) * sizeof(void*); + if (rep_ != NULL) { + for (int i = 0; i < rep_->allocated_size; ++i) { + allocated_bytes += TypeHandler::SpaceUsedLong( + *cast(rep_->elements[i])); + } + allocated_bytes += kRepHeaderSize; + } + return allocated_bytes; +} + +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::AddFromCleared() { + if (rep_ != NULL && current_size_ < rep_->allocated_size) { + return cast(rep_->elements[current_size_++]); + } else { + return NULL; + } +} + +// AddAllocated version that implements arena-safe copying behavior. +template +void RepeatedPtrFieldBase::AddAllocatedInternal( + typename TypeHandler::Type* value, + std::true_type) { + Arena* element_arena = reinterpret_cast( + TypeHandler::GetMaybeArenaPointer(value)); + Arena* arena = GetArenaNoVirtual(); + if (arena == element_arena && rep_ && + rep_->allocated_size < total_size_) { + // Fast path: underlying arena representation (tagged pointer) is equal to + // our arena pointer, and we can add to array without resizing it (at least + // one slot that is not allocated). + void** elems = rep_->elements; + if (current_size_ < rep_->allocated_size) { + // Make space at [current] by moving first allocated element to end of + // allocated list. + elems[rep_->allocated_size] = elems[current_size_]; + } + elems[current_size_] = value; + current_size_ = current_size_ + 1; + rep_->allocated_size = rep_->allocated_size + 1; + } else { + AddAllocatedSlowWithCopy( + value, TypeHandler::GetArena(value), arena); + } +} + +// Slowpath handles all cases, copying if necessary. +template +void RepeatedPtrFieldBase::AddAllocatedSlowWithCopy( + // Pass value_arena and my_arena to avoid duplicate virtual call (value) or + // load (mine). + typename TypeHandler::Type* value, Arena* value_arena, Arena* my_arena) { + // Ensure that either the value is in the same arena, or if not, we do the + // appropriate thing: Own() it (if it's on heap and we're in an arena) or copy + // it to our arena/heap (otherwise). + if (my_arena != NULL && value_arena == NULL) { + my_arena->Own(value); + } else if (my_arena != value_arena) { + typename TypeHandler::Type* new_value = + TypeHandler::NewFromPrototype(value, my_arena); + TypeHandler::Merge(*value, new_value); + TypeHandler::Delete(value, value_arena); + value = new_value; + } + + UnsafeArenaAddAllocated(value); +} + +// AddAllocated version that does not implement arena-safe copying behavior. +template +void RepeatedPtrFieldBase::AddAllocatedInternal( + typename TypeHandler::Type* value, + std::false_type) { + if (rep_ && rep_->allocated_size < total_size_) { + // Fast path: underlying arena representation (tagged pointer) is equal to + // our arena pointer, and we can add to array without resizing it (at least + // one slot that is not allocated). + void** elems = rep_->elements; + if (current_size_ < rep_->allocated_size) { + // Make space at [current] by moving first allocated element to end of + // allocated list. + elems[rep_->allocated_size] = elems[current_size_]; + } + elems[current_size_] = value; + current_size_ = current_size_ + 1; + ++rep_->allocated_size; + } else { + UnsafeArenaAddAllocated(value); + } +} + +template +void RepeatedPtrFieldBase::UnsafeArenaAddAllocated( + typename TypeHandler::Type* value) { + // Make room for the new pointer. + if (!rep_ || current_size_ == total_size_) { + // The array is completely full with no cleared objects, so grow it. + Reserve(total_size_ + 1); + ++rep_->allocated_size; + } else if (rep_->allocated_size == total_size_) { + // There is no more space in the pointer array because it contains some + // cleared objects awaiting reuse. We don't want to grow the array in this + // case because otherwise a loop calling AddAllocated() followed by Clear() + // would leak memory. + TypeHandler::Delete( + cast(rep_->elements[current_size_]), arena_); + } else if (current_size_ < rep_->allocated_size) { + // We have some cleared objects. We don't care about their order, so we + // can just move the first one to the end to make space. + rep_->elements[rep_->allocated_size] = rep_->elements[current_size_]; + ++rep_->allocated_size; + } else { + // There are no cleared objects. + ++rep_->allocated_size; + } + + rep_->elements[current_size_++] = value; +} + +// ReleaseLast() for types that implement merge/copy behavior. +template +inline typename TypeHandler::Type* +RepeatedPtrFieldBase::ReleaseLastInternal(std::true_type) { + // First, release an element. + typename TypeHandler::Type* result = UnsafeArenaReleaseLast(); + // Now perform a copy if we're on an arena. + Arena* arena = GetArenaNoVirtual(); + if (arena == NULL) { + return result; + } else { + typename TypeHandler::Type* new_result = + TypeHandler::NewFromPrototype(result, NULL); + TypeHandler::Merge(*result, new_result); + return new_result; + } +} + +// ReleaseLast() for types that *do not* implement merge/copy behavior -- this +// is the same as UnsafeArenaReleaseLast(). Note that we GOOGLE_DCHECK-fail if we're on +// an arena, since the user really should implement the copy operation in this +// case. +template +inline typename TypeHandler::Type* +RepeatedPtrFieldBase::ReleaseLastInternal(std::false_type) { + GOOGLE_DCHECK(GetArenaNoVirtual() == NULL) + << "ReleaseLast() called on a RepeatedPtrField that is on an arena, " + << "with a type that does not implement MergeFrom. This is unsafe; " + << "please implement MergeFrom for your type."; + return UnsafeArenaReleaseLast(); +} + +template +inline typename TypeHandler::Type* + RepeatedPtrFieldBase::UnsafeArenaReleaseLast() { + GOOGLE_DCHECK_GT(current_size_, 0); + typename TypeHandler::Type* result = + cast(rep_->elements[--current_size_]); + --rep_->allocated_size; + if (current_size_ < rep_->allocated_size) { + // There are cleared elements on the end; replace the removed element + // with the last allocated element. + rep_->elements[current_size_] = rep_->elements[rep_->allocated_size]; + } + return result; +} + +inline int RepeatedPtrFieldBase::ClearedCount() const { + return rep_ ? (rep_->allocated_size - current_size_) : 0; +} + +template +inline void RepeatedPtrFieldBase::AddCleared( + typename TypeHandler::Type* value) { + GOOGLE_DCHECK(GetArenaNoVirtual() == NULL) + << "AddCleared() can only be used on a RepeatedPtrField not on an arena."; + GOOGLE_DCHECK(TypeHandler::GetArena(value) == NULL) + << "AddCleared() can only accept values not on an arena."; + if (!rep_ || rep_->allocated_size == total_size_) { + Reserve(total_size_ + 1); + } + rep_->elements[rep_->allocated_size++] = value; +} + +template +inline typename TypeHandler::Type* RepeatedPtrFieldBase::ReleaseCleared() { + GOOGLE_DCHECK(GetArenaNoVirtual() == NULL) + << "ReleaseCleared() can only be used on a RepeatedPtrField not on " + << "an arena."; + GOOGLE_DCHECK(GetArenaNoVirtual() == NULL); + GOOGLE_DCHECK(rep_ != NULL); + GOOGLE_DCHECK_GT(rep_->allocated_size, current_size_); + return cast(rep_->elements[--rep_->allocated_size]); +} + +} // namespace internal + +// ------------------------------------------------------------------- + +template +class RepeatedPtrField::TypeHandler + : public internal::GenericTypeHandler { +}; + +template <> +class RepeatedPtrField::TypeHandler + : public internal::StringTypeHandler { +}; + +template +inline RepeatedPtrField::RepeatedPtrField() + : RepeatedPtrFieldBase() {} + +template +inline RepeatedPtrField::RepeatedPtrField(::google::protobuf::Arena* arena) : + RepeatedPtrFieldBase(arena) {} + +template +inline RepeatedPtrField::RepeatedPtrField( + const RepeatedPtrField& other) + : RepeatedPtrFieldBase() { + MergeFrom(other); +} + +template +template +inline RepeatedPtrField::RepeatedPtrField( + Iter begin, const Iter& end) { + int reserve = internal::CalculateReserve(begin, end); + if (reserve != -1) { + Reserve(reserve); + } + for (; begin != end; ++begin) { + *Add() = *begin; + } +} + +template +RepeatedPtrField::~RepeatedPtrField() { + Destroy(); +} + +template +inline RepeatedPtrField& RepeatedPtrField::operator=( + const RepeatedPtrField& other) { + if (this != &other) + CopyFrom(other); + return *this; +} + +template +inline RepeatedPtrField::RepeatedPtrField( + RepeatedPtrField&& other) noexcept + : RepeatedPtrField() { + // We don't just call Swap(&other) here because it would perform 3 copies if + // the two fields are on different arenas. + if (other.GetArenaNoVirtual()) { + CopyFrom(other); + } else { + InternalSwap(&other); + } +} + +template +inline RepeatedPtrField& RepeatedPtrField::operator=( + RepeatedPtrField&& other) noexcept { + // We don't just call Swap(&other) here because it would perform 3 copies if + // the two fields are on different arenas. + if (this != &other) { + if (this->GetArenaNoVirtual() != other.GetArenaNoVirtual()) { + CopyFrom(other); + } else { + InternalSwap(&other); + } + } + return *this; +} + +template +inline bool RepeatedPtrField::empty() const { + return RepeatedPtrFieldBase::empty(); +} + +template +inline int RepeatedPtrField::size() const { + return RepeatedPtrFieldBase::size(); +} + +template +inline const Element& RepeatedPtrField::Get(int index) const { + return RepeatedPtrFieldBase::Get(index); +} + + +template +inline Element* RepeatedPtrField::Mutable(int index) { + return RepeatedPtrFieldBase::Mutable(index); +} + +template +inline Element* RepeatedPtrField::Add() { + return RepeatedPtrFieldBase::Add(); +} + +template +inline void RepeatedPtrField::Add(Element&& value) { + RepeatedPtrFieldBase::Add(std::move(value)); +} + +template +inline void RepeatedPtrField::RemoveLast() { + RepeatedPtrFieldBase::RemoveLast(); +} + +template +inline void RepeatedPtrField::DeleteSubrange(int start, int num) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, size()); + for (int i = 0; i < num; ++i) { + RepeatedPtrFieldBase::Delete(start + i); + } + ExtractSubrange(start, num, NULL); +} + +template +inline void RepeatedPtrField::ExtractSubrange( + int start, int num, Element** elements) { + typename internal::TypeImplementsMergeBehavior< + typename TypeHandler::Type>::type t; + ExtractSubrangeInternal(start, num, elements, t); +} + +// ExtractSubrange() implementation for types that implement merge/copy +// behavior. +template +inline void RepeatedPtrField::ExtractSubrangeInternal( + int start, int num, Element** elements, std::true_type) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, size()); + + if (num > 0) { + // Save the values of the removed elements if requested. + if (elements != NULL) { + if (GetArenaNoVirtual() != NULL) { + // If we're on an arena, we perform a copy for each element so that the + // returned elements are heap-allocated. + for (int i = 0; i < num; ++i) { + Element* element = RepeatedPtrFieldBase:: + Mutable(i + start); + typename TypeHandler::Type* new_value = + TypeHandler::NewFromPrototype(element, NULL); + TypeHandler::Merge(*element, new_value); + elements[i] = new_value; + } + } else { + for (int i = 0; i < num; ++i) { + elements[i] = RepeatedPtrFieldBase::Mutable(i + start); + } + } + } + CloseGap(start, num); + } +} + +// ExtractSubrange() implementation for types that do not implement merge/copy +// behavior. +template +inline void RepeatedPtrField::ExtractSubrangeInternal( + int start, int num, Element** elements, std::false_type) { + // This case is identical to UnsafeArenaExtractSubrange(). However, since + // ExtractSubrange() must return heap-allocated objects by contract, and we + // cannot fulfill this contract if we are an on arena, we must GOOGLE_DCHECK() that + // we are not on an arena. + GOOGLE_DCHECK(GetArenaNoVirtual() == NULL) + << "ExtractSubrange() when arena is non-NULL is only supported when " + << "the Element type supplies a MergeFrom() operation to make copies."; + UnsafeArenaExtractSubrange(start, num, elements); +} + +template +inline void RepeatedPtrField::UnsafeArenaExtractSubrange( + int start, int num, Element** elements) { + GOOGLE_DCHECK_GE(start, 0); + GOOGLE_DCHECK_GE(num, 0); + GOOGLE_DCHECK_LE(start + num, size()); + + if (num > 0) { + // Save the values of the removed elements if requested. + if (elements != NULL) { + for (int i = 0; i < num; ++i) { + elements[i] = RepeatedPtrFieldBase::Mutable(i + start); + } + } + CloseGap(start, num); + } +} + +template +inline void RepeatedPtrField::Clear() { + RepeatedPtrFieldBase::Clear(); +} + +template +inline void RepeatedPtrField::MergeFrom( + const RepeatedPtrField& other) { + RepeatedPtrFieldBase::MergeFrom(other); +} + +template +inline void RepeatedPtrField::CopyFrom( + const RepeatedPtrField& other) { + RepeatedPtrFieldBase::CopyFrom(other); +} + +template +inline typename RepeatedPtrField::iterator +RepeatedPtrField::erase(const_iterator position) { + return erase(position, position + 1); +} + +template +inline typename RepeatedPtrField::iterator +RepeatedPtrField::erase(const_iterator first, const_iterator last) { + size_type pos_offset = std::distance(cbegin(), first); + size_type last_offset = std::distance(cbegin(), last); + DeleteSubrange(pos_offset, last_offset - pos_offset); + return begin() + pos_offset; +} + +template +inline Element** RepeatedPtrField::mutable_data() { + return RepeatedPtrFieldBase::mutable_data(); +} + +template +inline const Element* const* RepeatedPtrField::data() const { + return RepeatedPtrFieldBase::data(); +} + +template +inline void RepeatedPtrField::Swap(RepeatedPtrField* other) { + if (this == other) + return; + RepeatedPtrFieldBase::Swap(other); +} + +template +inline void RepeatedPtrField::UnsafeArenaSwap( + RepeatedPtrField* other) { + if (this == other) + return; + RepeatedPtrFieldBase::InternalSwap(other); +} + +template +inline void RepeatedPtrField::SwapElements(int index1, int index2) { + RepeatedPtrFieldBase::SwapElements(index1, index2); +} + +template +inline Arena* RepeatedPtrField::GetArenaNoVirtual() const { + return RepeatedPtrFieldBase::GetArenaNoVirtual(); +} + +template +inline size_t RepeatedPtrField::SpaceUsedExcludingSelfLong() const { + return RepeatedPtrFieldBase::SpaceUsedExcludingSelfLong(); +} + +template +inline void RepeatedPtrField::AddAllocated(Element* value) { + RepeatedPtrFieldBase::AddAllocated(value); +} + +template +inline void RepeatedPtrField::UnsafeArenaAddAllocated(Element* value) { + RepeatedPtrFieldBase::UnsafeArenaAddAllocated(value); +} + +template +inline Element* RepeatedPtrField::ReleaseLast() { + return RepeatedPtrFieldBase::ReleaseLast(); +} + +template +inline Element* RepeatedPtrField::UnsafeArenaReleaseLast() { + return RepeatedPtrFieldBase::UnsafeArenaReleaseLast(); +} + +template +inline int RepeatedPtrField::ClearedCount() const { + return RepeatedPtrFieldBase::ClearedCount(); +} + +template +inline void RepeatedPtrField::AddCleared(Element* value) { + return RepeatedPtrFieldBase::AddCleared(value); +} + +template +inline Element* RepeatedPtrField::ReleaseCleared() { + return RepeatedPtrFieldBase::ReleaseCleared(); +} + +template +inline void RepeatedPtrField::Reserve(int new_size) { + return RepeatedPtrFieldBase::Reserve(new_size); +} + +template +inline int RepeatedPtrField::Capacity() const { + return RepeatedPtrFieldBase::Capacity(); +} + +// ------------------------------------------------------------------- + +namespace internal { + +// STL-like iterator implementation for RepeatedPtrField. You should not +// refer to this class directly; use RepeatedPtrField::iterator instead. +// +// The iterator for RepeatedPtrField, RepeatedPtrIterator, is +// very similar to iterator_ptr in util/gtl/iterator_adaptors.h, +// but adds random-access operators and is modified to wrap a void** base +// iterator (since RepeatedPtrField stores its array as a void* array and +// casting void** to T** would violate C++ aliasing rules). +// +// This code based on net/proto/proto-array-internal.h by Jeffrey Yasskin +// (jyasskin@google.com). +template +class RepeatedPtrIterator + : public std::iterator< + std::random_access_iterator_tag, Element> { + public: + typedef RepeatedPtrIterator iterator; + typedef std::iterator< + std::random_access_iterator_tag, Element> superclass; + + // Shadow the value_type in std::iterator<> because const_iterator::value_type + // needs to be T, not const T. + typedef typename std::remove_const::type value_type; + + // Let the compiler know that these are type names, so we don't have to + // write "typename" in front of them everywhere. + typedef typename superclass::reference reference; + typedef typename superclass::pointer pointer; + typedef typename superclass::difference_type difference_type; + + RepeatedPtrIterator() : it_(NULL) {} + explicit RepeatedPtrIterator(void* const* it) : it_(it) {} + + // Allow "upcasting" from RepeatedPtrIterator to + // RepeatedPtrIterator. + template + RepeatedPtrIterator(const RepeatedPtrIterator& other) + : it_(other.it_) { + // Force a compiler error if the other type is not convertible to ours. + if (false) { + implicit_cast(static_cast(nullptr)); + } + } + + // dereferenceable + reference operator*() const { return *reinterpret_cast(*it_); } + pointer operator->() const { return &(operator*()); } + + // {inc,dec}rementable + iterator& operator++() { ++it_; return *this; } + iterator operator++(int) { return iterator(it_++); } + iterator& operator--() { --it_; return *this; } + iterator operator--(int) { return iterator(it_--); } + + // equality_comparable + bool operator==(const iterator& x) const { return it_ == x.it_; } + bool operator!=(const iterator& x) const { return it_ != x.it_; } + + // less_than_comparable + bool operator<(const iterator& x) const { return it_ < x.it_; } + bool operator<=(const iterator& x) const { return it_ <= x.it_; } + bool operator>(const iterator& x) const { return it_ > x.it_; } + bool operator>=(const iterator& x) const { return it_ >= x.it_; } + + // addable, subtractable + iterator& operator+=(difference_type d) { + it_ += d; + return *this; + } + friend iterator operator+(iterator it, const difference_type d) { + it += d; + return it; + } + friend iterator operator+(const difference_type d, iterator it) { + it += d; + return it; + } + iterator& operator-=(difference_type d) { + it_ -= d; + return *this; + } + friend iterator operator-(iterator it, difference_type d) { + it -= d; + return it; + } + + // indexable + reference operator[](difference_type d) const { return *(*this + d); } + + // random access iterator + difference_type operator-(const iterator& x) const { return it_ - x.it_; } + + private: + template + friend class RepeatedPtrIterator; + + // The internal iterator. + void* const* it_; +}; + +// Provide an iterator that operates on pointers to the underlying objects +// rather than the objects themselves as RepeatedPtrIterator does. +// Consider using this when working with stl algorithms that change +// the array. +// The VoidPtr template parameter holds the type-agnostic pointer value +// referenced by the iterator. It should either be "void *" for a mutable +// iterator, or "const void* const" for a constant iterator. +template +class RepeatedPtrOverPtrsIterator + : public std::iterator { + public: + typedef RepeatedPtrOverPtrsIterator iterator; + typedef std::iterator superclass; + + // Shadow the value_type in std::iterator<> because const_iterator::value_type + // needs to be T, not const T. + typedef typename std::remove_const::type value_type; + + // Let the compiler know that these are type names, so we don't have to + // write "typename" in front of them everywhere. + typedef typename superclass::reference reference; + typedef typename superclass::pointer pointer; + typedef typename superclass::difference_type difference_type; + + RepeatedPtrOverPtrsIterator() : it_(NULL) {} + explicit RepeatedPtrOverPtrsIterator(VoidPtr* it) : it_(it) {} + + // dereferenceable + reference operator*() const { return *reinterpret_cast(it_); } + pointer operator->() const { return &(operator*()); } + + // {inc,dec}rementable + iterator& operator++() { ++it_; return *this; } + iterator operator++(int) { return iterator(it_++); } + iterator& operator--() { --it_; return *this; } + iterator operator--(int) { return iterator(it_--); } + + // equality_comparable + bool operator==(const iterator& x) const { return it_ == x.it_; } + bool operator!=(const iterator& x) const { return it_ != x.it_; } + + // less_than_comparable + bool operator<(const iterator& x) const { return it_ < x.it_; } + bool operator<=(const iterator& x) const { return it_ <= x.it_; } + bool operator>(const iterator& x) const { return it_ > x.it_; } + bool operator>=(const iterator& x) const { return it_ >= x.it_; } + + // addable, subtractable + iterator& operator+=(difference_type d) { + it_ += d; + return *this; + } + friend iterator operator+(iterator it, difference_type d) { + it += d; + return it; + } + friend iterator operator+(difference_type d, iterator it) { + it += d; + return it; + } + iterator& operator-=(difference_type d) { + it_ -= d; + return *this; + } + friend iterator operator-(iterator it, difference_type d) { + it -= d; + return it; + } + + // indexable + reference operator[](difference_type d) const { return *(*this + d); } + + // random access iterator + difference_type operator-(const iterator& x) const { return it_ - x.it_; } + + private: + template + friend class RepeatedPtrIterator; + + // The internal iterator. + VoidPtr* it_; +}; + +void RepeatedPtrFieldBase::InternalSwap(RepeatedPtrFieldBase* other) { + GOOGLE_DCHECK(this != other); + GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + + std::swap(rep_, other->rep_); + std::swap(current_size_, other->current_size_); + std::swap(total_size_, other->total_size_); +} + +} // namespace internal + +template +inline typename RepeatedPtrField::iterator +RepeatedPtrField::begin() { + return iterator(raw_data()); +} +template +inline typename RepeatedPtrField::const_iterator +RepeatedPtrField::begin() const { + return iterator(raw_data()); +} +template +inline typename RepeatedPtrField::const_iterator +RepeatedPtrField::cbegin() const { + return begin(); +} +template +inline typename RepeatedPtrField::iterator +RepeatedPtrField::end() { + return iterator(raw_data() + size()); +} +template +inline typename RepeatedPtrField::const_iterator +RepeatedPtrField::end() const { + return iterator(raw_data() + size()); +} +template +inline typename RepeatedPtrField::const_iterator +RepeatedPtrField::cend() const { + return end(); +} + +template +inline typename RepeatedPtrField::pointer_iterator +RepeatedPtrField::pointer_begin() { + return pointer_iterator(raw_mutable_data()); +} +template +inline typename RepeatedPtrField::const_pointer_iterator +RepeatedPtrField::pointer_begin() const { + return const_pointer_iterator(const_cast(raw_data())); +} +template +inline typename RepeatedPtrField::pointer_iterator +RepeatedPtrField::pointer_end() { + return pointer_iterator(raw_mutable_data() + size()); +} +template +inline typename RepeatedPtrField::const_pointer_iterator +RepeatedPtrField::pointer_end() const { + return const_pointer_iterator( + const_cast(raw_data() + size())); +} + + +// Iterators and helper functions that follow the spirit of the STL +// std::back_insert_iterator and std::back_inserter but are tailor-made +// for RepeatedField and RepeatedPtrField. Typical usage would be: +// +// std::copy(some_sequence.begin(), some_sequence.end(), +// google::protobuf::RepeatedFieldBackInserter(proto.mutable_sequence())); +// +// Ported by johannes from util/gtl/proto-array-iterators.h + +namespace internal { +// A back inserter for RepeatedField objects. +template class RepeatedFieldBackInsertIterator + : public std::iterator { + public: + explicit RepeatedFieldBackInsertIterator( + RepeatedField* const mutable_field) + : field_(mutable_field) { + } + RepeatedFieldBackInsertIterator& operator=(const T& value) { + field_->Add(value); + return *this; + } + RepeatedFieldBackInsertIterator& operator*() { + return *this; + } + RepeatedFieldBackInsertIterator& operator++() { + return *this; + } + RepeatedFieldBackInsertIterator& operator++(int /* unused */) { + return *this; + } + + private: + RepeatedField* field_; +}; + +// A back inserter for RepeatedPtrField objects. +template class RepeatedPtrFieldBackInsertIterator + : public std::iterator { + public: + RepeatedPtrFieldBackInsertIterator( + RepeatedPtrField* const mutable_field) + : field_(mutable_field) { + } + RepeatedPtrFieldBackInsertIterator& operator=(const T& value) { + *field_->Add() = value; + return *this; + } + RepeatedPtrFieldBackInsertIterator& operator=( + const T* const ptr_to_value) { + *field_->Add() = *ptr_to_value; + return *this; + } + RepeatedPtrFieldBackInsertIterator& operator=(T&& value) { + *field_->Add() = std::move(value); + return *this; + } + RepeatedPtrFieldBackInsertIterator& operator*() { + return *this; + } + RepeatedPtrFieldBackInsertIterator& operator++() { + return *this; + } + RepeatedPtrFieldBackInsertIterator& operator++(int /* unused */) { + return *this; + } + + private: + RepeatedPtrField* field_; +}; + +// A back inserter for RepeatedPtrFields that inserts by transferring ownership +// of a pointer. +template class AllocatedRepeatedPtrFieldBackInsertIterator + : public std::iterator { + public: + explicit AllocatedRepeatedPtrFieldBackInsertIterator( + RepeatedPtrField* const mutable_field) + : field_(mutable_field) { + } + AllocatedRepeatedPtrFieldBackInsertIterator& operator=( + T* const ptr_to_value) { + field_->AddAllocated(ptr_to_value); + return *this; + } + AllocatedRepeatedPtrFieldBackInsertIterator& operator*() { + return *this; + } + AllocatedRepeatedPtrFieldBackInsertIterator& operator++() { + return *this; + } + AllocatedRepeatedPtrFieldBackInsertIterator& operator++( + int /* unused */) { + return *this; + } + + private: + RepeatedPtrField* field_; +}; + +// Almost identical to AllocatedRepeatedPtrFieldBackInsertIterator. This one +// uses the UnsafeArenaAddAllocated instead. +template +class UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator + : public std::iterator { + public: + explicit UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator( + ::google::protobuf::RepeatedPtrField* const mutable_field) + : field_(mutable_field) { + } + UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator& operator=( + T const* const ptr_to_value) { + field_->UnsafeArenaAddAllocated(const_cast(ptr_to_value)); + return *this; + } + UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator& operator*() { + return *this; + } + UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator& operator++() { + return *this; + } + UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator& operator++( + int /* unused */) { + return *this; + } + + private: + ::google::protobuf::RepeatedPtrField* field_; +}; + +} // namespace internal + +// Provides a back insert iterator for RepeatedField instances, +// similar to std::back_inserter(). +template internal::RepeatedFieldBackInsertIterator +RepeatedFieldBackInserter(RepeatedField* const mutable_field) { + return internal::RepeatedFieldBackInsertIterator(mutable_field); +} + +// Provides a back insert iterator for RepeatedPtrField instances, +// similar to std::back_inserter(). +template internal::RepeatedPtrFieldBackInsertIterator +RepeatedPtrFieldBackInserter(RepeatedPtrField* const mutable_field) { + return internal::RepeatedPtrFieldBackInsertIterator(mutable_field); +} + +// Special back insert iterator for RepeatedPtrField instances, just in +// case someone wants to write generic template code that can access both +// RepeatedFields and RepeatedPtrFields using a common name. +template internal::RepeatedPtrFieldBackInsertIterator +RepeatedFieldBackInserter(RepeatedPtrField* const mutable_field) { + return internal::RepeatedPtrFieldBackInsertIterator(mutable_field); +} + +// Provides a back insert iterator for RepeatedPtrField instances +// similar to std::back_inserter() which transfers the ownership while +// copying elements. +template internal::AllocatedRepeatedPtrFieldBackInsertIterator +AllocatedRepeatedPtrFieldBackInserter( + RepeatedPtrField* const mutable_field) { + return internal::AllocatedRepeatedPtrFieldBackInsertIterator( + mutable_field); +} + +// Similar to AllocatedRepeatedPtrFieldBackInserter, using +// UnsafeArenaAddAllocated instead of AddAllocated. +// This is slightly faster if that matters. It is also useful in legacy code +// that uses temporary ownership to avoid copies. Example: +// RepeatedPtrField temp_field; +// temp_field.AddAllocated(new T); +// ... // Do something with temp_field +// temp_field.ExtractSubrange(0, temp_field.size(), nullptr); +// If you put temp_field on the arena this fails, because the ownership +// transfers to the arena at the "AddAllocated" call and is not released anymore +// causing a double delete. Using UnsafeArenaAddAllocated prevents this. +template +internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator +UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( + ::google::protobuf::RepeatedPtrField* const mutable_field) { + return internal::UnsafeArenaAllocatedRepeatedPtrFieldBackInsertIterator( + mutable_field); +} + +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_REPEATED_FIELD_H__ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field_reflection_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field_reflection_unittest.cc new file mode 100644 index 000000000..74ec83b05 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field_reflection_unittest.cc @@ -0,0 +1,721 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: tgs@google.com (Tom Szymanski) +// +// Test reflection methods for aggregate access to Repeated[Ptr]Fields. +// This test proto2 methods on a proto2 layout. + +#include +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { + +using unittest::ForeignMessage; +using unittest::TestAllTypes; +using unittest::TestAllExtensions; + +namespace { + +static int Func(int i, int j) { + return i * j; +} + +static string StrFunc(int i, int j) { + string str; + SStringPrintf(&str, "%d", Func(i, 4)); + return str; +} + +TEST(RepeatedFieldReflectionTest, RegularFields) { + TestAllTypes message; + const Reflection* refl = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + for (int i = 0; i < 10; ++i) { + message.add_repeated_int32(Func(i, 1)); + message.add_repeated_double(Func(i, 2)); + message.add_repeated_string(StrFunc(i, 5)); + message.add_repeated_foreign_message()->set_c(Func(i, 6)); + } + + // Get FieldDescriptors for all the fields of interest. + const FieldDescriptor* fd_repeated_int32 = + desc->FindFieldByName("repeated_int32"); + const FieldDescriptor* fd_repeated_double = + desc->FindFieldByName("repeated_double"); + const FieldDescriptor* fd_repeated_string = + desc->FindFieldByName("repeated_string"); + const FieldDescriptor* fd_repeated_foreign_message = + desc->FindFieldByName("repeated_foreign_message"); + + // Get RepeatedField objects for all fields of interest. + const RepeatedField& rf_int32 = + refl->GetRepeatedField(message, fd_repeated_int32); + const RepeatedField& rf_double = + refl->GetRepeatedField(message, fd_repeated_double); + + // Get mutable RepeatedField objects for all fields of interest. + RepeatedField* mrf_int32 = + refl->MutableRepeatedField(&message, fd_repeated_int32); + RepeatedField* mrf_double = + refl->MutableRepeatedField(&message, fd_repeated_double); + + // Get RepeatedPtrField objects for all fields of interest. + const RepeatedPtrField& rpf_string = + refl->GetRepeatedPtrField(message, fd_repeated_string); + const RepeatedPtrField& rpf_foreign_message = + refl->GetRepeatedPtrField( + message, fd_repeated_foreign_message); + const RepeatedPtrField& rpf_message = + refl->GetRepeatedPtrField( + message, fd_repeated_foreign_message); + + // Get mutable RepeatedPtrField objects for all fields of interest. + RepeatedPtrField* mrpf_string = + refl->MutableRepeatedPtrField(&message, fd_repeated_string); + RepeatedPtrField* mrpf_foreign_message = + refl->MutableRepeatedPtrField( + &message, fd_repeated_foreign_message); + RepeatedPtrField* mrpf_message = + refl->MutableRepeatedPtrField( + &message, fd_repeated_foreign_message); + + // Make sure we can do gets and sets through the Repeated[Ptr]Field objects. + for (int i = 0; i < 10; ++i) { + // Check gets through const objects. + EXPECT_EQ(rf_int32.Get(i), Func(i, 1)); + EXPECT_EQ(rf_double.Get(i), Func(i, 2)); + EXPECT_EQ(rpf_string.Get(i), StrFunc(i, 5)); + EXPECT_EQ(rpf_foreign_message.Get(i).c(), Func(i, 6)); + EXPECT_EQ(down_cast(&rpf_message.Get(i))->c(), + Func(i, 6)); + + // Check gets through mutable objects. + EXPECT_EQ(mrf_int32->Get(i), Func(i, 1)); + EXPECT_EQ(mrf_double->Get(i), Func(i, 2)); + EXPECT_EQ(mrpf_string->Get(i), StrFunc(i, 5)); + EXPECT_EQ(mrpf_foreign_message->Get(i).c(), Func(i, 6)); + EXPECT_EQ(down_cast(&mrpf_message->Get(i))->c(), + Func(i, 6)); + + // Check sets through mutable objects. + mrf_int32->Set(i, Func(i, -1)); + mrf_double->Set(i, Func(i, -2)); + mrpf_string->Mutable(i)->assign(StrFunc(i, -5)); + mrpf_foreign_message->Mutable(i)->set_c(Func(i, -6)); + EXPECT_EQ(message.repeated_int32(i), Func(i, -1)); + EXPECT_EQ(message.repeated_double(i), Func(i, -2)); + EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5)); + EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6)); + down_cast(mrpf_message->Mutable(i))->set_c(Func(i, 7)); + EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7)); + } + +#ifdef PROTOBUF_HAS_DEATH_TEST + // Make sure types are checked correctly at runtime. + const FieldDescriptor* fd_optional_int32 = + desc->FindFieldByName("optional_int32"); + EXPECT_DEATH(refl->GetRepeatedField( + message, fd_optional_int32), "requires a repeated field"); + EXPECT_DEATH(refl->GetRepeatedField( + message, fd_repeated_int32), "not the right type"); + EXPECT_DEATH(refl->GetRepeatedPtrField( + message, fd_repeated_foreign_message), "wrong submessage type"); +#endif // PROTOBUF_HAS_DEATH_TEST +} + + +TEST(RepeatedFieldReflectionTest, ExtensionFields) { + TestAllExtensions extended_message; + const Reflection* refl = extended_message.GetReflection(); + const Descriptor* desc = extended_message.GetDescriptor(); + + for (int i = 0; i < 10; ++i) { + extended_message.AddExtension( + unittest::repeated_int64_extension, Func(i, 1)); + } + + const FieldDescriptor* fd_repeated_int64_extension = + desc->file()->FindExtensionByName("repeated_int64_extension"); + GOOGLE_CHECK(fd_repeated_int64_extension != NULL); + + const RepeatedField& rf_int64_extension = + refl->GetRepeatedField(extended_message, + fd_repeated_int64_extension); + + RepeatedField* mrf_int64_extension = + refl->MutableRepeatedField(&extended_message, + fd_repeated_int64_extension); + + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i)); + mrf_int64_extension->Set(i, Func(i, -1)); + EXPECT_EQ(Func(i, -1), + extended_message.GetExtension(unittest::repeated_int64_extension, i)); + } +} + +template +void TestRepeatedFieldRefIteratorForPrimitive( + const Ref& handle, const MessageType& message, + ValueType (MessageType::*GetFunc)(int) const) { + int index = 0; + for (typename Ref::const_iterator it = handle.begin(); + it != handle.end(); ++it) { + EXPECT_EQ((message.*GetFunc)(index), *it); + ++index; + } + EXPECT_EQ(handle.size(), index); +} + +template +void TestRepeatedFieldRefIteratorForString( + const RepeatedFieldRef& handle, const MessageType& message, + ValueType (MessageType::*GetFunc)(int) const) { + int index = 0; + for (typename RepeatedFieldRef::const_iterator it = handle.begin(); + it != handle.end(); ++it) { + // Test both operator* and operator-> + EXPECT_EQ((message.*GetFunc)(index), *it); + EXPECT_EQ((message.*GetFunc)(index).size(), it->size()); + ++index; + } + EXPECT_EQ(handle.size(), index); +} + +TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForRegularFields) { + TestAllTypes message; + const Reflection* refl = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + for (int i = 0; i < 10; ++i) { + message.add_repeated_int32(Func(i, 1)); + message.add_repeated_double(Func(i, 2)); + message.add_repeated_string(StrFunc(i, 5)); + message.add_repeated_foreign_message()->set_c(Func(i, 6)); + } + + // Get FieldDescriptors for all the fields of interest. + const FieldDescriptor* fd_repeated_int32 = + desc->FindFieldByName("repeated_int32"); + const FieldDescriptor* fd_repeated_double = + desc->FindFieldByName("repeated_double"); + const FieldDescriptor* fd_repeated_string = + desc->FindFieldByName("repeated_string"); + const FieldDescriptor* fd_repeated_foreign_message = + desc->FindFieldByName("repeated_foreign_message"); + + // Get RepeatedFieldRef objects for all fields of interest. + const RepeatedFieldRef rf_int32 = + refl->GetRepeatedFieldRef(message, fd_repeated_int32); + const RepeatedFieldRef rf_double = + refl->GetRepeatedFieldRef(message, fd_repeated_double); + const RepeatedFieldRef rf_string = + refl->GetRepeatedFieldRef(message, fd_repeated_string); + const RepeatedFieldRef rf_foreign_message = + refl->GetRepeatedFieldRef( + message, fd_repeated_foreign_message); + const RepeatedFieldRef rf_message = + refl->GetRepeatedFieldRef( + message, fd_repeated_foreign_message); + + // Get MutableRepeatedFieldRef objects for all fields of interest. + const MutableRepeatedFieldRef mrf_int32 = + refl->GetMutableRepeatedFieldRef(&message, fd_repeated_int32); + const MutableRepeatedFieldRef mrf_double = + refl->GetMutableRepeatedFieldRef(&message, fd_repeated_double); + const MutableRepeatedFieldRef mrf_string = + refl->GetMutableRepeatedFieldRef(&message, fd_repeated_string); + const MutableRepeatedFieldRef mrf_foreign_message = + refl->GetMutableRepeatedFieldRef( + &message, fd_repeated_foreign_message); + const MutableRepeatedFieldRef mrf_message = + refl->GetMutableRepeatedFieldRef( + &message, fd_repeated_foreign_message); + + EXPECT_EQ(message.repeated_int32_size(), rf_int32.size()); + EXPECT_EQ(message.repeated_int32_size(), mrf_int32.size()); + EXPECT_EQ(message.repeated_double_size(), rf_double.size()); + EXPECT_EQ(message.repeated_double_size(), mrf_double.size()); + EXPECT_EQ(message.repeated_string_size(), rf_string.size()); + EXPECT_EQ(message.repeated_string_size(), mrf_string.size()); + EXPECT_EQ(message.repeated_foreign_message_size(), + rf_foreign_message.size()); + EXPECT_EQ(message.repeated_foreign_message_size(), + mrf_foreign_message.size()); + EXPECT_EQ(message.repeated_foreign_message_size(), rf_message.size()); + EXPECT_EQ(message.repeated_foreign_message_size(), mrf_message.size()); + + EXPECT_FALSE(rf_int32.empty()); + EXPECT_FALSE(mrf_int32.empty()); + EXPECT_FALSE(rf_double.empty()); + EXPECT_FALSE(mrf_double.empty()); + EXPECT_FALSE(rf_string.empty()); + EXPECT_FALSE(mrf_string.empty()); + EXPECT_FALSE(rf_foreign_message.empty()); + EXPECT_FALSE(mrf_foreign_message.empty()); + EXPECT_FALSE(rf_message.empty()); + EXPECT_FALSE(mrf_message.empty()); + + // Make sure we can do gets and sets through the RepeatedFieldRef objects. + for (int i = 0; i < 10; ++i) { + // Check gets through const objects. + EXPECT_EQ(rf_int32.Get(i), Func(i, 1)); + EXPECT_EQ(rf_double.Get(i), Func(i, 2)); + EXPECT_EQ(rf_string.Get(i), StrFunc(i, 5)); + ForeignMessage scratch_space; + EXPECT_EQ(rf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6)); + EXPECT_EQ(down_cast( + rf_message.Get(i, &scratch_space)).c(), Func(i, 6)); + + // Check gets through mutable objects. + EXPECT_EQ(mrf_int32.Get(i), Func(i, 1)); + EXPECT_EQ(mrf_double.Get(i), Func(i, 2)); + EXPECT_EQ(mrf_string.Get(i), StrFunc(i, 5)); + EXPECT_EQ(mrf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6)); + EXPECT_EQ(down_cast( + mrf_message.Get(i, &scratch_space)).c(), Func(i, 6)); + + // Check sets through mutable objects. + mrf_int32.Set(i, Func(i, -1)); + mrf_double.Set(i, Func(i, -2)); + mrf_string.Set(i, StrFunc(i, -5)); + ForeignMessage foreign_message; + foreign_message.set_c(Func(i, -6)); + mrf_foreign_message.Set(i, foreign_message); + EXPECT_EQ(message.repeated_int32(i), Func(i, -1)); + EXPECT_EQ(message.repeated_double(i), Func(i, -2)); + EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5)); + EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6)); + foreign_message.set_c(Func(i, 7)); + mrf_message.Set(i, foreign_message); + EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7)); + } + + // Test iterators. + TestRepeatedFieldRefIteratorForPrimitive(rf_int32, message, + &TestAllTypes::repeated_int32); + TestRepeatedFieldRefIteratorForPrimitive(rf_double, message, + &TestAllTypes::repeated_double); + TestRepeatedFieldRefIteratorForString(rf_string, message, + &TestAllTypes::repeated_string); + + // Test iterators for message fields. + typedef RepeatedFieldRef::iterator MessageIterator; + int index = 0; + for (MessageIterator it = rf_foreign_message.begin(); + it != rf_foreign_message.end(); ++it) { + EXPECT_EQ(message.repeated_foreign_message(index).c(), it->c()); + ++index; + } + EXPECT_EQ(10, index); + + // Test iterator operators that are not ususally used in regular for-loops. + // Including: post increment, assign, ==. + MessageIterator old_it = rf_foreign_message.begin(); + MessageIterator new_it = old_it++; + EXPECT_FALSE(old_it == new_it); + // Check that old_it++ increments old_it once. + for (index = 1; old_it != rf_foreign_message.end(); ++old_it, ++index) { + EXPECT_EQ(message.repeated_foreign_message(index).c(), old_it->c()); + } + EXPECT_EQ(10, index); + // Test assign operator. + old_it = new_it; + for (index = 0; old_it != rf_foreign_message.end(); ++old_it, ++index) { + EXPECT_EQ(message.repeated_foreign_message(index).c(), old_it->c()); + } + EXPECT_EQ(10, index); + // Check that the returned value of old_it++ is the one before increment. + for (index = 0; new_it != rf_foreign_message.end(); ++new_it, ++index) { + EXPECT_EQ(message.repeated_foreign_message(index).c(), new_it->c()); + } + EXPECT_EQ(10, index); + + // Test MutableRepeatedFieldRef::Add() + mrf_int32.Add(1234); + mrf_double.Add(1234.0); + mrf_string.Add("1234"); + ForeignMessage foreign_message; + foreign_message.set_c(1234); + mrf_foreign_message.Add(foreign_message); + EXPECT_EQ(1234, message.repeated_int32(10)); + EXPECT_EQ(1234.0, message.repeated_double(10)); + EXPECT_EQ("1234", message.repeated_string(10)); + EXPECT_EQ(1234, message.repeated_foreign_message(10).c()); + + // Test MutableRepeatedFieldRef::RemoveLast() + mrf_int32.RemoveLast(); + mrf_double.RemoveLast(); + mrf_string.RemoveLast(); + mrf_foreign_message.RemoveLast(); + EXPECT_EQ(10, message.repeated_int32_size()); + EXPECT_EQ(10, message.repeated_double_size()); + EXPECT_EQ(10, message.repeated_string_size()); + EXPECT_EQ(10, message.repeated_foreign_message_size()); + + // Test MutableRepeatedFieldRef::SwapElements() + mrf_int32.SwapElements(0, 9); + mrf_double.SwapElements(0, 9); + mrf_string.SwapElements(0, 9); + mrf_foreign_message.SwapElements(0, 9); + EXPECT_EQ(Func(9, -1), message.repeated_int32(0)); + EXPECT_EQ(Func(0, -1), message.repeated_int32(9)); + EXPECT_EQ(Func(9, -2), message.repeated_double(0)); + EXPECT_EQ(Func(0, -2), message.repeated_double(9)); + EXPECT_EQ(StrFunc(9, -5), message.repeated_string(0)); + EXPECT_EQ(StrFunc(0, -5), message.repeated_string(9)); + EXPECT_EQ(Func(9, 7), message.repeated_foreign_message(0).c()); + EXPECT_EQ(Func(0, 7), message.repeated_foreign_message(9).c()); + + // Test MutableRepeatedFieldRef::Clear() + mrf_int32.Clear(); + mrf_double.Clear(); + mrf_string.Clear(); + mrf_foreign_message.Clear(); + EXPECT_EQ(0, message.repeated_int32_size()); + EXPECT_EQ(0, message.repeated_double_size()); + EXPECT_EQ(0, message.repeated_string_size()); + EXPECT_EQ(0, message.repeated_foreign_message_size()); + + // Test (Mutable)RepeatedFieldRef::empty() + EXPECT_TRUE(rf_int32.empty()); + EXPECT_TRUE(mrf_int32.empty()); + EXPECT_TRUE(rf_double.empty()); + EXPECT_TRUE(mrf_double.empty()); + EXPECT_TRUE(rf_string.empty()); + EXPECT_TRUE(mrf_string.empty()); + EXPECT_TRUE(rf_foreign_message.empty()); + EXPECT_TRUE(mrf_foreign_message.empty()); + EXPECT_TRUE(rf_message.empty()); + EXPECT_TRUE(mrf_message.empty()); + +#ifdef PROTOBUF_HAS_DEATH_TEST + + // Make sure types are checked correctly at runtime. + const FieldDescriptor* fd_optional_int32 = + desc->FindFieldByName("optional_int32"); + EXPECT_DEATH(refl->GetRepeatedFieldRef( + message, fd_optional_int32), ""); + EXPECT_DEATH(refl->GetRepeatedFieldRef( + message, fd_repeated_int32), ""); + EXPECT_DEATH(refl->GetRepeatedFieldRef( + message, fd_repeated_foreign_message), ""); + +#endif // PROTOBUF_HAS_DEATH_TEST +} + +TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForEnums) { + TestAllTypes message; + const Reflection* refl = message.GetReflection(); + const Descriptor* desc = message.GetDescriptor(); + + for (int i = 0; i < 10; ++i) { + message.add_repeated_nested_enum(TestAllTypes::BAR); + } + + const FieldDescriptor* fd_repeated_nested_enum = + desc->FindFieldByName("repeated_nested_enum"); + const RepeatedFieldRef enum_ref = + refl->GetRepeatedFieldRef( + message, fd_repeated_nested_enum); + const MutableRepeatedFieldRef + mutable_enum_ref = + refl->GetMutableRepeatedFieldRef( + &message, fd_repeated_nested_enum); + const RepeatedFieldRef int32_ref = + refl->GetRepeatedFieldRef( + message, fd_repeated_nested_enum); + const MutableRepeatedFieldRef mutable_int32_ref = + refl->GetMutableRepeatedFieldRef( + &message, fd_repeated_nested_enum); + + EXPECT_EQ(message.repeated_nested_enum_size(), enum_ref.size()); + EXPECT_EQ(message.repeated_nested_enum_size(), mutable_enum_ref.size()); + EXPECT_EQ(message.repeated_nested_enum_size(), int32_ref.size()); + EXPECT_EQ(message.repeated_nested_enum_size(), mutable_int32_ref.size()); + + EXPECT_FALSE(enum_ref.empty()); + EXPECT_FALSE(mutable_enum_ref.empty()); + EXPECT_FALSE(int32_ref.empty()); + EXPECT_FALSE(mutable_int32_ref.empty()); + + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(TestAllTypes::BAR, enum_ref.Get(i)); + EXPECT_EQ(TestAllTypes::BAR, mutable_enum_ref.Get(i)); + mutable_enum_ref.Set(i, TestAllTypes::BAZ); + EXPECT_EQ(TestAllTypes::BAZ, enum_ref.Get(i)); + EXPECT_EQ(TestAllTypes::BAZ, message.repeated_nested_enum(i)); + + message.set_repeated_nested_enum(i, TestAllTypes::BAR); + EXPECT_EQ(TestAllTypes::BAR, int32_ref.Get(i)); + EXPECT_EQ(TestAllTypes::BAR, mutable_int32_ref.Get(i)); + mutable_int32_ref.Set(i, TestAllTypes::BAZ); + EXPECT_EQ(TestAllTypes::BAZ, int32_ref.Get(i)); + EXPECT_EQ(TestAllTypes::BAZ, message.repeated_nested_enum(i)); + } + + TestRepeatedFieldRefIteratorForPrimitive(enum_ref, message, + &TestAllTypes::repeated_nested_enum); + TestRepeatedFieldRefIteratorForPrimitive(int32_ref, message, + &TestAllTypes::repeated_nested_enum); + + // Test Add() + mutable_enum_ref.Add(TestAllTypes::FOO); + EXPECT_EQ(TestAllTypes::FOO, message.repeated_nested_enum(10)); + mutable_int32_ref.Add(TestAllTypes::BAR); + EXPECT_EQ(TestAllTypes::BAR, message.repeated_nested_enum(11)); + + // Test RemoveLast() + mutable_enum_ref.RemoveLast(); + EXPECT_EQ(11, message.repeated_nested_enum_size()); + mutable_int32_ref.RemoveLast(); + EXPECT_EQ(10, message.repeated_nested_enum_size()); + + // Test SwapElements() + mutable_enum_ref.Set(0, TestAllTypes::BAR); + mutable_enum_ref.Set(9, TestAllTypes::BAZ); + mutable_enum_ref.SwapElements(0, 9); + EXPECT_EQ(TestAllTypes::BAZ, enum_ref.Get(0)); + EXPECT_EQ(TestAllTypes::BAR, enum_ref.Get(9)); + mutable_int32_ref.SwapElements(0, 9); + EXPECT_EQ(TestAllTypes::BAR, enum_ref.Get(0)); + EXPECT_EQ(TestAllTypes::BAZ, enum_ref.Get(9)); + + // Test Clear() + mutable_enum_ref.Clear(); + EXPECT_EQ(0, message.repeated_nested_enum_size()); + mutable_enum_ref.Add(TestAllTypes::FOO); + EXPECT_EQ(1, message.repeated_nested_enum_size()); + mutable_int32_ref.Clear(); + EXPECT_EQ(0, message.repeated_nested_enum_size()); + + // Test empty() + EXPECT_TRUE(enum_ref.empty()); + EXPECT_TRUE(mutable_enum_ref.empty()); + EXPECT_TRUE(int32_ref.empty()); + EXPECT_TRUE(mutable_int32_ref.empty()); +} + +TEST(RepeatedFieldReflectionTest, RepeatedFieldRefForExtensionFields) { + TestAllExtensions extended_message; + const Reflection* refl = extended_message.GetReflection(); + const Descriptor* desc = extended_message.GetDescriptor(); + + for (int i = 0; i < 10; ++i) { + extended_message.AddExtension( + unittest::repeated_int64_extension, Func(i, 1)); + } + + const FieldDescriptor* fd_repeated_int64_extension = + desc->file()->FindExtensionByName("repeated_int64_extension"); + GOOGLE_CHECK(fd_repeated_int64_extension != NULL); + + const RepeatedFieldRef rf_int64_extension = + refl->GetRepeatedFieldRef(extended_message, + fd_repeated_int64_extension); + + const MutableRepeatedFieldRef mrf_int64_extension = + refl->GetMutableRepeatedFieldRef(&extended_message, + fd_repeated_int64_extension); + + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(Func(i, 1), rf_int64_extension.Get(i)); + mrf_int64_extension.Set(i, Func(i, -1)); + EXPECT_EQ(Func(i, -1), + extended_message.GetExtension(unittest::repeated_int64_extension, i)); + } +} + + +TEST(RepeatedFieldReflectionTest, RepeatedFieldRefMergeFromAndSwap) { + // Set-up message content. + TestAllTypes m0, m1, m2; + for (int i = 0; i < 10; ++i) { + m0.add_repeated_int32(Func(i, 1)); + m0.add_repeated_double(Func(i, 2)); + m0.add_repeated_string(StrFunc(i, 5)); + m0.add_repeated_foreign_message()->set_c(Func(i, 6)); + m0.add_repeated_nested_enum(TestAllTypes::FOO); + m1.add_repeated_int32(Func(i, 11)); + m1.add_repeated_double(Func(i, 12)); + m1.add_repeated_string(StrFunc(i, 15)); + m1.add_repeated_foreign_message()->set_c(Func(i, 16)); + m1.add_repeated_nested_enum(TestAllTypes::BAR); + m2.add_repeated_int32(Func(i, 21)); + m2.add_repeated_double(Func(i, 22)); + m2.add_repeated_string(StrFunc(i, 25)); + m2.add_repeated_foreign_message()->set_c(Func(i, 26)); + m2.add_repeated_nested_enum(TestAllTypes::BAZ); + } + + const Reflection* refl = m0.GetReflection(); + const Descriptor* desc = m0.GetDescriptor(); + + // Get FieldDescriptors for all the fields of interest. + const FieldDescriptor* fd_repeated_int32 = + desc->FindFieldByName("repeated_int32"); + const FieldDescriptor* fd_repeated_double = + desc->FindFieldByName("repeated_double"); + const FieldDescriptor* fd_repeated_string = + desc->FindFieldByName("repeated_string"); + const FieldDescriptor* fd_repeated_foreign_message = + desc->FindFieldByName("repeated_foreign_message"); + const FieldDescriptor* fd_repeated_nested_enum = + desc->FindFieldByName("repeated_nested_enum"); + + // Get MutableRepeatedFieldRef objects for all fields of interest. + const MutableRepeatedFieldRef mrf_int32 = + refl->GetMutableRepeatedFieldRef(&m0, fd_repeated_int32); + const MutableRepeatedFieldRef mrf_double = + refl->GetMutableRepeatedFieldRef(&m0, fd_repeated_double); + const MutableRepeatedFieldRef mrf_string = + refl->GetMutableRepeatedFieldRef(&m0, fd_repeated_string); + const MutableRepeatedFieldRef mrf_foreign_message = + refl->GetMutableRepeatedFieldRef( + &m0, fd_repeated_foreign_message); + const MutableRepeatedFieldRef + mrf_nested_enum = + refl->GetMutableRepeatedFieldRef( + &m0, fd_repeated_nested_enum); + + // Test MutableRepeatedRef::CopyFrom + mrf_int32.CopyFrom( + refl->GetRepeatedFieldRef(m1, fd_repeated_int32)); + mrf_double.CopyFrom( + refl->GetRepeatedFieldRef(m1, fd_repeated_double)); + mrf_string.CopyFrom( + refl->GetRepeatedFieldRef(m1, fd_repeated_string)); + mrf_foreign_message.CopyFrom( + refl->GetRepeatedFieldRef( + m1, fd_repeated_foreign_message)); + mrf_nested_enum.CopyFrom( + refl->GetRepeatedFieldRef( + m1, fd_repeated_nested_enum)); + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(Func(i, 11), m0.repeated_int32(i)); + EXPECT_EQ(Func(i, 12), m0.repeated_double(i)); + EXPECT_EQ(StrFunc(i, 15), m0.repeated_string(i)); + EXPECT_EQ(Func(i, 16), m0.repeated_foreign_message(i).c()); + EXPECT_EQ(TestAllTypes::BAR, m0.repeated_nested_enum(i)); + } + + // Test MutableRepeatedRef::MergeFrom + mrf_int32.MergeFrom( + refl->GetRepeatedFieldRef(m2, fd_repeated_int32)); + mrf_double.MergeFrom( + refl->GetRepeatedFieldRef(m2, fd_repeated_double)); + mrf_string.MergeFrom( + refl->GetRepeatedFieldRef(m2, fd_repeated_string)); + mrf_foreign_message.MergeFrom( + refl->GetRepeatedFieldRef( + m2, fd_repeated_foreign_message)); + mrf_nested_enum.MergeFrom( + refl->GetRepeatedFieldRef( + m2, fd_repeated_nested_enum)); + for (int i = 0; i < 10; ++i) { + EXPECT_EQ(Func(i, 21), m0.repeated_int32(i + 10)); + EXPECT_EQ(Func(i, 22), m0.repeated_double(i + 10)); + EXPECT_EQ(StrFunc(i, 25), m0.repeated_string(i + 10)); + EXPECT_EQ(Func(i, 26), m0.repeated_foreign_message(i + 10).c()); + EXPECT_EQ(TestAllTypes::BAZ, m0.repeated_nested_enum(i + 10)); + } + + // Test MutableRepeatedRef::Swap + // Swap between m0 and m2. + mrf_int32.Swap( + refl->GetMutableRepeatedFieldRef(&m2, fd_repeated_int32)); + mrf_double.Swap( + refl->GetMutableRepeatedFieldRef(&m2, fd_repeated_double)); + mrf_string.Swap( + refl->GetMutableRepeatedFieldRef(&m2, fd_repeated_string)); + mrf_foreign_message.Swap( + refl->GetMutableRepeatedFieldRef( + &m2, fd_repeated_foreign_message)); + mrf_nested_enum.Swap( + refl->GetMutableRepeatedFieldRef( + &m2, fd_repeated_nested_enum)); + for (int i = 0; i < 10; ++i) { + // Check the content of m0. + EXPECT_EQ(Func(i, 21), m0.repeated_int32(i)); + EXPECT_EQ(Func(i, 22), m0.repeated_double(i)); + EXPECT_EQ(StrFunc(i, 25), m0.repeated_string(i)); + EXPECT_EQ(Func(i, 26), m0.repeated_foreign_message(i).c()); + EXPECT_EQ(TestAllTypes::BAZ, m0.repeated_nested_enum(i)); + + // Check the content of m2. + EXPECT_EQ(Func(i, 11), m2.repeated_int32(i)); + EXPECT_EQ(Func(i, 12), m2.repeated_double(i)); + EXPECT_EQ(StrFunc(i, 15), m2.repeated_string(i)); + EXPECT_EQ(Func(i, 16), m2.repeated_foreign_message(i).c()); + EXPECT_EQ(TestAllTypes::BAR, m2.repeated_nested_enum(i)); + EXPECT_EQ(Func(i, 21), m2.repeated_int32(i + 10)); + EXPECT_EQ(Func(i, 22), m2.repeated_double(i + 10)); + EXPECT_EQ(StrFunc(i, 25), m2.repeated_string(i + 10)); + EXPECT_EQ(Func(i, 26), m2.repeated_foreign_message(i + 10).c()); + EXPECT_EQ(TestAllTypes::BAZ, m2.repeated_nested_enum(i + 10)); + } +} + +// Test that GetRepeatedFieldRef/MutableRepeatedFieldRef works with +// DynamicMessage. +TEST(RepeatedFieldReflectionTest, RepeatedFieldRefDynamicMessage) { + // DynamicMessage shares the same memory layout as generated message + // and use the same GeneratedMessageReflection code for reflection. + // All code paths should already be covered by the other tests for + // generated messages. Here we just test one field. + + const Descriptor* desc = TestAllTypes::descriptor(); + const FieldDescriptor* fd_repeated_int32 = + desc->FindFieldByName("repeated_int32"); + + DynamicMessageFactory factory; + std::unique_ptr dynamic_message(factory.GetPrototype(desc)->New()); + const Reflection* refl = dynamic_message->GetReflection(); + + MutableRepeatedFieldRef rf_int32 = + refl->GetMutableRepeatedFieldRef( + dynamic_message.get(), fd_repeated_int32); + rf_int32.Add(1234); + EXPECT_EQ(1, refl->FieldSize(*dynamic_message, fd_repeated_int32)); + EXPECT_EQ(1234, refl->GetRepeatedInt32(*dynamic_message, + fd_repeated_int32, 0)); +} + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/repeated_field_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field_unittest.cc similarity index 71% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/repeated_field_unittest.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field_unittest.cc index f4d48f597..053a4d68f 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/repeated_field_unittest.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/repeated_field_unittest.cc @@ -42,19 +42,22 @@ #include +#include #include #include -#include +#include #include #include +#include #include namespace google { -using protobuf_unittest::TestAllTypes; - namespace protobuf { namespace { +using ::protobuf_unittest::TestAllTypes; +using ::testing::ElementsAre; + // Test operations on a small RepeatedField. TEST(RepeatedField, Small) { RepeatedField field; @@ -92,8 +95,9 @@ TEST(RepeatedField, Small) { EXPECT_TRUE(field.empty()); EXPECT_EQ(field.size(), 0); - int expected_usage = 4 * sizeof(int); - EXPECT_EQ(field.SpaceUsedExcludingSelf(), expected_usage); + // Additional bytes are for 'struct Rep' header. + int expected_usage = 4 * sizeof(int) + sizeof(Arena*); + EXPECT_GE(field.SpaceUsedExcludingSelf(), expected_usage); } @@ -205,7 +209,7 @@ TEST(RepeatedField, ReserveMoreThanDouble) { RepeatedField field; field.Reserve(20); - EXPECT_EQ(20, ReservedSpace(&field)); + EXPECT_LE(20, ReservedSpace(&field)); } TEST(RepeatedField, ReserveLessThanDouble) { @@ -213,9 +217,10 @@ TEST(RepeatedField, ReserveLessThanDouble) { // field to grow by double instead. RepeatedField field; field.Reserve(20); - field.Reserve(30); + int capacity = field.Capacity(); + field.Reserve(capacity * 1.5); - EXPECT_EQ(40, ReservedSpace(&field)); + EXPECT_LE(2 * capacity, ReservedSpace(&field)); } TEST(RepeatedField, ReserveLessThanExisting) { @@ -227,7 +232,7 @@ TEST(RepeatedField, ReserveLessThanExisting) { field.Reserve(10); EXPECT_EQ(previous_ptr, field.data()); - EXPECT_EQ(20, ReservedSpace(&field)); + EXPECT_LE(20, ReservedSpace(&field)); } TEST(RepeatedField, Resize) { @@ -264,13 +269,6 @@ TEST(RepeatedField, MergeFrom) { EXPECT_EQ(5, destination.Get(4)); } -#ifdef PROTOBUF_HAS_DEATH_TEST -TEST(RepeatedField, MergeFromSelf) { - RepeatedField me; - me.Add(3); - EXPECT_DEATH(me.MergeFrom(me), ""); -} -#endif // PROTOBUF_HAS_DEATH_TEST TEST(RepeatedField, CopyFrom) { RepeatedField source, destination; @@ -295,6 +293,39 @@ TEST(RepeatedField, CopyFromSelf) { EXPECT_EQ(3, me.Get(0)); } +TEST(RepeatedField, Erase) { + RepeatedField me; + RepeatedField::iterator it = me.erase(me.begin(), me.end()); + EXPECT_TRUE(me.begin() == it); + EXPECT_EQ(0, me.size()); + + me.Add(1); + me.Add(2); + me.Add(3); + it = me.erase(me.begin(), me.end()); + EXPECT_TRUE(me.begin() == it); + EXPECT_EQ(0, me.size()); + + me.Add(4); + me.Add(5); + me.Add(6); + it = me.erase(me.begin() + 2, me.end()); + EXPECT_TRUE(me.begin() + 2 == it); + EXPECT_EQ(2, me.size()); + EXPECT_EQ(4, me.Get(0)); + EXPECT_EQ(5, me.Get(1)); + + me.Add(6); + me.Add(7); + me.Add(8); + it = me.erase(me.begin() + 1, me.begin() + 3); + EXPECT_TRUE(me.begin() + 1 == it); + EXPECT_EQ(3, me.size()); + EXPECT_EQ(4, me.Get(0)); + EXPECT_EQ(7, me.Get(1)); + EXPECT_EQ(8, me.Get(2)); +} + TEST(RepeatedField, CopyConstruct) { RepeatedField source; source.Add(1); @@ -308,7 +339,7 @@ TEST(RepeatedField, CopyConstruct) { } TEST(RepeatedField, IteratorConstruct) { - vector values; + std::vector values; values.push_back(1); values.push_back(2); @@ -352,6 +383,138 @@ TEST(RepeatedField, SelfAssign) { EXPECT_EQ(8, source.Get(1)); } +TEST(RepeatedField, MoveConstruct) { + { + RepeatedField source; + source.Add(1); + source.Add(2); + const int* data = source.data(); + RepeatedField destination = std::move(source); + EXPECT_EQ(data, destination.data()); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_TRUE(source.empty()); + } + { + Arena arena; + RepeatedField* source = + Arena::CreateMessage>(&arena); + source->Add(1); + source->Add(2); + RepeatedField destination = std::move(*source); + EXPECT_EQ(nullptr, destination.GetArena()); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre(1, 2)); + } +} + +TEST(RepeatedField, MoveAssign) { + { + RepeatedField source; + source.Add(1); + source.Add(2); + RepeatedField destination; + destination.Add(3); + const int* source_data = source.data(); + const int* destination_data = destination.data(); + destination = std::move(source); + EXPECT_EQ(source_data, destination.data()); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source.data()); + EXPECT_THAT(source, ElementsAre(3)); + } + { + Arena arena; + RepeatedField* source = + Arena::CreateMessage>(&arena); + source->Add(1); + source->Add(2); + RepeatedField* destination = + Arena::CreateMessage>(&arena); + destination->Add(3); + const int* source_data = source->data(); + const int* destination_data = destination->data(); + *destination = std::move(*source); + EXPECT_EQ(source_data, destination->data()); + EXPECT_THAT(*destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source->data()); + EXPECT_THAT(*source, ElementsAre(3)); + } + { + Arena source_arena; + RepeatedField* source = + Arena::CreateMessage>(&source_arena); + source->Add(1); + source->Add(2); + Arena destination_arena; + RepeatedField* destination = + Arena::CreateMessage>(&destination_arena); + destination->Add(3); + *destination = std::move(*source); + EXPECT_THAT(*destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre(1, 2)); + } + { + Arena arena; + RepeatedField* source = + Arena::CreateMessage>(&arena); + source->Add(1); + source->Add(2); + RepeatedField destination; + destination.Add(3); + destination = std::move(*source); + EXPECT_THAT(destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre(1, 2)); + } + { + RepeatedField source; + source.Add(1); + source.Add(2); + Arena arena; + RepeatedField* destination = + Arena::CreateMessage>(&arena); + destination->Add(3); + *destination = std::move(source); + EXPECT_THAT(*destination, ElementsAre(1, 2)); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(source, ElementsAre(1, 2)); + } + { + RepeatedField field; + // An alias to defeat -Wself-move. + RepeatedField& alias = field; + field.Add(1); + field.Add(2); + const int* data = field.data(); + field = std::move(alias); + EXPECT_EQ(data, field.data()); + EXPECT_THAT(field, ElementsAre(1, 2)); + } + { + Arena arena; + RepeatedField* field = + Arena::CreateMessage>(&arena); + field->Add(1); + field->Add(2); + const int* data = field->data(); + *field = std::move(*field); + EXPECT_EQ(data, field->data()); + EXPECT_THAT(*field, ElementsAre(1, 2)); + } +} + TEST(RepeatedField, MutableDataIsMutable) { RepeatedField field; field.Add(1); @@ -362,6 +525,16 @@ TEST(RepeatedField, MutableDataIsMutable) { EXPECT_EQ(2, field.Get(0)); } +TEST(RepeatedField, SubscriptOperators) { + RepeatedField field; + field.Add(1); + EXPECT_EQ(1, field.Get(0)); + EXPECT_EQ(1, field[0]); + EXPECT_EQ(field.Mutable(0), &field[0]); + const RepeatedField& const_field = field; + EXPECT_EQ(field.data(), &const_field[0]); +} + TEST(RepeatedField, Truncate) { RepeatedField field; @@ -422,6 +595,28 @@ TEST(RepeatedField, ExtractSubrange) { } } +TEST(RepeatedField, ClearThenReserveMore) { + // Test that Reserve properly destroys the old internal array when it's forced + // to allocate a new one, even when cleared-but-not-deleted objects are + // present. Use a 'string' and > 16 bytes length so that the elements are + // non-POD and allocate -- the leak checker will catch any skipped destructor + // calls here. + RepeatedField field; + for (int i = 0; i < 32; i++) { + field.Add(string("abcdefghijklmnopqrstuvwxyz0123456789")); + } + EXPECT_EQ(32, field.size()); + field.Clear(); + EXPECT_EQ(0, field.size()); + EXPECT_LE(32, field.Capacity()); + + field.Reserve(1024); + EXPECT_EQ(0, field.size()); + EXPECT_LE(1024, field.Capacity()); + // Finish test -- |field| should destroy the cleared-but-not-yet-destroyed + // strings. +} + // =================================================================== // RepeatedPtrField tests. These pretty much just mirror the RepeatedField // tests above. @@ -572,15 +767,18 @@ TEST(RepeatedPtrField, ReserveMoreThanDouble) { RepeatedPtrField field; field.Reserve(20); - EXPECT_EQ(20, ReservedSpace(&field)); + EXPECT_LE(20, ReservedSpace(&field)); } TEST(RepeatedPtrField, ReserveLessThanDouble) { RepeatedPtrField field; field.Reserve(20); - field.Reserve(30); - EXPECT_EQ(40, ReservedSpace(&field)); + int capacity = field.Capacity(); + // Grow by 1.5x + field.Reserve(capacity + (capacity >> 2)); + + EXPECT_LE(2 * capacity, ReservedSpace(&field)); } TEST(RepeatedPtrField, ReserveLessThanExisting) { @@ -590,7 +788,7 @@ TEST(RepeatedPtrField, ReserveLessThanExisting) { field.Reserve(10); EXPECT_EQ(previous_ptr, field.data()); - EXPECT_EQ(20, ReservedSpace(&field)); + EXPECT_LE(20, ReservedSpace(&field)); } TEST(RepeatedPtrField, ReserveDoesntLoseAllocated) { @@ -710,13 +908,6 @@ TEST(RepeatedPtrField, MergeFrom) { EXPECT_EQ("5", destination.Get(4)); } -#ifdef PROTOBUF_HAS_DEATH_TEST -TEST(RepeatedPtrField, MergeFromSelf) { - RepeatedPtrField me; - me.Add()->assign("1"); - EXPECT_DEATH(me.MergeFrom(me), ""); -} -#endif // PROTOBUF_HAS_DEATH_TEST TEST(RepeatedPtrField, CopyFrom) { RepeatedPtrField source, destination; @@ -741,6 +932,39 @@ TEST(RepeatedPtrField, CopyFromSelf) { EXPECT_EQ("1", me.Get(0)); } +TEST(RepeatedPtrField, Erase) { + RepeatedPtrField me; + RepeatedPtrField::iterator it = me.erase(me.begin(), me.end()); + EXPECT_TRUE(me.begin() == it); + EXPECT_EQ(0, me.size()); + + *me.Add() = "1"; + *me.Add() = "2"; + *me.Add() = "3"; + it = me.erase(me.begin(), me.end()); + EXPECT_TRUE(me.begin() == it); + EXPECT_EQ(0, me.size()); + + *me.Add() = "4"; + *me.Add() = "5"; + *me.Add() = "6"; + it = me.erase(me.begin() + 2, me.end()); + EXPECT_TRUE(me.begin() + 2 == it); + EXPECT_EQ(2, me.size()); + EXPECT_EQ("4", me.Get(0)); + EXPECT_EQ("5", me.Get(1)); + + *me.Add() = "6"; + *me.Add() = "7"; + *me.Add() = "8"; + it = me.erase(me.begin() + 1, me.begin() + 3); + EXPECT_TRUE(me.begin() + 1 == it); + EXPECT_EQ(3, me.size()); + EXPECT_EQ("4", me.Get(0)); + EXPECT_EQ("7", me.Get(1)); + EXPECT_EQ("8", me.Get(2)); +} + TEST(RepeatedPtrField, CopyConstruct) { RepeatedPtrField source; source.Add()->assign("1"); @@ -754,7 +978,7 @@ TEST(RepeatedPtrField, CopyConstruct) { } TEST(RepeatedPtrField, IteratorConstruct_String) { - vector values; + std::vector values; values.push_back("1"); values.push_back("2"); @@ -771,7 +995,7 @@ TEST(RepeatedPtrField, IteratorConstruct_String) { TEST(RepeatedPtrField, IteratorConstruct_Proto) { typedef TestAllTypes::NestedMessage Nested; - vector values; + std::vector values; values.push_back(Nested()); values.back().set_bb(1); values.push_back(Nested()); @@ -817,6 +1041,138 @@ TEST(RepeatedPtrField, SelfAssign) { EXPECT_EQ("8", source.Get(1)); } +TEST(RepeatedPtrField, MoveConstruct) { + { + RepeatedPtrField source; + *source.Add() = "1"; + *source.Add() = "2"; + const string* const* data = source.data(); + RepeatedPtrField destination = std::move(source); + EXPECT_EQ(data, destination.data()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_TRUE(source.empty()); + } + { + Arena arena; + RepeatedPtrField* source = + Arena::CreateMessage>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField destination = std::move(*source); + EXPECT_EQ(nullptr, destination.GetArena()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } +} + +TEST(RepeatedPtrField, MoveAssign) { + { + RepeatedPtrField source; + *source.Add() = "1"; + *source.Add() = "2"; + RepeatedPtrField destination; + *destination.Add() = "3"; + const string* const* source_data = source.data(); + const string* const* destination_data = destination.data(); + destination = std::move(source); + EXPECT_EQ(source_data, destination.data()); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source.data()); + EXPECT_THAT(source, ElementsAre("3")); + } + { + Arena arena; + RepeatedPtrField* source = + Arena::CreateMessage>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField* destination = + Arena::CreateMessage>(&arena); + *destination->Add() = "3"; + const string* const* source_data = source->data(); + const string* const* destination_data = destination->data(); + *destination = std::move(*source); + EXPECT_EQ(source_data, destination->data()); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_EQ(destination_data, source->data()); + EXPECT_THAT(*source, ElementsAre("3")); + } + { + Arena source_arena; + RepeatedPtrField* source = + Arena::CreateMessage>(&source_arena); + *source->Add() = "1"; + *source->Add() = "2"; + Arena destination_arena; + RepeatedPtrField* destination = + Arena::CreateMessage>(&destination_arena); + *destination->Add() = "3"; + *destination = std::move(*source); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } + { + Arena arena; + RepeatedPtrField* source = + Arena::CreateMessage>(&arena); + *source->Add() = "1"; + *source->Add() = "2"; + RepeatedPtrField destination; + *destination.Add() = "3"; + destination = std::move(*source); + EXPECT_THAT(destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(*source, ElementsAre("1", "2")); + } + { + RepeatedPtrField source; + *source.Add() = "1"; + *source.Add() = "2"; + Arena arena; + RepeatedPtrField* destination = + Arena::CreateMessage>(&arena); + *destination->Add() = "3"; + *destination = std::move(source); + EXPECT_THAT(*destination, ElementsAre("1", "2")); + // This property isn't guaranteed but it's useful to have a test that would + // catch changes in this area. + EXPECT_THAT(source, ElementsAre("1", "2")); + } + { + RepeatedPtrField field; + // An alias to defeat -Wself-move. + RepeatedPtrField& alias = field; + *field.Add() = "1"; + *field.Add() = "2"; + const string* const* data = field.data(); + field = std::move(alias); + EXPECT_EQ(data, field.data()); + EXPECT_THAT(field, ElementsAre("1", "2")); + } + { + Arena arena; + RepeatedPtrField* field = + Arena::CreateMessage>(&arena); + *field->Add() = "1"; + *field->Add() = "2"; + const string* const* data = field->data(); + *field = std::move(*field); + EXPECT_EQ(data, field->data()); + EXPECT_THAT(*field, ElementsAre("1", "2")); + } +} + TEST(RepeatedPtrField, MutableDataIsMutable) { RepeatedPtrField field; *field.Add() = "1"; @@ -828,6 +1184,16 @@ TEST(RepeatedPtrField, MutableDataIsMutable) { EXPECT_EQ("2", field.Get(0)); } +TEST(RepeatedPtrField, SubscriptOperators) { + RepeatedPtrField field; + *field.Add() = "1"; + EXPECT_EQ("1", field.Get(0)); + EXPECT_EQ("1", field[0]); + EXPECT_EQ(field.Mutable(0), &field[0]); + const RepeatedPtrField& const_field = field; + EXPECT_EQ(*field.data(), &const_field[0]); +} + TEST(RepeatedPtrField, ExtractSubrange) { // Exhaustively test every subrange in arrays of all sizes from 0 through 9 // with 0 through 3 cleared elements at the end. @@ -835,7 +1201,7 @@ TEST(RepeatedPtrField, ExtractSubrange) { for (int num = 0; num <= sz; ++num) { for (int start = 0; start < sz - num; ++start) { for (int extra = 0; extra < 4; ++extra) { - vector subject; + std::vector subject; // Create an array with "sz" elements and "extra" cleared elements. RepeatedPtrField field; @@ -1064,7 +1430,7 @@ TEST_F(RepeatedPtrFieldIteratorTest, STLAlgorithms_lower_bound) { string v = "f"; RepeatedPtrField::const_iterator it = - lower_bound(proto_array_.begin(), proto_array_.end(), v); + std::lower_bound(proto_array_.begin(), proto_array_.end(), v); EXPECT_EQ(*it, "n"); EXPECT_TRUE(it == proto_array_.begin() + 3); @@ -1225,8 +1591,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { { string v = "f"; RepeatedPtrField::pointer_iterator it = - lower_bound(proto_array_.pointer_begin(), proto_array_.pointer_end(), - &v, StringLessThan()); + std::lower_bound(proto_array_.pointer_begin(), + proto_array_.pointer_end(), &v, StringLessThan()); GOOGLE_CHECK(*it != NULL); @@ -1235,10 +1601,9 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, PtrSTLAlgorithms_lower_bound) { } { string v = "f"; - RepeatedPtrField::const_pointer_iterator it = - lower_bound(const_proto_array_->pointer_begin(), - const_proto_array_->pointer_end(), - &v, StringLessThan()); + RepeatedPtrField::const_pointer_iterator it = std::lower_bound( + const_proto_array_->pointer_begin(), const_proto_array_->pointer_end(), + &v, StringLessThan()); GOOGLE_CHECK(*it != NULL); @@ -1276,9 +1641,8 @@ TEST_F(RepeatedPtrFieldPtrsIteratorTest, Sort) { EXPECT_EQ("foo", proto_array_.Get(0)); EXPECT_EQ("n", proto_array_.Get(5)); EXPECT_EQ("x", proto_array_.Get(9)); - sort(proto_array_.pointer_begin(), - proto_array_.pointer_end(), - StringLessThan()); + std::sort(proto_array_.pointer_begin(), proto_array_.pointer_end(), + StringLessThan()); EXPECT_EQ("a", proto_array_.Get(0)); EXPECT_EQ("baz", proto_array_.Get(2)); EXPECT_EQ("y", proto_array_.Get(9)); @@ -1342,7 +1706,6 @@ class RepeatedFieldInsertionIteratorsTest : public testing::Test { std::copy(nested_ptrs.begin(), nested_ptrs.end(), RepeatedFieldBackInserter( protobuffer.mutable_repeated_nested_message())); - } virtual void TearDown() { @@ -1400,7 +1763,7 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, Nesteds) { TEST_F(RepeatedFieldInsertionIteratorsTest, AllocatedRepeatedPtrFieldWithStringIntData) { - vector data; + std::vector data; TestAllTypes goldenproto; for (int i = 0; i < 10; ++i) { Nested* new_data = new Nested; @@ -1411,15 +1774,15 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, new_data->set_bb(i); } TestAllTypes testproto; - copy(data.begin(), data.end(), - AllocatedRepeatedPtrFieldBackInserter( - testproto.mutable_repeated_nested_message())); + std::copy(data.begin(), data.end(), + AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_nested_message())); EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); } TEST_F(RepeatedFieldInsertionIteratorsTest, AllocatedRepeatedPtrFieldWithString) { - vector data; + std::vector data; TestAllTypes goldenproto; for (int i = 0; i < 10; ++i) { string* new_data = new string; @@ -1430,12 +1793,79 @@ TEST_F(RepeatedFieldInsertionIteratorsTest, *new_data = "name-" + SimpleItoa(i); } TestAllTypes testproto; - copy(data.begin(), data.end(), - AllocatedRepeatedPtrFieldBackInserter( - testproto.mutable_repeated_string())); + std::copy(data.begin(), data.end(), AllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_string())); EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); } +TEST_F(RepeatedFieldInsertionIteratorsTest, + UnsafeArenaAllocatedRepeatedPtrFieldWithStringIntData) { + std::vector data; + TestAllTypes goldenproto; + for (int i = 0; i < 10; ++i) { + Nested* new_data = new Nested; + new_data->set_bb(i); + data.push_back(new_data); + + new_data = goldenproto.add_repeated_nested_message(); + new_data->set_bb(i); + } + TestAllTypes testproto; + std::copy(data.begin(), data.end(), + UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_nested_message())); + EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, + UnsafeArenaAllocatedRepeatedPtrFieldWithString) { + std::vector data; + TestAllTypes goldenproto; + for (int i = 0; i < 10; ++i) { + string* new_data = new string; + *new_data = "name-" + SimpleItoa(i); + data.push_back(new_data); + + new_data = goldenproto.add_repeated_string(); + *new_data = "name-" + SimpleItoa(i); + } + TestAllTypes testproto; + std::copy(data.begin(), data.end(), + UnsafeArenaAllocatedRepeatedPtrFieldBackInserter( + testproto.mutable_repeated_string())); + EXPECT_EQ(testproto.DebugString(), goldenproto.DebugString()); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, MoveStrings) { + std::vector src = {"a", "b", "c", "d"}; + std::vector copy = src; // copy since move leaves in undefined state + TestAllTypes testproto; + std::move(copy.begin(), copy.end(), + RepeatedFieldBackInserter(testproto.mutable_repeated_string())); + + ASSERT_THAT(testproto.repeated_string(), testing::ElementsAreArray(src)); +} + +TEST_F(RepeatedFieldInsertionIteratorsTest, MoveProtos) { + auto make_nested = [](int32 x) { + Nested ret; + ret.set_bb(x); + return ret; + }; + std::vector src = {make_nested(3), make_nested(5), make_nested(7)}; + std::vector copy = src; // copy since move leaves in undefined state + TestAllTypes testproto; + std::move( + copy.begin(), copy.end(), + RepeatedFieldBackInserter(testproto.mutable_repeated_nested_message())); + + ASSERT_EQ(src.size(), testproto.repeated_nested_message_size()); + for (int i = 0; i < src.size(); ++i) { + EXPECT_EQ(src[i].DebugString(), + testproto.repeated_nested_message(i).DebugString()); + } +} + } // namespace } // namespace protobuf diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/service.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/service.cc similarity index 100% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/service.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/service.cc diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/service.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/service.h similarity index 99% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/service.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/service.h index cc0b45d41..ad6f96854 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/service.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/service.h @@ -74,12 +74,12 @@ // // To call a remote MyServiceImpl, first you need an RpcChannel connected to it. // How to construct a channel depends, again, on your RPC implementation. -// Here we use a hypothentical "MyRpcChannel" as an example: +// Here we use a hypothetical "MyRpcChannel" as an example: // MyRpcChannel channel("rpc:hostname:1234/myservice"); // MyRpcController controller; // MyServiceImpl::Stub stub(&channel); // FooRequest request; -// FooRespnose response; +// FooResponse response; // // // ... fill in request ... // @@ -102,6 +102,7 @@ #include #include +#include namespace google { namespace protobuf { diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/source_context.pb.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/source_context.pb.cc new file mode 100644 index 000000000..739172f84 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/source_context.pb.cc @@ -0,0 +1,370 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +// This is a temporary google only hack +#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS +#include "third_party/protobuf/version.h" +#endif +// @@protoc_insertion_point(includes) + +namespace google { +namespace protobuf { +class SourceContextDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _SourceContext_default_instance_; +} // namespace protobuf +} // namespace google +namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto { +static void InitDefaultsSourceContext() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::google::protobuf::_SourceContext_default_instance_; + new (ptr) ::google::protobuf::SourceContext(); + ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); + } + ::google::protobuf::SourceContext::InitAsDefaultInstance(); +} + +LIBPROTOBUF_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_SourceContext = + {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsSourceContext}, {}}; + +void InitDefaults() { + ::google::protobuf::internal::InitSCC(&scc_info_SourceContext.base); +} + +::google::protobuf::Metadata file_level_metadata[1]; + +const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::SourceContext, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::SourceContext, file_name_), +}; +static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(::google::protobuf::SourceContext)}, +}; + +static ::google::protobuf::Message const * const file_default_instances[] = { + reinterpret_cast(&::google::protobuf::_SourceContext_default_instance_), +}; + +void protobuf_AssignDescriptors() { + AddDescriptors(); + AssignDescriptors( + "google/protobuf/source_context.proto", schemas, file_default_instances, TableStruct::offsets, + file_level_metadata, NULL, NULL); +} + +void protobuf_AssignDescriptorsOnce() { + static ::google::protobuf::internal::once_flag once; + ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors); +} + +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD; +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); +} + +void AddDescriptorsImpl() { + InitDefaults(); + static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + "\n$google/protobuf/source_context.proto\022\017" + "google.protobuf\"\"\n\rSourceContext\022\021\n\tfile" + "_name\030\001 \001(\tB\225\001\n\023com.google.protobufB\022Sou" + "rceContextProtoP\001ZAgoogle.golang.org/gen" + "proto/protobuf/source_context;source_con" + "text\242\002\003GPB\252\002\036Google.Protobuf.WellKnownTy" + "pesb\006proto3" + }; + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + descriptor, 251); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "google/protobuf/source_context.proto", &protobuf_RegisterTypes); +} + +void AddDescriptors() { + static ::google::protobuf::internal::once_flag once; + ::google::protobuf::internal::call_once(once, AddDescriptorsImpl); +} +// Force AddDescriptors() to be called at dynamic initialization time. +struct StaticDescriptorInitializer { + StaticDescriptorInitializer() { + AddDescriptors(); + } +} static_descriptor_initializer; +} // namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto +namespace google { +namespace protobuf { + +// =================================================================== + +void SourceContext::InitAsDefaultInstance() { +} +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +const int SourceContext::kFileNameFieldNumber; +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +SourceContext::SourceContext() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + ::google::protobuf::internal::InitSCC( + &protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::scc_info_SourceContext.base); + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.SourceContext) +} +SourceContext::SourceContext(const SourceContext& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + file_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + if (from.file_name().size() > 0) { + file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_); + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.SourceContext) +} + +void SourceContext::SharedCtor() { + file_name_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + +SourceContext::~SourceContext() { + // @@protoc_insertion_point(destructor:google.protobuf.SourceContext) + SharedDtor(); +} + +void SourceContext::SharedDtor() { + file_name_.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} + +void SourceContext::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const ::google::protobuf::Descriptor* SourceContext::descriptor() { + ::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +} + +const SourceContext& SourceContext::default_instance() { + ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::scc_info_SourceContext.base); + return *internal_default_instance(); +} + + +void SourceContext::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext) + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + _internal_metadata_.Clear(); +} + +bool SourceContext::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.SourceContext) + for (;;) { + ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // string file_name = 1; + case 1: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_file_name())); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->file_name().data(), static_cast(this->file_name().length()), + ::google::protobuf::internal::WireFormatLite::PARSE, + "google.protobuf.SourceContext.file_name")); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.SourceContext) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.SourceContext) + return false; +#undef DO_ +} + +void SourceContext::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.SourceContext) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string file_name = 1; + if (this->file_name().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->file_name().data(), static_cast(this->file_name().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "google.protobuf.SourceContext.file_name"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 1, this->file_name(), output); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.SourceContext) +} + +::google::protobuf::uint8* SourceContext::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { + (void)deterministic; // Unused + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // string file_name = 1; + if (this->file_name().size() > 0) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->file_name().data(), static_cast(this->file_name().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "google.protobuf.SourceContext.file_name"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 1, this->file_name(), target); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.SourceContext) + return target; +} + +size_t SourceContext::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext) + size_t total_size = 0; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); + } + // string file_name = 1; + if (this->file_name().size() > 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->file_name()); + } + + int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void SourceContext::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.SourceContext) + GOOGLE_DCHECK_NE(&from, this); + const SourceContext* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.SourceContext) + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.SourceContext) + MergeFrom(*source); + } +} + +void SourceContext::MergeFrom(const SourceContext& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.file_name().size() > 0) { + + file_name_.AssignWithDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from.file_name_); + } +} + +void SourceContext::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.SourceContext) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void SourceContext::CopyFrom(const SourceContext& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.SourceContext) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SourceContext::IsInitialized() const { + return true; +} + +void SourceContext::Swap(SourceContext* other) { + if (other == this) return; + InternalSwap(other); +} +void SourceContext::InternalSwap(SourceContext* other) { + using std::swap; + file_name_.Swap(&other->file_name_, &::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + _internal_metadata_.Swap(&other->_internal_metadata_); +} + +::google::protobuf::Metadata SourceContext::GetMetadata() const { + protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::file_level_metadata[kIndexInFileMessages]; +} + + +// @@protoc_insertion_point(namespace_scope) +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::SourceContext* Arena::CreateMaybeMessage< ::google::protobuf::SourceContext >(Arena* arena) { + return Arena::CreateInternal< ::google::protobuf::SourceContext >(arena); +} +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/source_context.pb.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/source_context.pb.h new file mode 100644 index 000000000..dcc856e28 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/source_context.pb.h @@ -0,0 +1,249 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/source_context.proto + +#ifndef PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto +#define PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 3006001 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) +#define PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto LIBPROTOBUF_EXPORT + +namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto { +// Internal implementation detail -- do not use these members. +struct LIBPROTOBUF_EXPORT TableStruct { + static const ::google::protobuf::internal::ParseTableField entries[]; + static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; + static const ::google::protobuf::internal::ParseTable schema[1]; + static const ::google::protobuf::internal::FieldMetadata field_metadata[]; + static const ::google::protobuf::internal::SerializationTable serialization_table[]; + static const ::google::protobuf::uint32 offsets[]; +}; +void LIBPROTOBUF_EXPORT AddDescriptors(); +} // namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto +namespace google { +namespace protobuf { +class SourceContext; +class SourceContextDefaultTypeInternal; +LIBPROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_; +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { +template<> LIBPROTOBUF_EXPORT ::google::protobuf::SourceContext* Arena::CreateMaybeMessage<::google::protobuf::SourceContext>(Arena*); +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { + +// =================================================================== + +class LIBPROTOBUF_EXPORT SourceContext : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceContext) */ { + public: + SourceContext(); + virtual ~SourceContext(); + + SourceContext(const SourceContext& from); + + inline SourceContext& operator=(const SourceContext& from) { + CopyFrom(from); + return *this; + } + #if LANG_CXX11 + SourceContext(SourceContext&& from) noexcept + : SourceContext() { + *this = ::std::move(from); + } + + inline SourceContext& operator=(SourceContext&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + #endif + static const ::google::protobuf::Descriptor* descriptor(); + static const SourceContext& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const SourceContext* internal_default_instance() { + return reinterpret_cast( + &_SourceContext_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + void Swap(SourceContext* other); + friend void swap(SourceContext& a, SourceContext& b) { + a.Swap(&b); + } + + // implements Message ---------------------------------------------- + + inline SourceContext* New() const final { + return CreateMaybeMessage(NULL); + } + + SourceContext* New(::google::protobuf::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::google::protobuf::Message& from) final; + void MergeFrom(const ::google::protobuf::Message& from) final; + void CopyFrom(const SourceContext& from); + void MergeFrom(const SourceContext& from); + void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) final; + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const final; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SourceContext* other); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return NULL; + } + inline void* MaybeArenaPtr() const { + return NULL; + } + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // string file_name = 1; + void clear_file_name(); + static const int kFileNameFieldNumber = 1; + const ::std::string& file_name() const; + void set_file_name(const ::std::string& value); + #if LANG_CXX11 + void set_file_name(::std::string&& value); + #endif + void set_file_name(const char* value); + void set_file_name(const char* value, size_t size); + ::std::string* mutable_file_name(); + ::std::string* release_file_name(); + void set_allocated_file_name(::std::string* file_name); + + // @@protoc_insertion_point(class_scope:google.protobuf.SourceContext) + private: + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + ::google::protobuf::internal::ArenaStringPtr file_name_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + friend struct ::protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto::TableStruct; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// SourceContext + +// string file_name = 1; +inline void SourceContext::clear_file_name() { + file_name_.ClearToEmptyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline const ::std::string& SourceContext::file_name() const { + // @@protoc_insertion_point(field_get:google.protobuf.SourceContext.file_name) + return file_name_.GetNoArena(); +} +inline void SourceContext::set_file_name(const ::std::string& value) { + + file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value); + // @@protoc_insertion_point(field_set:google.protobuf.SourceContext.file_name) +} +#if LANG_CXX11 +inline void SourceContext::set_file_name(::std::string&& value) { + + file_name_.SetNoArena( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value)); + // @@protoc_insertion_point(field_set_rvalue:google.protobuf.SourceContext.file_name) +} +#endif +inline void SourceContext::set_file_name(const char* value) { + GOOGLE_DCHECK(value != NULL); + + file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string(value)); + // @@protoc_insertion_point(field_set_char:google.protobuf.SourceContext.file_name) +} +inline void SourceContext::set_file_name(const char* value, size_t size) { + + file_name_.SetNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(reinterpret_cast(value), size)); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceContext.file_name) +} +inline ::std::string* SourceContext::mutable_file_name() { + + // @@protoc_insertion_point(field_mutable:google.protobuf.SourceContext.file_name) + return file_name_.MutableNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline ::std::string* SourceContext::release_file_name() { + // @@protoc_insertion_point(field_release:google.protobuf.SourceContext.file_name) + + return file_name_.ReleaseNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); +} +inline void SourceContext::set_allocated_file_name(::std::string* file_name) { + if (file_name != NULL) { + + } else { + + } + file_name_.SetAllocatedNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), file_name); + // @@protoc_insertion_point(field_set_allocated:google.protobuf.SourceContext.file_name) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/source_context.proto b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/source_context.proto new file mode 100644 index 000000000..f3b2c9668 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/source_context.proto @@ -0,0 +1,48 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "SourceContextProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; +option go_package = "google.golang.org/genproto/protobuf/source_context;source_context"; + +// `SourceContext` represents information about the source of a +// protobuf element, like the file in which it is defined. +message SourceContext { + // The path-qualified name of the .proto file that contained the associated + // protobuf element. For example: `"google/protobuf/source_context.proto"`. + string file_name = 1; +} diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/struct.pb.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/struct.pb.cc new file mode 100644 index 000000000..8f2d48481 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/struct.pb.cc @@ -0,0 +1,1460 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +// This is a temporary google only hack +#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS +#include "third_party/protobuf/version.h" +#endif +// @@protoc_insertion_point(includes) + +namespace protobuf_google_2fprotobuf_2fstruct_2eproto { +extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fstruct_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_ListValue; +} // namespace protobuf_google_2fprotobuf_2fstruct_2eproto +namespace google { +namespace protobuf { +class Struct_FieldsEntry_DoNotUseDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _Struct_FieldsEntry_DoNotUse_default_instance_; +class StructDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _Struct_default_instance_; +class ValueDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; + int null_value_; + double number_value_; + ::google::protobuf::internal::ArenaStringPtr string_value_; + bool bool_value_; + const ::google::protobuf::Struct* struct_value_; + const ::google::protobuf::ListValue* list_value_; +} _Value_default_instance_; +class ListValueDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _ListValue_default_instance_; +} // namespace protobuf +} // namespace google +namespace protobuf_google_2fprotobuf_2fstruct_2eproto { +static void InitDefaultsListValue() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::google::protobuf::_Struct_FieldsEntry_DoNotUse_default_instance_; + new (ptr) ::google::protobuf::Struct_FieldsEntry_DoNotUse(); + } + { + void* ptr = &::google::protobuf::_Struct_default_instance_; + new (ptr) ::google::protobuf::Struct(); + ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); + } + { + void* ptr = &::google::protobuf::_Value_default_instance_; + new (ptr) ::google::protobuf::Value(); + ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); + } + { + void* ptr = &::google::protobuf::_ListValue_default_instance_; + new (ptr) ::google::protobuf::ListValue(); + ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); + } + ::google::protobuf::Struct_FieldsEntry_DoNotUse::InitAsDefaultInstance(); + ::google::protobuf::Struct::InitAsDefaultInstance(); + ::google::protobuf::Value::InitAsDefaultInstance(); + ::google::protobuf::ListValue::InitAsDefaultInstance(); +} + +LIBPROTOBUF_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_ListValue = + {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsListValue}, {}}; + +void InitDefaults() { + ::google::protobuf::internal::InitSCC(&scc_info_ListValue.base); +} + +::google::protobuf::Metadata file_level_metadata[4]; +const ::google::protobuf::EnumDescriptor* file_level_enum_descriptors[1]; + +const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, _has_bits_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, key_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Struct_FieldsEntry_DoNotUse, value_), + 0, + 1, + ~0u, // no _has_bits_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Struct, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Struct, fields_), + ~0u, // no _has_bits_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Value, _internal_metadata_), + ~0u, // no _extensions_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Value, _oneof_case_[0]), + ~0u, // no _weak_field_map_ + offsetof(::google::protobuf::ValueDefaultTypeInternal, null_value_), + offsetof(::google::protobuf::ValueDefaultTypeInternal, number_value_), + offsetof(::google::protobuf::ValueDefaultTypeInternal, string_value_), + offsetof(::google::protobuf::ValueDefaultTypeInternal, bool_value_), + offsetof(::google::protobuf::ValueDefaultTypeInternal, struct_value_), + offsetof(::google::protobuf::ValueDefaultTypeInternal, list_value_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Value, kind_), + ~0u, // no _has_bits_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::ListValue, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::ListValue, values_), +}; +static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + { 0, 7, sizeof(::google::protobuf::Struct_FieldsEntry_DoNotUse)}, + { 9, -1, sizeof(::google::protobuf::Struct)}, + { 15, -1, sizeof(::google::protobuf::Value)}, + { 27, -1, sizeof(::google::protobuf::ListValue)}, +}; + +static ::google::protobuf::Message const * const file_default_instances[] = { + reinterpret_cast(&::google::protobuf::_Struct_FieldsEntry_DoNotUse_default_instance_), + reinterpret_cast(&::google::protobuf::_Struct_default_instance_), + reinterpret_cast(&::google::protobuf::_Value_default_instance_), + reinterpret_cast(&::google::protobuf::_ListValue_default_instance_), +}; + +void protobuf_AssignDescriptors() { + AddDescriptors(); + AssignDescriptors( + "google/protobuf/struct.proto", schemas, file_default_instances, TableStruct::offsets, + file_level_metadata, file_level_enum_descriptors, NULL); +} + +void protobuf_AssignDescriptorsOnce() { + static ::google::protobuf::internal::once_flag once; + ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors); +} + +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD; +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 4); +} + +void AddDescriptorsImpl() { + InitDefaults(); + static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + "\n\034google/protobuf/struct.proto\022\017google.p" + "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo" + "gle.protobuf.Struct.FieldsEntry\032E\n\013Field" + "sEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026.goo" + "gle.protobuf.Value:\0028\001\"\352\001\n\005Value\0220\n\nnull" + "_value\030\001 \001(\0162\032.google.protobuf.NullValue" + "H\000\022\026\n\014number_value\030\002 \001(\001H\000\022\026\n\014string_val" + "ue\030\003 \001(\tH\000\022\024\n\nbool_value\030\004 \001(\010H\000\022/\n\014stru" + "ct_value\030\005 \001(\0132\027.google.protobuf.StructH" + "\000\0220\n\nlist_value\030\006 \001(\0132\032.google.protobuf." + "ListValueH\000B\006\n\004kind\"3\n\tListValue\022&\n\006valu" + "es\030\001 \003(\0132\026.google.protobuf.Value*\033\n\tNull" + "Value\022\016\n\nNULL_VALUE\020\000B\201\001\n\023com.google.pro" + "tobufB\013StructProtoP\001Z1github.com/golang/" + "protobuf/ptypes/struct;structpb\370\001\001\242\002\003GPB" + "\252\002\036Google.Protobuf.WellKnownTypesb\006proto" + "3" + }; + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + descriptor, 641); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "google/protobuf/struct.proto", &protobuf_RegisterTypes); +} + +void AddDescriptors() { + static ::google::protobuf::internal::once_flag once; + ::google::protobuf::internal::call_once(once, AddDescriptorsImpl); +} +// Force AddDescriptors() to be called at dynamic initialization time. +struct StaticDescriptorInitializer { + StaticDescriptorInitializer() { + AddDescriptors(); + } +} static_descriptor_initializer; +} // namespace protobuf_google_2fprotobuf_2fstruct_2eproto +namespace google { +namespace protobuf { +const ::google::protobuf::EnumDescriptor* NullValue_descriptor() { + protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); + return protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_enum_descriptors[0]; +} +bool NullValue_IsValid(int value) { + switch (value) { + case 0: + return true; + default: + return false; + } +} + + +// =================================================================== + +Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse() {} +Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(::google::protobuf::Arena* arena) : SuperType(arena) {} +void Struct_FieldsEntry_DoNotUse::MergeFrom(const Struct_FieldsEntry_DoNotUse& other) { + MergeFromInternal(other); +} +::google::protobuf::Metadata Struct_FieldsEntry_DoNotUse::GetMetadata() const { + ::protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[0]; +} +void Struct_FieldsEntry_DoNotUse::MergeFrom( + const ::google::protobuf::Message& other) { + ::google::protobuf::Message::MergeFrom(other); +} + + +// =================================================================== + +void Struct::InitAsDefaultInstance() { +} +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +const int Struct::kFieldsFieldNumber; +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +Struct::Struct() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + ::google::protobuf::internal::InitSCC( + &protobuf_google_2fprotobuf_2fstruct_2eproto::scc_info_ListValue.base); + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.Struct) +} +Struct::Struct(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(), + _internal_metadata_(arena), + fields_(arena) { + ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fstruct_2eproto::scc_info_ListValue.base); + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Struct) +} +Struct::Struct(const Struct& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + fields_.MergeFrom(from.fields_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.Struct) +} + +void Struct::SharedCtor() { +} + +Struct::~Struct() { + // @@protoc_insertion_point(destructor:google.protobuf.Struct) + SharedDtor(); +} + +void Struct::SharedDtor() { + GOOGLE_DCHECK(GetArenaNoVirtual() == NULL); +} + +void Struct::ArenaDtor(void* object) { + Struct* _this = reinterpret_cast< Struct* >(object); + (void)_this; +} +void Struct::RegisterArenaDtor(::google::protobuf::Arena* arena) { +} +void Struct::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const ::google::protobuf::Descriptor* Struct::descriptor() { + ::protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +} + +const Struct& Struct::default_instance() { + ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fstruct_2eproto::scc_info_ListValue.base); + return *internal_default_instance(); +} + + +void Struct::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Struct) + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + fields_.Clear(); + _internal_metadata_.Clear(); +} + +bool Struct::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.Struct) + for (;;) { + ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // map fields = 1; + case 1: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { + Struct_FieldsEntry_DoNotUse::Parser< ::google::protobuf::internal::MapField< + Struct_FieldsEntry_DoNotUse, + ::std::string, ::google::protobuf::Value, + ::google::protobuf::internal::WireFormatLite::TYPE_STRING, + ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE, + 0 >, + ::google::protobuf::Map< ::std::string, ::google::protobuf::Value > > parser(&fields_); + DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual( + input, &parser)); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + parser.key().data(), static_cast(parser.key().length()), + ::google::protobuf::internal::WireFormatLite::PARSE, + "google.protobuf.Struct.FieldsEntry.key")); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.Struct) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.Struct) + return false; +#undef DO_ +} + +void Struct::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.Struct) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // map fields = 1; + if (!this->fields().empty()) { + typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_pointer + ConstPtr; + typedef ConstPtr SortItem; + typedef ::google::protobuf::internal::CompareByDerefFirst Less; + struct Utf8Check { + static void Check(ConstPtr p) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + p->first.data(), static_cast(p->first.length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Struct.FieldsEntry.key"); + } + }; + + if (output->IsSerializationDeterministic() && + this->fields().size() > 1) { + ::std::unique_ptr items( + new SortItem[this->fields().size()]); + typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::size_type size_type; + size_type n = 0; + for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator + it = this->fields().begin(); + it != this->fields().end(); ++it, ++n) { + items[static_cast(n)] = SortItem(&*it); + } + ::std::sort(&items[0], &items[static_cast(n)], Less()); + ::std::unique_ptr entry; + for (size_type i = 0; i < n; i++) { + entry.reset(fields_.NewEntryWrapper( + items[static_cast(i)]->first, items[static_cast(i)]->second)); + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, *entry, output); + if (entry->GetArena() != NULL) { + entry.release(); + } + Utf8Check::Check(items[static_cast(i)]); + } + } else { + ::std::unique_ptr entry; + for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator + it = this->fields().begin(); + it != this->fields().end(); ++it) { + entry.reset(fields_.NewEntryWrapper( + it->first, it->second)); + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, *entry, output); + if (entry->GetArena() != NULL) { + entry.release(); + } + Utf8Check::Check(&*it); + } + } + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.Struct) +} + +::google::protobuf::uint8* Struct::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { + (void)deterministic; // Unused + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // map fields = 1; + if (!this->fields().empty()) { + typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_pointer + ConstPtr; + typedef ConstPtr SortItem; + typedef ::google::protobuf::internal::CompareByDerefFirst Less; + struct Utf8Check { + static void Check(ConstPtr p) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + p->first.data(), static_cast(p->first.length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Struct.FieldsEntry.key"); + } + }; + + if (deterministic && + this->fields().size() > 1) { + ::std::unique_ptr items( + new SortItem[this->fields().size()]); + typedef ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::size_type size_type; + size_type n = 0; + for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator + it = this->fields().begin(); + it != this->fields().end(); ++it, ++n) { + items[static_cast(n)] = SortItem(&*it); + } + ::std::sort(&items[0], &items[static_cast(n)], Less()); + ::std::unique_ptr entry; + for (size_type i = 0; i < n; i++) { + entry.reset(fields_.NewEntryWrapper( + items[static_cast(i)]->first, items[static_cast(i)]->second)); + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessageNoVirtualToArray( + 1, *entry, deterministic, target); +; + if (entry->GetArena() != NULL) { + entry.release(); + } + Utf8Check::Check(items[static_cast(i)]); + } + } else { + ::std::unique_ptr entry; + for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator + it = this->fields().begin(); + it != this->fields().end(); ++it) { + entry.reset(fields_.NewEntryWrapper( + it->first, it->second)); + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessageNoVirtualToArray( + 1, *entry, deterministic, target); +; + if (entry->GetArena() != NULL) { + entry.release(); + } + Utf8Check::Check(&*it); + } + } + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Struct) + return target; +} + +size_t Struct::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct) + size_t total_size = 0; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); + } + // map fields = 1; + total_size += 1 * + ::google::protobuf::internal::FromIntSize(this->fields_size()); + { + ::std::unique_ptr entry; + for (::google::protobuf::Map< ::std::string, ::google::protobuf::Value >::const_iterator + it = this->fields().begin(); + it != this->fields().end(); ++it) { + if (entry.get() != NULL && entry->GetArena() != NULL) { + entry.release(); + } + entry.reset(fields_.NewEntryWrapper(it->first, it->second)); + total_size += ::google::protobuf::internal::WireFormatLite:: + MessageSizeNoVirtual(*entry); + } + if (entry.get() != NULL && entry->GetArena() != NULL) { + entry.release(); + } + } + + int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void Struct::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Struct) + GOOGLE_DCHECK_NE(&from, this); + const Struct* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Struct) + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Struct) + MergeFrom(*source); + } +} + +void Struct::MergeFrom(const Struct& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + fields_.MergeFrom(from.fields_); +} + +void Struct::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Struct) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Struct::CopyFrom(const Struct& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Struct) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Struct::IsInitialized() const { + return true; +} + +void Struct::Swap(Struct* other) { + if (other == this) return; + if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { + InternalSwap(other); + } else { + Struct* temp = New(GetArenaNoVirtual()); + temp->MergeFrom(*other); + other->CopyFrom(*this); + InternalSwap(temp); + if (GetArenaNoVirtual() == NULL) { + delete temp; + } + } +} +void Struct::UnsafeArenaSwap(Struct* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + InternalSwap(other); +} +void Struct::InternalSwap(Struct* other) { + using std::swap; + fields_.Swap(&other->fields_); + _internal_metadata_.Swap(&other->_internal_metadata_); +} + +::google::protobuf::Metadata Struct::GetMetadata() const { + protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages]; +} + + +// =================================================================== + +void Value::InitAsDefaultInstance() { + ::google::protobuf::_Value_default_instance_.null_value_ = 0; + ::google::protobuf::_Value_default_instance_.number_value_ = 0; + ::google::protobuf::_Value_default_instance_.string_value_.UnsafeSetDefault( + &::google::protobuf::internal::GetEmptyStringAlreadyInited()); + ::google::protobuf::_Value_default_instance_.bool_value_ = false; + ::google::protobuf::_Value_default_instance_.struct_value_ = const_cast< ::google::protobuf::Struct*>( + ::google::protobuf::Struct::internal_default_instance()); + ::google::protobuf::_Value_default_instance_.list_value_ = const_cast< ::google::protobuf::ListValue*>( + ::google::protobuf::ListValue::internal_default_instance()); +} +void Value::set_allocated_struct_value(::google::protobuf::Struct* struct_value) { + ::google::protobuf::Arena* message_arena = GetArenaNoVirtual(); + clear_kind(); + if (struct_value) { + ::google::protobuf::Arena* submessage_arena = + ::google::protobuf::Arena::GetArena(struct_value); + if (message_arena != submessage_arena) { + struct_value = ::google::protobuf::internal::GetOwnedMessage( + message_arena, struct_value, submessage_arena); + } + set_has_struct_value(); + kind_.struct_value_ = struct_value; + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.struct_value) +} +void Value::set_allocated_list_value(::google::protobuf::ListValue* list_value) { + ::google::protobuf::Arena* message_arena = GetArenaNoVirtual(); + clear_kind(); + if (list_value) { + ::google::protobuf::Arena* submessage_arena = + ::google::protobuf::Arena::GetArena(list_value); + if (message_arena != submessage_arena) { + list_value = ::google::protobuf::internal::GetOwnedMessage( + message_arena, list_value, submessage_arena); + } + set_has_list_value(); + kind_.list_value_ = list_value; + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.list_value) +} +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +const int Value::kNullValueFieldNumber; +const int Value::kNumberValueFieldNumber; +const int Value::kStringValueFieldNumber; +const int Value::kBoolValueFieldNumber; +const int Value::kStructValueFieldNumber; +const int Value::kListValueFieldNumber; +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +Value::Value() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + ::google::protobuf::internal::InitSCC( + &protobuf_google_2fprotobuf_2fstruct_2eproto::scc_info_ListValue.base); + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.Value) +} +Value::Value(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(), + _internal_metadata_(arena) { + ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fstruct_2eproto::scc_info_ListValue.base); + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Value) +} +Value::Value(const Value& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + clear_has_kind(); + switch (from.kind_case()) { + case kNullValue: { + set_null_value(from.null_value()); + break; + } + case kNumberValue: { + set_number_value(from.number_value()); + break; + } + case kStringValue: { + set_string_value(from.string_value()); + break; + } + case kBoolValue: { + set_bool_value(from.bool_value()); + break; + } + case kStructValue: { + mutable_struct_value()->::google::protobuf::Struct::MergeFrom(from.struct_value()); + break; + } + case kListValue: { + mutable_list_value()->::google::protobuf::ListValue::MergeFrom(from.list_value()); + break; + } + case KIND_NOT_SET: { + break; + } + } + // @@protoc_insertion_point(copy_constructor:google.protobuf.Value) +} + +void Value::SharedCtor() { + clear_has_kind(); +} + +Value::~Value() { + // @@protoc_insertion_point(destructor:google.protobuf.Value) + SharedDtor(); +} + +void Value::SharedDtor() { + GOOGLE_DCHECK(GetArenaNoVirtual() == NULL); + if (has_kind()) { + clear_kind(); + } +} + +void Value::ArenaDtor(void* object) { + Value* _this = reinterpret_cast< Value* >(object); + (void)_this; +} +void Value::RegisterArenaDtor(::google::protobuf::Arena* arena) { +} +void Value::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const ::google::protobuf::Descriptor* Value::descriptor() { + ::protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +} + +const Value& Value::default_instance() { + ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fstruct_2eproto::scc_info_ListValue.base); + return *internal_default_instance(); +} + + +void Value::clear_kind() { +// @@protoc_insertion_point(one_of_clear_start:google.protobuf.Value) + switch (kind_case()) { + case kNullValue: { + // No need to clear + break; + } + case kNumberValue: { + // No need to clear + break; + } + case kStringValue: { + kind_.string_value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + break; + } + case kBoolValue: { + // No need to clear + break; + } + case kStructValue: { + if (GetArenaNoVirtual() == NULL) { + delete kind_.struct_value_; + } + break; + } + case kListValue: { + if (GetArenaNoVirtual() == NULL) { + delete kind_.list_value_; + } + break; + } + case KIND_NOT_SET: { + break; + } + } + _oneof_case_[0] = KIND_NOT_SET; +} + + +void Value::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Value) + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + clear_kind(); + _internal_metadata_.Clear(); +} + +bool Value::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.Value) + for (;;) { + ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // .google.protobuf.NullValue null_value = 1; + case 1: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { + int value; + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + int, ::google::protobuf::internal::WireFormatLite::TYPE_ENUM>( + input, &value))); + set_null_value(static_cast< ::google::protobuf::NullValue >(value)); + } else { + goto handle_unusual; + } + break; + } + + // double number_value = 2; + case 2: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(17u /* 17 & 0xFF */)) { + clear_kind(); + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + double, ::google::protobuf::internal::WireFormatLite::TYPE_DOUBLE>( + input, &kind_.number_value_))); + set_has_number_value(); + } else { + goto handle_unusual; + } + break; + } + + // string string_value = 3; + case 3: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(26u /* 26 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadString( + input, this->mutable_string_value())); + DO_(::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->string_value().data(), static_cast(this->string_value().length()), + ::google::protobuf::internal::WireFormatLite::PARSE, + "google.protobuf.Value.string_value")); + } else { + goto handle_unusual; + } + break; + } + + // bool bool_value = 4; + case 4: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(32u /* 32 & 0xFF */)) { + clear_kind(); + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + bool, ::google::protobuf::internal::WireFormatLite::TYPE_BOOL>( + input, &kind_.bool_value_))); + set_has_bool_value(); + } else { + goto handle_unusual; + } + break; + } + + // .google.protobuf.Struct struct_value = 5; + case 5: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(42u /* 42 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessage( + input, mutable_struct_value())); + } else { + goto handle_unusual; + } + break; + } + + // .google.protobuf.ListValue list_value = 6; + case 6: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(50u /* 50 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessage( + input, mutable_list_value())); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.Value) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.Value) + return false; +#undef DO_ +} + +void Value::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.Value) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // .google.protobuf.NullValue null_value = 1; + if (has_null_value()) { + ::google::protobuf::internal::WireFormatLite::WriteEnum( + 1, this->null_value(), output); + } + + // double number_value = 2; + if (has_number_value()) { + ::google::protobuf::internal::WireFormatLite::WriteDouble(2, this->number_value(), output); + } + + // string string_value = 3; + if (has_string_value()) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->string_value().data(), static_cast(this->string_value().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Value.string_value"); + ::google::protobuf::internal::WireFormatLite::WriteStringMaybeAliased( + 3, this->string_value(), output); + } + + // bool bool_value = 4; + if (has_bool_value()) { + ::google::protobuf::internal::WireFormatLite::WriteBool(4, this->bool_value(), output); + } + + // .google.protobuf.Struct struct_value = 5; + if (has_struct_value()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 5, this->_internal_struct_value(), output); + } + + // .google.protobuf.ListValue list_value = 6; + if (has_list_value()) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 6, this->_internal_list_value(), output); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.Value) +} + +::google::protobuf::uint8* Value::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { + (void)deterministic; // Unused + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // .google.protobuf.NullValue null_value = 1; + if (has_null_value()) { + target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray( + 1, this->null_value(), target); + } + + // double number_value = 2; + if (has_number_value()) { + target = ::google::protobuf::internal::WireFormatLite::WriteDoubleToArray(2, this->number_value(), target); + } + + // string string_value = 3; + if (has_string_value()) { + ::google::protobuf::internal::WireFormatLite::VerifyUtf8String( + this->string_value().data(), static_cast(this->string_value().length()), + ::google::protobuf::internal::WireFormatLite::SERIALIZE, + "google.protobuf.Value.string_value"); + target = + ::google::protobuf::internal::WireFormatLite::WriteStringToArray( + 3, this->string_value(), target); + } + + // bool bool_value = 4; + if (has_bool_value()) { + target = ::google::protobuf::internal::WireFormatLite::WriteBoolToArray(4, this->bool_value(), target); + } + + // .google.protobuf.Struct struct_value = 5; + if (has_struct_value()) { + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessageToArray( + 5, this->_internal_struct_value(), deterministic, target); + } + + // .google.protobuf.ListValue list_value = 6; + if (has_list_value()) { + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessageToArray( + 6, this->_internal_list_value(), deterministic, target); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Value) + return target; +} + +size_t Value::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value) + size_t total_size = 0; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); + } + switch (kind_case()) { + // .google.protobuf.NullValue null_value = 1; + case kNullValue: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::EnumSize(this->null_value()); + break; + } + // double number_value = 2; + case kNumberValue: { + total_size += 1 + 8; + break; + } + // string string_value = 3; + case kStringValue: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::StringSize( + this->string_value()); + break; + } + // bool bool_value = 4; + case kBoolValue: { + total_size += 1 + 1; + break; + } + // .google.protobuf.Struct struct_value = 5; + case kStructValue: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize( + *kind_.struct_value_); + break; + } + // .google.protobuf.ListValue list_value = 6; + case kListValue: { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::MessageSize( + *kind_.list_value_); + break; + } + case KIND_NOT_SET: { + break; + } + } + int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void Value::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Value) + GOOGLE_DCHECK_NE(&from, this); + const Value* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Value) + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Value) + MergeFrom(*source); + } +} + +void Value::MergeFrom(const Value& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + switch (from.kind_case()) { + case kNullValue: { + set_null_value(from.null_value()); + break; + } + case kNumberValue: { + set_number_value(from.number_value()); + break; + } + case kStringValue: { + set_string_value(from.string_value()); + break; + } + case kBoolValue: { + set_bool_value(from.bool_value()); + break; + } + case kStructValue: { + mutable_struct_value()->::google::protobuf::Struct::MergeFrom(from.struct_value()); + break; + } + case kListValue: { + mutable_list_value()->::google::protobuf::ListValue::MergeFrom(from.list_value()); + break; + } + case KIND_NOT_SET: { + break; + } + } +} + +void Value::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Value) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Value::CopyFrom(const Value& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Value) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Value::IsInitialized() const { + return true; +} + +void Value::Swap(Value* other) { + if (other == this) return; + if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { + InternalSwap(other); + } else { + Value* temp = New(GetArenaNoVirtual()); + temp->MergeFrom(*other); + other->CopyFrom(*this); + InternalSwap(temp); + if (GetArenaNoVirtual() == NULL) { + delete temp; + } + } +} +void Value::UnsafeArenaSwap(Value* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + InternalSwap(other); +} +void Value::InternalSwap(Value* other) { + using std::swap; + swap(kind_, other->kind_); + swap(_oneof_case_[0], other->_oneof_case_[0]); + _internal_metadata_.Swap(&other->_internal_metadata_); +} + +::google::protobuf::Metadata Value::GetMetadata() const { + protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages]; +} + + +// =================================================================== + +void ListValue::InitAsDefaultInstance() { +} +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +const int ListValue::kValuesFieldNumber; +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +ListValue::ListValue() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + ::google::protobuf::internal::InitSCC( + &protobuf_google_2fprotobuf_2fstruct_2eproto::scc_info_ListValue.base); + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.ListValue) +} +ListValue::ListValue(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(), + _internal_metadata_(arena), + values_(arena) { + ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fstruct_2eproto::scc_info_ListValue.base); + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.ListValue) +} +ListValue::ListValue(const ListValue& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL), + values_(from.values_) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + // @@protoc_insertion_point(copy_constructor:google.protobuf.ListValue) +} + +void ListValue::SharedCtor() { +} + +ListValue::~ListValue() { + // @@protoc_insertion_point(destructor:google.protobuf.ListValue) + SharedDtor(); +} + +void ListValue::SharedDtor() { + GOOGLE_DCHECK(GetArenaNoVirtual() == NULL); +} + +void ListValue::ArenaDtor(void* object) { + ListValue* _this = reinterpret_cast< ListValue* >(object); + (void)_this; +} +void ListValue::RegisterArenaDtor(::google::protobuf::Arena* arena) { +} +void ListValue::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const ::google::protobuf::Descriptor* ListValue::descriptor() { + ::protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +} + +const ListValue& ListValue::default_instance() { + ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2fstruct_2eproto::scc_info_ListValue.base); + return *internal_default_instance(); +} + + +void ListValue::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue) + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + values_.Clear(); + _internal_metadata_.Clear(); +} + +bool ListValue::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.ListValue) + for (;;) { + ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // repeated .google.protobuf.Value values = 1; + case 1: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(10u /* 10 & 0xFF */)) { + DO_(::google::protobuf::internal::WireFormatLite::ReadMessage( + input, add_values())); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.ListValue) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.ListValue) + return false; +#undef DO_ +} + +void ListValue::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.ListValue) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .google.protobuf.Value values = 1; + for (unsigned int i = 0, + n = static_cast(this->values_size()); i < n; i++) { + ::google::protobuf::internal::WireFormatLite::WriteMessageMaybeToArray( + 1, + this->values(static_cast(i)), + output); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.ListValue) +} + +::google::protobuf::uint8* ListValue::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { + (void)deterministic; // Unused + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // repeated .google.protobuf.Value values = 1; + for (unsigned int i = 0, + n = static_cast(this->values_size()); i < n; i++) { + target = ::google::protobuf::internal::WireFormatLite:: + InternalWriteMessageToArray( + 1, this->values(static_cast(i)), deterministic, target); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.ListValue) + return target; +} + +size_t ListValue::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue) + size_t total_size = 0; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); + } + // repeated .google.protobuf.Value values = 1; + { + unsigned int count = static_cast(this->values_size()); + total_size += 1UL * count; + for (unsigned int i = 0; i < count; i++) { + total_size += + ::google::protobuf::internal::WireFormatLite::MessageSize( + this->values(static_cast(i))); + } + } + + int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void ListValue::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.ListValue) + GOOGLE_DCHECK_NE(&from, this); + const ListValue* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.ListValue) + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.ListValue) + MergeFrom(*source); + } +} + +void ListValue::MergeFrom(const ListValue& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + values_.MergeFrom(from.values_); +} + +void ListValue::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.ListValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void ListValue::CopyFrom(const ListValue& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.ListValue) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ListValue::IsInitialized() const { + return true; +} + +void ListValue::Swap(ListValue* other) { + if (other == this) return; + if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { + InternalSwap(other); + } else { + ListValue* temp = New(GetArenaNoVirtual()); + temp->MergeFrom(*other); + other->CopyFrom(*this); + InternalSwap(temp); + if (GetArenaNoVirtual() == NULL) { + delete temp; + } + } +} +void ListValue::UnsafeArenaSwap(ListValue* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + InternalSwap(other); +} +void ListValue::InternalSwap(ListValue* other) { + using std::swap; + CastToBase(&values_)->InternalSwap(CastToBase(&other->values_)); + _internal_metadata_.Swap(&other->_internal_metadata_); +} + +::google::protobuf::Metadata ListValue::GetMetadata() const { + protobuf_google_2fprotobuf_2fstruct_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2fstruct_2eproto::file_level_metadata[kIndexInFileMessages]; +} + + +// @@protoc_insertion_point(namespace_scope) +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Struct_FieldsEntry_DoNotUse* Arena::CreateMaybeMessage< ::google::protobuf::Struct_FieldsEntry_DoNotUse >(Arena* arena) { + return Arena::CreateMessageInternal< ::google::protobuf::Struct_FieldsEntry_DoNotUse >(arena); +} +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Struct* Arena::CreateMaybeMessage< ::google::protobuf::Struct >(Arena* arena) { + return Arena::CreateMessageInternal< ::google::protobuf::Struct >(arena); +} +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Value* Arena::CreateMaybeMessage< ::google::protobuf::Value >(Arena* arena) { + return Arena::CreateMessageInternal< ::google::protobuf::Value >(arena); +} +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::ListValue* Arena::CreateMaybeMessage< ::google::protobuf::ListValue >(Arena* arena) { + return Arena::CreateMessageInternal< ::google::protobuf::ListValue >(arena); +} +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/struct.pb.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/struct.pb.h new file mode 100644 index 000000000..1cf75d9bb --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/struct.pb.h @@ -0,0 +1,1051 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/struct.proto + +#ifndef PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto +#define PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 3006001 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +#include +#include +#include +// @@protoc_insertion_point(includes) +#define PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fstruct_2eproto LIBPROTOBUF_EXPORT + +namespace protobuf_google_2fprotobuf_2fstruct_2eproto { +// Internal implementation detail -- do not use these members. +struct LIBPROTOBUF_EXPORT TableStruct { + static const ::google::protobuf::internal::ParseTableField entries[]; + static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; + static const ::google::protobuf::internal::ParseTable schema[4]; + static const ::google::protobuf::internal::FieldMetadata field_metadata[]; + static const ::google::protobuf::internal::SerializationTable serialization_table[]; + static const ::google::protobuf::uint32 offsets[]; +}; +void LIBPROTOBUF_EXPORT AddDescriptors(); +} // namespace protobuf_google_2fprotobuf_2fstruct_2eproto +namespace google { +namespace protobuf { +class ListValue; +class ListValueDefaultTypeInternal; +LIBPROTOBUF_EXPORT extern ListValueDefaultTypeInternal _ListValue_default_instance_; +class Struct; +class StructDefaultTypeInternal; +LIBPROTOBUF_EXPORT extern StructDefaultTypeInternal _Struct_default_instance_; +class Struct_FieldsEntry_DoNotUse; +class Struct_FieldsEntry_DoNotUseDefaultTypeInternal; +LIBPROTOBUF_EXPORT extern Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_; +class Value; +class ValueDefaultTypeInternal; +LIBPROTOBUF_EXPORT extern ValueDefaultTypeInternal _Value_default_instance_; +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { +template<> LIBPROTOBUF_EXPORT ::google::protobuf::ListValue* Arena::CreateMaybeMessage<::google::protobuf::ListValue>(Arena*); +template<> LIBPROTOBUF_EXPORT ::google::protobuf::Struct* Arena::CreateMaybeMessage<::google::protobuf::Struct>(Arena*); +template<> LIBPROTOBUF_EXPORT ::google::protobuf::Struct_FieldsEntry_DoNotUse* Arena::CreateMaybeMessage<::google::protobuf::Struct_FieldsEntry_DoNotUse>(Arena*); +template<> LIBPROTOBUF_EXPORT ::google::protobuf::Value* Arena::CreateMaybeMessage<::google::protobuf::Value>(Arena*); +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { + +enum NullValue { + NULL_VALUE = 0, + NullValue_INT_MIN_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32min, + NullValue_INT_MAX_SENTINEL_DO_NOT_USE_ = ::google::protobuf::kint32max +}; +LIBPROTOBUF_EXPORT bool NullValue_IsValid(int value); +const NullValue NullValue_MIN = NULL_VALUE; +const NullValue NullValue_MAX = NULL_VALUE; +const int NullValue_ARRAYSIZE = NullValue_MAX + 1; + +LIBPROTOBUF_EXPORT const ::google::protobuf::EnumDescriptor* NullValue_descriptor(); +inline const ::std::string& NullValue_Name(NullValue value) { + return ::google::protobuf::internal::NameOfEnum( + NullValue_descriptor(), value); +} +inline bool NullValue_Parse( + const ::std::string& name, NullValue* value) { + return ::google::protobuf::internal::ParseNamedEnum( + NullValue_descriptor(), name, value); +} +// =================================================================== + +class Struct_FieldsEntry_DoNotUse : public ::google::protobuf::internal::MapEntry { +public: + typedef ::google::protobuf::internal::MapEntry SuperType; + Struct_FieldsEntry_DoNotUse(); + Struct_FieldsEntry_DoNotUse(::google::protobuf::Arena* arena); + void MergeFrom(const Struct_FieldsEntry_DoNotUse& other); + static const Struct_FieldsEntry_DoNotUse* internal_default_instance() { return reinterpret_cast(&_Struct_FieldsEntry_DoNotUse_default_instance_); } + void MergeFrom(const ::google::protobuf::Message& other) final; + ::google::protobuf::Metadata GetMetadata() const; +}; + +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT Struct : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Struct) */ { + public: + Struct(); + virtual ~Struct(); + + Struct(const Struct& from); + + inline Struct& operator=(const Struct& from) { + CopyFrom(from); + return *this; + } + #if LANG_CXX11 + Struct(Struct&& from) noexcept + : Struct() { + *this = ::std::move(from); + } + + inline Struct& operator=(Struct&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + #endif + inline ::google::protobuf::Arena* GetArena() const final { + return GetArenaNoVirtual(); + } + inline void* GetMaybeArenaPointer() const final { + return MaybeArenaPtr(); + } + static const ::google::protobuf::Descriptor* descriptor(); + static const Struct& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const Struct* internal_default_instance() { + return reinterpret_cast( + &_Struct_default_instance_); + } + static constexpr int kIndexInFileMessages = + 1; + + void UnsafeArenaSwap(Struct* other); + void Swap(Struct* other); + friend void swap(Struct& a, Struct& b) { + a.Swap(&b); + } + + // implements Message ---------------------------------------------- + + inline Struct* New() const final { + return CreateMaybeMessage(NULL); + } + + Struct* New(::google::protobuf::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::google::protobuf::Message& from) final; + void MergeFrom(const ::google::protobuf::Message& from) final; + void CopyFrom(const Struct& from); + void MergeFrom(const Struct& from); + void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) final; + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const final; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Struct* other); + protected: + explicit Struct(::google::protobuf::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + + // accessors ------------------------------------------------------- + + // map fields = 1; + int fields_size() const; + void clear_fields(); + static const int kFieldsFieldNumber = 1; + const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >& + fields() const; + ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >* + mutable_fields(); + + // @@protoc_insertion_point(class_scope:google.protobuf.Struct) + private: + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + template friend class ::google::protobuf::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::google::protobuf::internal::MapField< + Struct_FieldsEntry_DoNotUse, + ::std::string, ::google::protobuf::Value, + ::google::protobuf::internal::WireFormatLite::TYPE_STRING, + ::google::protobuf::internal::WireFormatLite::TYPE_MESSAGE, + 0 > fields_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + friend struct ::protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT Value : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Value) */ { + public: + Value(); + virtual ~Value(); + + Value(const Value& from); + + inline Value& operator=(const Value& from) { + CopyFrom(from); + return *this; + } + #if LANG_CXX11 + Value(Value&& from) noexcept + : Value() { + *this = ::std::move(from); + } + + inline Value& operator=(Value&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + #endif + inline ::google::protobuf::Arena* GetArena() const final { + return GetArenaNoVirtual(); + } + inline void* GetMaybeArenaPointer() const final { + return MaybeArenaPtr(); + } + static const ::google::protobuf::Descriptor* descriptor(); + static const Value& default_instance(); + + enum KindCase { + kNullValue = 1, + kNumberValue = 2, + kStringValue = 3, + kBoolValue = 4, + kStructValue = 5, + kListValue = 6, + KIND_NOT_SET = 0, + }; + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const Value* internal_default_instance() { + return reinterpret_cast( + &_Value_default_instance_); + } + static constexpr int kIndexInFileMessages = + 2; + + void UnsafeArenaSwap(Value* other); + void Swap(Value* other); + friend void swap(Value& a, Value& b) { + a.Swap(&b); + } + + // implements Message ---------------------------------------------- + + inline Value* New() const final { + return CreateMaybeMessage(NULL); + } + + Value* New(::google::protobuf::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::google::protobuf::Message& from) final; + void MergeFrom(const ::google::protobuf::Message& from) final; + void CopyFrom(const Value& from); + void MergeFrom(const Value& from); + void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) final; + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const final; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Value* other); + protected: + explicit Value(::google::protobuf::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // .google.protobuf.NullValue null_value = 1; + private: + bool has_null_value() const; + public: + void clear_null_value(); + static const int kNullValueFieldNumber = 1; + ::google::protobuf::NullValue null_value() const; + void set_null_value(::google::protobuf::NullValue value); + + // double number_value = 2; + private: + bool has_number_value() const; + public: + void clear_number_value(); + static const int kNumberValueFieldNumber = 2; + double number_value() const; + void set_number_value(double value); + + // string string_value = 3; + private: + bool has_string_value() const; + public: + void clear_string_value(); + static const int kStringValueFieldNumber = 3; + const ::std::string& string_value() const; + void set_string_value(const ::std::string& value); + #if LANG_CXX11 + void set_string_value(::std::string&& value); + #endif + void set_string_value(const char* value); + void set_string_value(const char* value, size_t size); + ::std::string* mutable_string_value(); + ::std::string* release_string_value(); + void set_allocated_string_value(::std::string* string_value); + PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for" + " string fields are deprecated and will be removed in a" + " future release.") + ::std::string* unsafe_arena_release_string_value(); + PROTOBUF_RUNTIME_DEPRECATED("The unsafe_arena_ accessors for" + " string fields are deprecated and will be removed in a" + " future release.") + void unsafe_arena_set_allocated_string_value( + ::std::string* string_value); + + // bool bool_value = 4; + private: + bool has_bool_value() const; + public: + void clear_bool_value(); + static const int kBoolValueFieldNumber = 4; + bool bool_value() const; + void set_bool_value(bool value); + + // .google.protobuf.Struct struct_value = 5; + bool has_struct_value() const; + void clear_struct_value(); + static const int kStructValueFieldNumber = 5; + private: + const ::google::protobuf::Struct& _internal_struct_value() const; + public: + const ::google::protobuf::Struct& struct_value() const; + ::google::protobuf::Struct* release_struct_value(); + ::google::protobuf::Struct* mutable_struct_value(); + void set_allocated_struct_value(::google::protobuf::Struct* struct_value); + void unsafe_arena_set_allocated_struct_value( + ::google::protobuf::Struct* struct_value); + ::google::protobuf::Struct* unsafe_arena_release_struct_value(); + + // .google.protobuf.ListValue list_value = 6; + bool has_list_value() const; + void clear_list_value(); + static const int kListValueFieldNumber = 6; + private: + const ::google::protobuf::ListValue& _internal_list_value() const; + public: + const ::google::protobuf::ListValue& list_value() const; + ::google::protobuf::ListValue* release_list_value(); + ::google::protobuf::ListValue* mutable_list_value(); + void set_allocated_list_value(::google::protobuf::ListValue* list_value); + void unsafe_arena_set_allocated_list_value( + ::google::protobuf::ListValue* list_value); + ::google::protobuf::ListValue* unsafe_arena_release_list_value(); + + void clear_kind(); + KindCase kind_case() const; + // @@protoc_insertion_point(class_scope:google.protobuf.Value) + private: + void set_has_null_value(); + void set_has_number_value(); + void set_has_string_value(); + void set_has_bool_value(); + void set_has_struct_value(); + void set_has_list_value(); + + inline bool has_kind() const; + inline void clear_has_kind(); + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + template friend class ::google::protobuf::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + union KindUnion { + KindUnion() {} + int null_value_; + double number_value_; + ::google::protobuf::internal::ArenaStringPtr string_value_; + bool bool_value_; + ::google::protobuf::Struct* struct_value_; + ::google::protobuf::ListValue* list_value_; + } kind_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + ::google::protobuf::uint32 _oneof_case_[1]; + + friend struct ::protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct; +}; +// ------------------------------------------------------------------- + +class LIBPROTOBUF_EXPORT ListValue : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ListValue) */ { + public: + ListValue(); + virtual ~ListValue(); + + ListValue(const ListValue& from); + + inline ListValue& operator=(const ListValue& from) { + CopyFrom(from); + return *this; + } + #if LANG_CXX11 + ListValue(ListValue&& from) noexcept + : ListValue() { + *this = ::std::move(from); + } + + inline ListValue& operator=(ListValue&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + #endif + inline ::google::protobuf::Arena* GetArena() const final { + return GetArenaNoVirtual(); + } + inline void* GetMaybeArenaPointer() const final { + return MaybeArenaPtr(); + } + static const ::google::protobuf::Descriptor* descriptor(); + static const ListValue& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const ListValue* internal_default_instance() { + return reinterpret_cast( + &_ListValue_default_instance_); + } + static constexpr int kIndexInFileMessages = + 3; + + void UnsafeArenaSwap(ListValue* other); + void Swap(ListValue* other); + friend void swap(ListValue& a, ListValue& b) { + a.Swap(&b); + } + + // implements Message ---------------------------------------------- + + inline ListValue* New() const final { + return CreateMaybeMessage(NULL); + } + + ListValue* New(::google::protobuf::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::google::protobuf::Message& from) final; + void MergeFrom(const ::google::protobuf::Message& from) final; + void CopyFrom(const ListValue& from); + void MergeFrom(const ListValue& from); + void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) final; + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const final; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ListValue* other); + protected: + explicit ListValue(::google::protobuf::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // repeated .google.protobuf.Value values = 1; + int values_size() const; + void clear_values(); + static const int kValuesFieldNumber = 1; + ::google::protobuf::Value* mutable_values(int index); + ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >* + mutable_values(); + const ::google::protobuf::Value& values(int index) const; + ::google::protobuf::Value* add_values(); + const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >& + values() const; + + // @@protoc_insertion_point(class_scope:google.protobuf.ListValue) + private: + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + template friend class ::google::protobuf::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value > values_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + friend struct ::protobuf_google_2fprotobuf_2fstruct_2eproto::TableStruct; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// Struct + +// map fields = 1; +inline int Struct::fields_size() const { + return fields_.size(); +} +inline void Struct::clear_fields() { + fields_.Clear(); +} +inline const ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >& +Struct::fields() const { + // @@protoc_insertion_point(field_map:google.protobuf.Struct.fields) + return fields_.GetMap(); +} +inline ::google::protobuf::Map< ::std::string, ::google::protobuf::Value >* +Struct::mutable_fields() { + // @@protoc_insertion_point(field_mutable_map:google.protobuf.Struct.fields) + return fields_.MutableMap(); +} + +// ------------------------------------------------------------------- + +// Value + +// .google.protobuf.NullValue null_value = 1; +inline bool Value::has_null_value() const { + return kind_case() == kNullValue; +} +inline void Value::set_has_null_value() { + _oneof_case_[0] = kNullValue; +} +inline void Value::clear_null_value() { + if (has_null_value()) { + kind_.null_value_ = 0; + clear_has_kind(); + } +} +inline ::google::protobuf::NullValue Value::null_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.null_value) + if (has_null_value()) { + return static_cast< ::google::protobuf::NullValue >(kind_.null_value_); + } + return static_cast< ::google::protobuf::NullValue >(0); +} +inline void Value::set_null_value(::google::protobuf::NullValue value) { + if (!has_null_value()) { + clear_kind(); + set_has_null_value(); + } + kind_.null_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.Value.null_value) +} + +// double number_value = 2; +inline bool Value::has_number_value() const { + return kind_case() == kNumberValue; +} +inline void Value::set_has_number_value() { + _oneof_case_[0] = kNumberValue; +} +inline void Value::clear_number_value() { + if (has_number_value()) { + kind_.number_value_ = 0; + clear_has_kind(); + } +} +inline double Value::number_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.number_value) + if (has_number_value()) { + return kind_.number_value_; + } + return 0; +} +inline void Value::set_number_value(double value) { + if (!has_number_value()) { + clear_kind(); + set_has_number_value(); + } + kind_.number_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.Value.number_value) +} + +// string string_value = 3; +inline bool Value::has_string_value() const { + return kind_case() == kStringValue; +} +inline void Value::set_has_string_value() { + _oneof_case_[0] = kStringValue; +} +inline void Value::clear_string_value() { + if (has_string_value()) { + kind_.string_value_.Destroy(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + clear_has_kind(); + } +} +inline const ::std::string& Value::string_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.string_value) + if (has_string_value()) { + return kind_.string_value_.Get(); + } + return *&::google::protobuf::internal::GetEmptyStringAlreadyInited(); +} +inline void Value::set_string_value(const ::std::string& value) { + if (!has_string_value()) { + clear_kind(); + set_has_string_value(); + kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + kind_.string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), value, + GetArenaNoVirtual()); + // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value) +} +#if LANG_CXX11 +inline void Value::set_string_value(::std::string&& value) { + // @@protoc_insertion_point(field_set:google.protobuf.Value.string_value) + if (!has_string_value()) { + clear_kind(); + set_has_string_value(); + kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + kind_.string_value_.Set( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::move(value), GetArenaNoVirtual()); + // @@protoc_insertion_point(field_set_rvalue:google.protobuf.Value.string_value) +} +#endif +inline void Value::set_string_value(const char* value) { + GOOGLE_DCHECK(value != NULL); + if (!has_string_value()) { + clear_kind(); + set_has_string_value(); + kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + kind_.string_value_.Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + ::std::string(value), GetArenaNoVirtual()); + // @@protoc_insertion_point(field_set_char:google.protobuf.Value.string_value) +} +inline void Value::set_string_value(const char* value, + size_t size) { + if (!has_string_value()) { + clear_kind(); + set_has_string_value(); + kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + kind_.string_value_.Set( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), ::std::string( + reinterpret_cast(value), size), + GetArenaNoVirtual()); + // @@protoc_insertion_point(field_set_pointer:google.protobuf.Value.string_value) +} +inline ::std::string* Value::mutable_string_value() { + if (!has_string_value()) { + clear_kind(); + set_has_string_value(); + kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + return kind_.string_value_.Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + // @@protoc_insertion_point(field_mutable:google.protobuf.Value.string_value) +} +inline ::std::string* Value::release_string_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value) + if (has_string_value()) { + clear_has_kind(); + return kind_.string_value_.Release(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), + GetArenaNoVirtual()); + } else { + return NULL; + } +} +inline void Value::set_allocated_string_value(::std::string* string_value) { + if (!has_string_value()) { + kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + clear_kind(); + if (string_value != NULL) { + set_has_string_value(); + kind_.string_value_.SetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value, + GetArenaNoVirtual()); + } + // @@protoc_insertion_point(field_set_allocated:google.protobuf.Value.string_value) +} +inline ::std::string* Value::unsafe_arena_release_string_value() { + // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.string_value) + GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); + if (has_string_value()) { + clear_has_kind(); + return kind_.string_value_.UnsafeArenaRelease( + &::google::protobuf::internal::GetEmptyStringAlreadyInited(), GetArenaNoVirtual()); + } else { + return NULL; + } +} +inline void Value::unsafe_arena_set_allocated_string_value(::std::string* string_value) { + GOOGLE_DCHECK(GetArenaNoVirtual() != NULL); + if (!has_string_value()) { + kind_.string_value_.UnsafeSetDefault(&::google::protobuf::internal::GetEmptyStringAlreadyInited()); + } + clear_kind(); + if (string_value) { + set_has_string_value(); + kind_.string_value_.UnsafeArenaSetAllocated(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), string_value, GetArenaNoVirtual()); + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.string_value) +} + +// bool bool_value = 4; +inline bool Value::has_bool_value() const { + return kind_case() == kBoolValue; +} +inline void Value::set_has_bool_value() { + _oneof_case_[0] = kBoolValue; +} +inline void Value::clear_bool_value() { + if (has_bool_value()) { + kind_.bool_value_ = false; + clear_has_kind(); + } +} +inline bool Value::bool_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.bool_value) + if (has_bool_value()) { + return kind_.bool_value_; + } + return false; +} +inline void Value::set_bool_value(bool value) { + if (!has_bool_value()) { + clear_kind(); + set_has_bool_value(); + } + kind_.bool_value_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.Value.bool_value) +} + +// .google.protobuf.Struct struct_value = 5; +inline bool Value::has_struct_value() const { + return kind_case() == kStructValue; +} +inline void Value::set_has_struct_value() { + _oneof_case_[0] = kStructValue; +} +inline void Value::clear_struct_value() { + if (has_struct_value()) { + if (GetArenaNoVirtual() == NULL) { + delete kind_.struct_value_; + } + clear_has_kind(); + } +} +inline const ::google::protobuf::Struct& Value::_internal_struct_value() const { + return *kind_.struct_value_; +} +inline ::google::protobuf::Struct* Value::release_struct_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value) + if (has_struct_value()) { + clear_has_kind(); + ::google::protobuf::Struct* temp = kind_.struct_value_; + if (GetArenaNoVirtual() != NULL) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + kind_.struct_value_ = NULL; + return temp; + } else { + return NULL; + } +} +inline const ::google::protobuf::Struct& Value::struct_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.struct_value) + return has_struct_value() + ? *kind_.struct_value_ + : *reinterpret_cast< ::google::protobuf::Struct*>(&::google::protobuf::_Struct_default_instance_); +} +inline ::google::protobuf::Struct* Value::unsafe_arena_release_struct_value() { + // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.struct_value) + if (has_struct_value()) { + clear_has_kind(); + ::google::protobuf::Struct* temp = kind_.struct_value_; + kind_.struct_value_ = NULL; + return temp; + } else { + return NULL; + } +} +inline void Value::unsafe_arena_set_allocated_struct_value(::google::protobuf::Struct* struct_value) { + clear_kind(); + if (struct_value) { + set_has_struct_value(); + kind_.struct_value_ = struct_value; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.struct_value) +} +inline ::google::protobuf::Struct* Value::mutable_struct_value() { + if (!has_struct_value()) { + clear_kind(); + set_has_struct_value(); + kind_.struct_value_ = CreateMaybeMessage< ::google::protobuf::Struct >( + GetArenaNoVirtual()); + } + // @@protoc_insertion_point(field_mutable:google.protobuf.Value.struct_value) + return kind_.struct_value_; +} + +// .google.protobuf.ListValue list_value = 6; +inline bool Value::has_list_value() const { + return kind_case() == kListValue; +} +inline void Value::set_has_list_value() { + _oneof_case_[0] = kListValue; +} +inline void Value::clear_list_value() { + if (has_list_value()) { + if (GetArenaNoVirtual() == NULL) { + delete kind_.list_value_; + } + clear_has_kind(); + } +} +inline const ::google::protobuf::ListValue& Value::_internal_list_value() const { + return *kind_.list_value_; +} +inline ::google::protobuf::ListValue* Value::release_list_value() { + // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value) + if (has_list_value()) { + clear_has_kind(); + ::google::protobuf::ListValue* temp = kind_.list_value_; + if (GetArenaNoVirtual() != NULL) { + temp = ::google::protobuf::internal::DuplicateIfNonNull(temp); + } + kind_.list_value_ = NULL; + return temp; + } else { + return NULL; + } +} +inline const ::google::protobuf::ListValue& Value::list_value() const { + // @@protoc_insertion_point(field_get:google.protobuf.Value.list_value) + return has_list_value() + ? *kind_.list_value_ + : *reinterpret_cast< ::google::protobuf::ListValue*>(&::google::protobuf::_ListValue_default_instance_); +} +inline ::google::protobuf::ListValue* Value::unsafe_arena_release_list_value() { + // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.list_value) + if (has_list_value()) { + clear_has_kind(); + ::google::protobuf::ListValue* temp = kind_.list_value_; + kind_.list_value_ = NULL; + return temp; + } else { + return NULL; + } +} +inline void Value::unsafe_arena_set_allocated_list_value(::google::protobuf::ListValue* list_value) { + clear_kind(); + if (list_value) { + set_has_list_value(); + kind_.list_value_ = list_value; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.list_value) +} +inline ::google::protobuf::ListValue* Value::mutable_list_value() { + if (!has_list_value()) { + clear_kind(); + set_has_list_value(); + kind_.list_value_ = CreateMaybeMessage< ::google::protobuf::ListValue >( + GetArenaNoVirtual()); + } + // @@protoc_insertion_point(field_mutable:google.protobuf.Value.list_value) + return kind_.list_value_; +} + +inline bool Value::has_kind() const { + return kind_case() != KIND_NOT_SET; +} +inline void Value::clear_has_kind() { + _oneof_case_[0] = KIND_NOT_SET; +} +inline Value::KindCase Value::kind_case() const { + return Value::KindCase(_oneof_case_[0]); +} +// ------------------------------------------------------------------- + +// ListValue + +// repeated .google.protobuf.Value values = 1; +inline int ListValue::values_size() const { + return values_.size(); +} +inline void ListValue::clear_values() { + values_.Clear(); +} +inline ::google::protobuf::Value* ListValue::mutable_values(int index) { + // @@protoc_insertion_point(field_mutable:google.protobuf.ListValue.values) + return values_.Mutable(index); +} +inline ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >* +ListValue::mutable_values() { + // @@protoc_insertion_point(field_mutable_list:google.protobuf.ListValue.values) + return &values_; +} +inline const ::google::protobuf::Value& ListValue::values(int index) const { + // @@protoc_insertion_point(field_get:google.protobuf.ListValue.values) + return values_.Get(index); +} +inline ::google::protobuf::Value* ListValue::add_values() { + // @@protoc_insertion_point(field_add:google.protobuf.ListValue.values) + return values_.Add(); +} +inline const ::google::protobuf::RepeatedPtrField< ::google::protobuf::Value >& +ListValue::values() const { + // @@protoc_insertion_point(field_list:google.protobuf.ListValue.values) + return values_; +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + + +// @@protoc_insertion_point(namespace_scope) + +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { + +template <> struct is_proto_enum< ::google::protobuf::NullValue> : ::std::true_type {}; +template <> +inline const EnumDescriptor* GetEnumDescriptor< ::google::protobuf::NullValue>() { + return ::google::protobuf::NullValue_descriptor(); +} + +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/struct.proto b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/struct.proto new file mode 100644 index 000000000..7d7808e7f --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/struct.proto @@ -0,0 +1,96 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/struct;structpb"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "StructProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + + +// `Struct` represents a structured data value, consisting of fields +// which map to dynamically typed values. In some languages, `Struct` +// might be supported by a native representation. For example, in +// scripting languages like JS a struct is represented as an +// object. The details of that representation are described together +// with the proto support for the language. +// +// The JSON representation for `Struct` is JSON object. +message Struct { + // Unordered map of dynamically typed values. + map fields = 1; +} + +// `Value` represents a dynamically typed value which can be either +// null, a number, a string, a boolean, a recursive struct value, or a +// list of values. A producer of value is expected to set one of that +// variants, absence of any variant indicates an error. +// +// The JSON representation for `Value` is JSON value. +message Value { + // The kind of value. + oneof kind { + // Represents a null value. + NullValue null_value = 1; + // Represents a double value. + double number_value = 2; + // Represents a string value. + string string_value = 3; + // Represents a boolean value. + bool bool_value = 4; + // Represents a structured value. + Struct struct_value = 5; + // Represents a repeated `Value`. + ListValue list_value = 6; + } +} + +// `NullValue` is a singleton enumeration to represent the null value for the +// `Value` type union. +// +// The JSON representation for `NullValue` is JSON `null`. +enum NullValue { + // Null value. + NULL_VALUE = 0; +} + +// `ListValue` is a wrapper around a repeated field of values. +// +// The JSON representation for `ListValue` is JSON array. +message ListValue { + // Repeated field of dynamically typed values. + repeated Value values = 1; +} diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/bytestream.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/bytestream.cc new file mode 100644 index 000000000..f4af6a50a --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/bytestream.cc @@ -0,0 +1,196 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include +#include + +namespace google { +namespace protobuf { +namespace strings { + +void ByteSource::CopyTo(ByteSink* sink, size_t n) { + while (n > 0) { + StringPiece fragment = Peek(); + if (fragment.empty()) { + GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input."; + break; + } + std::size_t fragment_size = std::min(n, fragment.size()); + sink->Append(fragment.data(), fragment_size); + Skip(fragment_size); + n -= fragment_size; + } +} + +void ByteSink::Flush() {} + +void UncheckedArrayByteSink::Append(const char* data, size_t n) { + if (data != dest_) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + GOOGLE_DCHECK(!(dest_ <= data && data < (dest_ + n))) + << "Append() data[] overlaps with dest_[]"; + memcpy(dest_, data, n); + } + dest_ += n; +} + +CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, size_t capacity) + : outbuf_(outbuf), capacity_(capacity), size_(0), overflowed_(false) { +} + +void CheckedArrayByteSink::Append(const char* bytes, size_t n) { + size_t available = capacity_ - size_; + if (n > available) { + n = available; + overflowed_ = true; + } + if (n > 0 && bytes != (outbuf_ + size_)) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + GOOGLE_DCHECK(!(outbuf_ <= bytes && bytes < (outbuf_ + capacity_))) + << "Append() bytes[] overlaps with outbuf_[]"; + memcpy(outbuf_ + size_, bytes, n); + } + size_ += n; +} + +GrowingArrayByteSink::GrowingArrayByteSink(size_t estimated_size) + : capacity_(estimated_size), + buf_(new char[estimated_size]), + size_(0) { +} + +GrowingArrayByteSink::~GrowingArrayByteSink() { + delete[] buf_; // Just in case the user didn't call GetBuffer. +} + +void GrowingArrayByteSink::Append(const char* bytes, size_t n) { + size_t available = capacity_ - size_; + if (bytes != (buf_ + size_)) { + // Catch cases where the pointer returned by GetAppendBuffer() was modified. + // We need to test for this before calling Expand() which may reallocate. + GOOGLE_DCHECK(!(buf_ <= bytes && bytes < (buf_ + capacity_))) + << "Append() bytes[] overlaps with buf_[]"; + } + if (n > available) { + Expand(n - available); + } + if (n > 0 && bytes != (buf_ + size_)) { + memcpy(buf_ + size_, bytes, n); + } + size_ += n; +} + +char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) { + ShrinkToFit(); + char* b = buf_; + *nbytes = size_; + buf_ = NULL; + size_ = capacity_ = 0; + return b; +} + +void GrowingArrayByteSink::Expand(size_t amount) { // Expand by at least 50%. + size_t new_capacity = std::max(capacity_ + amount, (3 * capacity_) / 2); + char* bigger = new char[new_capacity]; + memcpy(bigger, buf_, size_); + delete[] buf_; + buf_ = bigger; + capacity_ = new_capacity; +} + +void GrowingArrayByteSink::ShrinkToFit() { + // Shrink only if the buffer is large and size_ is less than 3/4 + // of capacity_. + if (capacity_ > 256 && size_ < (3 * capacity_) / 4) { + char* just_enough = new char[size_]; + memcpy(just_enough, buf_, size_); + delete[] buf_; + buf_ = just_enough; + capacity_ = size_; + } +} + +void StringByteSink::Append(const char* data, size_t n) { + dest_->append(data, n); +} + +size_t ArrayByteSource::Available() const { + return input_.size(); +} + +StringPiece ArrayByteSource::Peek() { + return input_; +} + +void ArrayByteSource::Skip(size_t n) { + GOOGLE_DCHECK_LE(n, input_.size()); + input_.remove_prefix(n); +} + +LimitByteSource::LimitByteSource(ByteSource *source, size_t limit) + : source_(source), + limit_(limit) { +} + +size_t LimitByteSource::Available() const { + size_t available = source_->Available(); + if (available > limit_) { + available = limit_; + } + + return available; +} + +StringPiece LimitByteSource::Peek() { + StringPiece piece(source_->Peek()); + if (piece.size() > limit_) { + piece.set(piece.data(), limit_); + } + + return piece; +} + +void LimitByteSource::Skip(size_t n) { + GOOGLE_DCHECK_LE(n, limit_); + source_->Skip(n); + limit_ -= n; +} + +void LimitByteSource::CopyTo(ByteSink *sink, size_t n) { + GOOGLE_DCHECK_LE(n, limit_); + source_->CopyTo(sink, n); + limit_ -= n; +} + +} // namespace strings +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/bytestream.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/bytestream.h new file mode 100644 index 000000000..86510d140 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/bytestream.h @@ -0,0 +1,348 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// This file declares the ByteSink and ByteSource abstract interfaces. These +// interfaces represent objects that consume (ByteSink) or produce (ByteSource) +// a sequence of bytes. Using these abstract interfaces in your APIs can help +// make your code work with a variety of input and output types. +// +// This file also declares the following commonly used implementations of these +// interfaces. +// +// ByteSink: +// UncheckedArrayByteSink Writes to an array, without bounds checking +// CheckedArrayByteSink Writes to an array, with bounds checking +// GrowingArrayByteSink Allocates and writes to a growable buffer +// StringByteSink Writes to an STL string +// NullByteSink Consumes a never-ending stream of bytes +// +// ByteSource: +// ArrayByteSource Reads from an array or string/StringPiece +// LimitedByteSource Limits the number of bytes read from an + +#ifndef GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ +#define GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ + +#include +#include + +#include +#include + +class CordByteSink; +class MemBlock; + +namespace google { +namespace protobuf { +namespace strings { + +// An abstract interface for an object that consumes a sequence of bytes. This +// interface offers a way to append data as well as a Flush() function. +// +// Example: +// +// string my_data; +// ... +// ByteSink* sink = ... +// sink->Append(my_data.data(), my_data.size()); +// sink->Flush(); +// +class LIBPROTOBUF_EXPORT ByteSink { + public: + ByteSink() {} + virtual ~ByteSink() {} + + // Appends the "n" bytes starting at "bytes". + virtual void Append(const char* bytes, size_t n) = 0; + + // Flushes internal buffers. The default implemenation does nothing. ByteSink + // subclasses may use internal buffers that require calling Flush() at the end + // of the stream. + virtual void Flush(); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSink); +}; + +// An abstract interface for an object that produces a fixed-size sequence of +// bytes. +// +// Example: +// +// ByteSource* source = ... +// while (source->Available() > 0) { +// StringPiece data = source->Peek(); +// ... do something with "data" ... +// source->Skip(data.length()); +// } +// +class LIBPROTOBUF_EXPORT ByteSource { + public: + ByteSource() {} + virtual ~ByteSource() {} + + // Returns the number of bytes left to read from the source. Available() + // should decrease by N each time Skip(N) is called. Available() may not + // increase. Available() returning 0 indicates that the ByteSource is + // exhausted. + // + // Note: Size() may have been a more appropriate name as it's more + // indicative of the fixed-size nature of a ByteSource. + virtual size_t Available() const = 0; + + // Returns a StringPiece of the next contiguous region of the source. Does not + // reposition the source. The returned region is empty iff Available() == 0. + // + // The returned region is valid until the next call to Skip() or until this + // object is destroyed, whichever occurs first. + // + // The length of the returned StringPiece will be <= Available(). + virtual StringPiece Peek() = 0; + + // Skips the next n bytes. Invalidates any StringPiece returned by a previous + // call to Peek(). + // + // REQUIRES: Available() >= n + virtual void Skip(size_t n) = 0; + + // Writes the next n bytes in this ByteSource to the given ByteSink, and + // advances this ByteSource past the copied bytes. The default implementation + // of this method just copies the bytes normally, but subclasses might + // override CopyTo to optimize certain cases. + // + // REQUIRES: Available() >= n + virtual void CopyTo(ByteSink* sink, size_t n); + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource); +}; + +// +// Some commonly used implementations of ByteSink +// + +// Implementation of ByteSink that writes to an unsized byte array. No +// bounds-checking is performed--it is the caller's responsibility to ensure +// that the destination array is large enough. +// +// Example: +// +// char buf[10]; +// UncheckedArrayByteSink sink(buf); +// sink.Append("hi", 2); // OK +// sink.Append(data, 100); // WOOPS! Overflows buf[10]. +// +class LIBPROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink { + public: + explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {} + virtual void Append(const char* data, size_t n); + + // Returns the current output pointer so that a caller can see how many bytes + // were produced. + // + // Note: this method is not part of the ByteSink interface. + char* CurrentDestination() const { return dest_; } + + private: + char* dest_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink); +}; + +// Implementation of ByteSink that writes to a sized byte array. This sink will +// not write more than "capacity" bytes to outbuf. Once "capacity" bytes are +// appended, subsequent bytes will be ignored and Overflowed() will return true. +// Overflowed() does not cause a runtime error (i.e., it does not CHECK fail). +// +// Example: +// +// char buf[10]; +// CheckedArrayByteSink sink(buf, 10); +// sink.Append("hi", 2); // OK +// sink.Append(data, 100); // Will only write 8 more bytes +// +class LIBPROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink { + public: + CheckedArrayByteSink(char* outbuf, size_t capacity); + virtual void Append(const char* bytes, size_t n); + + // Returns the number of bytes actually written to the sink. + size_t NumberOfBytesWritten() const { return size_; } + + // Returns true if any bytes were discarded, i.e., if there was an + // attempt to write more than 'capacity' bytes. + bool Overflowed() const { return overflowed_; } + + private: + char* outbuf_; + const size_t capacity_; + size_t size_; + bool overflowed_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CheckedArrayByteSink); +}; + +// Implementation of ByteSink that allocates an internal buffer (a char array) +// and expands it as needed to accommodate appended data (similar to a string), +// and allows the caller to take ownership of the internal buffer via the +// GetBuffer() method. The buffer returned from GetBuffer() must be deleted by +// the caller with delete[]. GetBuffer() also sets the internal buffer to be +// empty, and subsequent appends to the sink will create a new buffer. The +// destructor will free the internal buffer if GetBuffer() was not called. +// +// Example: +// +// GrowingArrayByteSink sink(10); +// sink.Append("hi", 2); +// sink.Append(data, n); +// const char* buf = sink.GetBuffer(); // Ownership transferred +// delete[] buf; +// +class LIBPROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink { + public: + explicit GrowingArrayByteSink(size_t estimated_size); + virtual ~GrowingArrayByteSink(); + virtual void Append(const char* bytes, size_t n); + + // Returns the allocated buffer, and sets nbytes to its size. The caller takes + // ownership of the buffer and must delete it with delete[]. + char* GetBuffer(size_t* nbytes); + + private: + void Expand(size_t amount); + void ShrinkToFit(); + + size_t capacity_; + char* buf_; + size_t size_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink); +}; + +// Implementation of ByteSink that appends to the given string. +// Existing contents of "dest" are not modified; new data is appended. +// +// Example: +// +// string dest = "Hello "; +// StringByteSink sink(&dest); +// sink.Append("World", 5); +// assert(dest == "Hello World"); +// +class LIBPROTOBUF_EXPORT StringByteSink : public ByteSink { + public: + explicit StringByteSink(string* dest) : dest_(dest) {} + virtual void Append(const char* data, size_t n); + + private: + string* dest_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink); +}; + +// Implementation of ByteSink that discards all data. +// +// Example: +// +// NullByteSink sink; +// sink.Append(data, data.size()); // All data ignored. +// +class LIBPROTOBUF_EXPORT NullByteSink : public ByteSink { + public: + NullByteSink() {} + virtual void Append(const char *data, size_t n) {} + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink); +}; + +// +// Some commonly used implementations of ByteSource +// + +// Implementation of ByteSource that reads from a StringPiece. +// +// Example: +// +// string data = "Hello"; +// ArrayByteSource source(data); +// assert(source.Available() == 5); +// assert(source.Peek() == "Hello"); +// +class LIBPROTOBUF_EXPORT ArrayByteSource : public ByteSource { + public: + explicit ArrayByteSource(StringPiece s) : input_(s) {} + + virtual size_t Available() const; + virtual StringPiece Peek(); + virtual void Skip(size_t n); + + private: + StringPiece input_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource); +}; + +// Implementation of ByteSource that wraps another ByteSource, limiting the +// number of bytes returned. +// +// The caller maintains ownership of the underlying source, and may not use the +// underlying source while using the LimitByteSource object. The underlying +// source's pointer is advanced by n bytes every time this LimitByteSource +// object is advanced by n. +// +// Example: +// +// string data = "Hello World"; +// ArrayByteSource abs(data); +// assert(abs.Available() == data.size()); +// +// LimitByteSource limit(abs, 5); +// assert(limit.Available() == 5); +// assert(limit.Peek() == "Hello"); +// +class LIBPROTOBUF_EXPORT LimitByteSource : public ByteSource { + public: + // Returns at most "limit" bytes from "source". + LimitByteSource(ByteSource* source, size_t limit); + + virtual size_t Available() const; + virtual StringPiece Peek(); + virtual void Skip(size_t n); + + // We override CopyTo so that we can forward to the underlying source, in + // case it has an efficient implementation of CopyTo. + virtual void CopyTo(ByteSink* sink, size_t n); + + private: + ByteSource* source_; + size_t limit_; +}; + +} // namespace strings +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/bytestream_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/bytestream_unittest.cc new file mode 100644 index 000000000..06f114abc --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/bytestream_unittest.cc @@ -0,0 +1,146 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace strings { +namespace { + +// We use this class instead of ArrayByteSource to simulate a ByteSource that +// contains multiple fragments. ArrayByteSource returns the entire array in +// one fragment. +class MockByteSource : public ByteSource { + public: + MockByteSource(StringPiece data, int block_size) + : data_(data), block_size_(block_size) {} + + size_t Available() const { return data_.size(); } + StringPiece Peek() { + return data_.substr(0, block_size_); + } + void Skip(size_t n) { data_.remove_prefix(n); } + + private: + StringPiece data_; + int block_size_; +}; + +TEST(ByteSourceTest, CopyTo) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + string str; + StringByteSink sink(&str); + + source.CopyTo(&sink, data.size()); + EXPECT_EQ(data, str); +} + +TEST(ByteSourceTest, CopySubstringTo) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + source.Skip(1); + string str; + StringByteSink sink(&str); + + source.CopyTo(&sink, data.size() - 2); + EXPECT_EQ(data.substr(1, data.size() - 2), str); + EXPECT_EQ("!", source.Peek()); +} + +TEST(ByteSourceTest, LimitByteSource) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + LimitByteSource limit_source(&source, 6); + EXPECT_EQ(6, limit_source.Available()); + limit_source.Skip(1); + EXPECT_EQ(5, limit_source.Available()); + + { + string str; + StringByteSink sink(&str); + limit_source.CopyTo(&sink, limit_source.Available()); + EXPECT_EQ("ello ", str); + EXPECT_EQ(0, limit_source.Available()); + EXPECT_EQ(6, source.Available()); + } + + { + string str; + StringByteSink sink(&str); + source.CopyTo(&sink, source.Available()); + EXPECT_EQ("world!", str); + EXPECT_EQ(0, source.Available()); + } +} + +TEST(ByteSourceTest, CopyToStringByteSink) { + StringPiece data("Hello world!"); + MockByteSource source(data, 3); + string str; + StringByteSink sink(&str); + source.CopyTo(&sink, data.size()); + EXPECT_EQ(data, str); +} + +// Verify that ByteSink is subclassable and Flush() overridable. +class FlushingByteSink : public StringByteSink { + public: + explicit FlushingByteSink(string* dest) : StringByteSink(dest) {} + virtual void Flush() { Append("z", 1); } + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FlushingByteSink); +}; + +// Write and Flush via the ByteSink superclass interface. +void WriteAndFlush(ByteSink* s) { + s->Append("abc", 3); + s->Flush(); +} + +TEST(ByteSinkTest, Flush) { + string str; + FlushingByteSink f_sink(&str); + WriteAndFlush(&f_sink); + EXPECT_STREQ("abcz", str.c_str()); +} + +} // namespace +} // namespace strings +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/callback.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/callback.h new file mode 100644 index 000000000..6888f136d --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/callback.h @@ -0,0 +1,577 @@ +#ifndef GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ +#define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ + +#include + +#include + +// =================================================================== +// emulates google3/base/callback.h + +namespace google { +namespace protobuf { + +// Abstract interface for a callback. When calling an RPC, you must provide +// a Closure to call when the procedure completes. See the Service interface +// in service.h. +// +// To automatically construct a Closure which calls a particular function or +// method with a particular set of parameters, use the NewCallback() function. +// Example: +// void FooDone(const FooResponse* response) { +// ... +// } +// +// void CallFoo() { +// ... +// // When done, call FooDone() and pass it a pointer to the response. +// Closure* callback = NewCallback(&FooDone, response); +// // Make the call. +// service->Foo(controller, request, response, callback); +// } +// +// Example that calls a method: +// class Handler { +// public: +// ... +// +// void FooDone(const FooResponse* response) { +// ... +// } +// +// void CallFoo() { +// ... +// // When done, call FooDone() and pass it a pointer to the response. +// Closure* callback = NewCallback(this, &Handler::FooDone, response); +// // Make the call. +// service->Foo(controller, request, response, callback); +// } +// }; +// +// Currently NewCallback() supports binding zero, one, or two arguments. +// +// Callbacks created with NewCallback() automatically delete themselves when +// executed. They should be used when a callback is to be called exactly +// once (usually the case with RPC callbacks). If a callback may be called +// a different number of times (including zero), create it with +// NewPermanentCallback() instead. You are then responsible for deleting the +// callback (using the "delete" keyword as normal). +// +// Note that NewCallback() is a bit touchy regarding argument types. Generally, +// the values you provide for the parameter bindings must exactly match the +// types accepted by the callback function. For example: +// void Foo(string s); +// NewCallback(&Foo, "foo"); // WON'T WORK: const char* != string +// NewCallback(&Foo, string("foo")); // WORKS +// Also note that the arguments cannot be references: +// void Foo(const string& s); +// string my_str; +// NewCallback(&Foo, my_str); // WON'T WORK: Can't use referecnes. +// However, correctly-typed pointers will work just fine. +class LIBPROTOBUF_EXPORT Closure { + public: + Closure() {} + virtual ~Closure(); + + virtual void Run() = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure); +}; + +template +class ResultCallback { + public: + ResultCallback() {} + virtual ~ResultCallback() {} + + virtual R Run() = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback); +}; + +template +class LIBPROTOBUF_EXPORT ResultCallback1 { + public: + ResultCallback1() {} + virtual ~ResultCallback1() {} + + virtual R Run(A1) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1); +}; + +template +class LIBPROTOBUF_EXPORT ResultCallback2 { + public: + ResultCallback2() {} + virtual ~ResultCallback2() {} + + virtual R Run(A1,A2) = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2); +}; + +namespace internal { + +class LIBPROTOBUF_EXPORT FunctionClosure0 : public Closure { + public: + typedef void (*FunctionType)(); + + FunctionClosure0(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionClosure0(); + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + function_(); + if (needs_delete) delete this; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template +class MethodClosure0 : public Closure { + public: + typedef void (Class::*MethodType)(); + + MethodClosure0(Class* object, MethodType method, bool self_deleting) + : object_(object), method_(method), self_deleting_(self_deleting) {} + ~MethodClosure0() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + (object_->*method_)(); + if (needs_delete) delete this; + } + + private: + Class* object_; + MethodType method_; + bool self_deleting_; +}; + +template +class FunctionClosure1 : public Closure { + public: + typedef void (*FunctionType)(Arg1 arg1); + + FunctionClosure1(FunctionType function, bool self_deleting, + Arg1 arg1) + : function_(function), self_deleting_(self_deleting), + arg1_(arg1) {} + ~FunctionClosure1() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + function_(arg1_); + if (needs_delete) delete this; + } + + private: + FunctionType function_; + bool self_deleting_; + Arg1 arg1_; +}; + +template +class MethodClosure1 : public Closure { + public: + typedef void (Class::*MethodType)(Arg1 arg1); + + MethodClosure1(Class* object, MethodType method, bool self_deleting, + Arg1 arg1) + : object_(object), method_(method), self_deleting_(self_deleting), + arg1_(arg1) {} + ~MethodClosure1() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + (object_->*method_)(arg1_); + if (needs_delete) delete this; + } + + private: + Class* object_; + MethodType method_; + bool self_deleting_; + Arg1 arg1_; +}; + +template +class FunctionClosure2 : public Closure { + public: + typedef void (*FunctionType)(Arg1 arg1, Arg2 arg2); + + FunctionClosure2(FunctionType function, bool self_deleting, + Arg1 arg1, Arg2 arg2) + : function_(function), self_deleting_(self_deleting), + arg1_(arg1), arg2_(arg2) {} + ~FunctionClosure2() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + function_(arg1_, arg2_); + if (needs_delete) delete this; + } + + private: + FunctionType function_; + bool self_deleting_; + Arg1 arg1_; + Arg2 arg2_; +}; + +template +class MethodClosure2 : public Closure { + public: + typedef void (Class::*MethodType)(Arg1 arg1, Arg2 arg2); + + MethodClosure2(Class* object, MethodType method, bool self_deleting, + Arg1 arg1, Arg2 arg2) + : object_(object), method_(method), self_deleting_(self_deleting), + arg1_(arg1), arg2_(arg2) {} + ~MethodClosure2() {} + + void Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + (object_->*method_)(arg1_, arg2_); + if (needs_delete) delete this; + } + + private: + Class* object_; + MethodType method_; + bool self_deleting_; + Arg1 arg1_; + Arg2 arg2_; +}; + +template +class FunctionResultCallback_0_0 : public ResultCallback { + public: + typedef R (*FunctionType)(); + + FunctionResultCallback_0_0(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionResultCallback_0_0() {} + + R Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template +class FunctionResultCallback_1_0 : public ResultCallback { + public: + typedef R (*FunctionType)(P1); + + FunctionResultCallback_1_0(FunctionType function, bool self_deleting, + P1 p1) + : function_(function), self_deleting_(self_deleting), p1_(p1) {} + ~FunctionResultCallback_1_0() {} + + R Run() { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(p1_); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; + P1 p1_; +}; + +template +class FunctionResultCallback_0_1 : public ResultCallback1 { + public: + typedef R (*FunctionType)(Arg1 arg1); + + FunctionResultCallback_0_1(FunctionType function, bool self_deleting) + : function_(function), self_deleting_(self_deleting) {} + ~FunctionResultCallback_0_1() {} + + R Run(Arg1 a1) { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; +}; + +template +class FunctionResultCallback_1_1 : public ResultCallback1 { + public: + typedef R (*FunctionType)(P1, A1); + + FunctionResultCallback_1_1(FunctionType function, bool self_deleting, + P1 p1) + : function_(function), self_deleting_(self_deleting), p1_(p1) {} + ~FunctionResultCallback_1_1() {} + + R Run(A1 a1) { + bool needs_delete = self_deleting_; // read in case callback deletes + R result = function_(p1_, a1); + if (needs_delete) delete this; + return result; + } + + private: + FunctionType function_; + bool self_deleting_; + P1 p1_; +}; + +template +struct InternalConstRef { + typedef typename std::remove_reference::type base_type; + typedef const base_type& type; +}; + +template +class MethodResultCallback_0_0 : public ResultCallback { + public: + typedef R (T::*MethodType)(); + MethodResultCallback_0_0(T* object, MethodType method, bool self_deleting) + : object_(object), + method_(method), + self_deleting_(self_deleting) {} + ~MethodResultCallback_0_0() {} + + R Run() { + bool needs_delete = self_deleting_; + R result = (object_->*method_)(); + if (needs_delete) delete this; + return result; + } + + private: + T* object_; + MethodType method_; + bool self_deleting_; +}; + +template +class MethodResultCallback_5_2 : public ResultCallback2 { + public: + typedef R (T::*MethodType)(P1, P2, P3, P4, P5, A1, A2); + MethodResultCallback_5_2(T* object, MethodType method, bool self_deleting, + P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) + : object_(object), + method_(method), + self_deleting_(self_deleting), + p1_(p1), + p2_(p2), + p3_(p3), + p4_(p4), + p5_(p5) {} + ~MethodResultCallback_5_2() {} + + R Run(A1 a1, A2 a2) { + bool needs_delete = self_deleting_; + R result = (object_->*method_)(p1_, p2_, p3_, p4_, p5_, a1, a2); + if (needs_delete) delete this; + return result; + } + + private: + T* object_; + MethodType method_; + bool self_deleting_; + typename std::remove_reference::type p1_; + typename std::remove_reference::type p2_; + typename std::remove_reference::type p3_; + typename std::remove_reference::type p4_; + typename std::remove_reference::type p5_; +}; + +} // namespace internal + +// See Closure. +inline Closure* NewCallback(void (*function)()) { + return new internal::FunctionClosure0(function, true); +} + +// See Closure. +inline Closure* NewPermanentCallback(void (*function)()) { + return new internal::FunctionClosure0(function, false); +} + +// See Closure. +template +inline Closure* NewCallback(Class* object, void (Class::*method)()) { + return new internal::MethodClosure0(object, method, true); +} + +// See Closure. +template +inline Closure* NewPermanentCallback(Class* object, void (Class::*method)()) { + return new internal::MethodClosure0(object, method, false); +} + +// See Closure. +template +inline Closure* NewCallback(void (*function)(Arg1), + Arg1 arg1) { + return new internal::FunctionClosure1(function, true, arg1); +} + +// See Closure. +template +inline Closure* NewPermanentCallback(void (*function)(Arg1), + Arg1 arg1) { + return new internal::FunctionClosure1(function, false, arg1); +} + +// See Closure. +template +inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1), + Arg1 arg1) { + return new internal::MethodClosure1(object, method, true, arg1); +} + +// See Closure. +template +inline Closure* NewPermanentCallback(Class* object, void (Class::*method)(Arg1), + Arg1 arg1) { + return new internal::MethodClosure1(object, method, false, arg1); +} + +// See Closure. +template +inline Closure* NewCallback(void (*function)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::FunctionClosure2( + function, true, arg1, arg2); +} + +// See Closure. +template +inline Closure* NewPermanentCallback(void (*function)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::FunctionClosure2( + function, false, arg1, arg2); +} + +// See Closure. +template +inline Closure* NewCallback(Class* object, void (Class::*method)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::MethodClosure2( + object, method, true, arg1, arg2); +} + +// See Closure. +template +inline Closure* NewPermanentCallback( + Class* object, void (Class::*method)(Arg1, Arg2), + Arg1 arg1, Arg2 arg2) { + return new internal::MethodClosure2( + object, method, false, arg1, arg2); +} + +// See ResultCallback +template +inline ResultCallback* NewCallback(R (*function)()) { + return new internal::FunctionResultCallback_0_0(function, true); +} + +// See ResultCallback +template +inline ResultCallback* NewPermanentCallback(R (*function)()) { + return new internal::FunctionResultCallback_0_0(function, false); +} + +// See ResultCallback +template +inline ResultCallback* NewCallback(R (*function)(P1), P1 p1) { + return new internal::FunctionResultCallback_1_0( + function, true, p1); +} + +// See ResultCallback +template +inline ResultCallback* NewPermanentCallback( + R (*function)(P1), P1 p1) { + return new internal::FunctionResultCallback_1_0( + function, false, p1); +} + +// See ResultCallback1 +template +inline ResultCallback1* NewCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1(function, true); +} + +// See ResultCallback1 +template +inline ResultCallback1* NewPermanentCallback(R (*function)(A1)) { + return new internal::FunctionResultCallback_0_1(function, false); +} + +// See ResultCallback1 +template +inline ResultCallback1* NewCallback(R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1( + function, true, p1); +} + +// See ResultCallback1 +template +inline ResultCallback1* NewPermanentCallback( + R (*function)(P1, A1), P1 p1) { + return new internal::FunctionResultCallback_1_1( + function, false, p1); +} + +// See MethodResultCallback_0_0 +template +inline ResultCallback* NewPermanentCallback( + T1* object, R (T2::*function)()) { + return new internal::MethodResultCallback_0_0(object, function, false); +} + +// See MethodResultCallback_5_2 +template +inline ResultCallback2* NewPermanentCallback( + T* object, R (T::*function)(P1, P2, P3, P4, P5, A1, A2), + typename internal::InternalConstRef::type p1, + typename internal::InternalConstRef::type p2, + typename internal::InternalConstRef::type p3, + typename internal::InternalConstRef::type p4, + typename internal::InternalConstRef::type p5) { + return new internal::MethodResultCallback_5_2(object, function, false, p1, + p2, p3, p4, p5); +} + +// A function which does nothing. Useful for creating no-op callbacks, e.g.: +// Closure* nothing = NewCallback(&DoNothing); +void LIBPROTOBUF_EXPORT DoNothing(); + + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/casts.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/casts.h new file mode 100644 index 000000000..35e2dba05 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/casts.h @@ -0,0 +1,134 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +#ifndef GOOGLE_PROTOBUF_CASTS_H__ +#define GOOGLE_PROTOBUF_CASTS_H__ + +#include + +#include + +namespace google { +namespace protobuf { +namespace internal { +// Use implicit_cast as a safe version of static_cast or const_cast +// for upcasting in the type hierarchy (i.e. casting a pointer to Foo +// to a pointer to SuperclassOfFoo or casting a pointer to Foo to +// a const pointer to Foo). +// When you use implicit_cast, the compiler checks that the cast is safe. +// Such explicit implicit_casts are necessary in surprisingly many +// situations where C++ demands an exact type match instead of an +// argument type convertable to a target type. +// +// The From type can be inferred, so the preferred syntax for using +// implicit_cast is the same as for static_cast etc.: +// +// implicit_cast(expr) +// +// implicit_cast would have been part of the C++ standard library, +// but the proposal was submitted too late. It will probably make +// its way into the language in the future. +template +inline To implicit_cast(From const &f) { + return f; +} + +// When you upcast (that is, cast a pointer from type Foo to type +// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts +// always succeed. When you downcast (that is, cast a pointer from +// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because +// how do you know the pointer is really of type SubclassOfFoo? It +// could be a bare Foo, or of type DifferentSubclassOfFoo. Thus, +// when you downcast, you should use this macro. In debug mode, we +// use dynamic_cast<> to double-check the downcast is legal (we die +// if it's not). In normal mode, we do the efficient static_cast<> +// instead. Thus, it's important to test in debug mode to make sure +// the cast is legal! +// This is the only place in the code we should use dynamic_cast<>. +// In particular, you SHOULDN'T be using dynamic_cast<> in order to +// do RTTI (eg code like this: +// if (dynamic_cast(foo)) HandleASubclass1Object(foo); +// if (dynamic_cast(foo)) HandleASubclass2Object(foo); +// You should design the code some other way not to need this. + +template // use like this: down_cast(foo); +inline To down_cast(From* f) { // so we only accept pointers + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + implicit_cast(0); + } + +#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI) + assert(f == NULL || dynamic_cast(f) != NULL); // RTTI: debug mode only! +#endif + return static_cast(f); +} + +template // use like this: down_cast(foo); +inline To down_cast(From& f) { + typedef typename std::remove_reference::type* ToAsPointer; + // Ensures that To is a sub-type of From *. This test is here only + // for compile-time type checking, and has no overhead in an + // optimized build at run-time, as it will be optimized away + // completely. + if (false) { + implicit_cast(0); + } + +#if !defined(NDEBUG) && !defined(GOOGLE_PROTOBUF_NO_RTTI) + // RTTI: debug mode only! + assert(dynamic_cast(&f) != NULL); +#endif + return *static_cast(&f); +} + +template +inline To bit_cast(const From& from) { + GOOGLE_COMPILE_ASSERT(sizeof(From) == sizeof(To), + bit_cast_with_different_sizes); + To dest; + memcpy(&dest, &from, sizeof(dest)); + return dest; +} + +} // namespace internal + +// We made these internal so that they would show up as such in the docs, +// but we don't want to stick "internal::" in front of them everywhere. +using internal::implicit_cast; +using internal::down_cast; +using internal::bit_cast; + +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_CASTS_H__ diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/common.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/common.cc similarity index 73% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/common.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/common.cc index 1e02b2289..1329d3f46 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/common.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/common.cc @@ -30,14 +30,18 @@ // Author: kenton@google.com (Kenton Varda) +#include // TODO(gerbens) ideally remove this. #include #include -#include +#include +#include +#include +#include #include +#include +#include #include -#include "config.h" - #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN // We only need minimal includes #include @@ -47,6 +51,9 @@ #else #error "No suitable threading library available." #endif +#if defined(__ANDROID__) +#include +#endif namespace google { namespace protobuf { @@ -102,10 +109,55 @@ string VersionString(int version) { // =================================================================== // emulates google3/base/logging.cc +// If the minimum logging level is not set, we default to logging messages for +// all levels. +#ifndef GOOGLE_PROTOBUF_MIN_LOG_LEVEL +#define GOOGLE_PROTOBUF_MIN_LOG_LEVEL LOGLEVEL_INFO +#endif + namespace internal { +#if defined(__ANDROID__) +inline void DefaultLogHandler(LogLevel level, const char* filename, int line, + const string& message) { + if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { + return; + } + static const char* level_names[] = {"INFO", "WARNING", "ERROR", "FATAL"}; + + static const int android_log_levels[] = { + ANDROID_LOG_INFO, // LOG(INFO), + ANDROID_LOG_WARN, // LOG(WARNING) + ANDROID_LOG_ERROR, // LOG(ERROR) + ANDROID_LOG_FATAL, // LOG(FATAL) + }; + + // Bound the logging level. + const int android_log_level = android_log_levels[level]; + ::std::ostringstream ostr; + ostr << "[libprotobuf " << level_names[level] << " " << filename << ":" + << line << "] " << message.c_str(); + + // Output the log string the Android log at the appropriate level. + __android_log_write(android_log_level, "libprotobuf-native", + ostr.str().c_str()); + // Also output to std::cerr. + fprintf(stderr, "%s", ostr.str().c_str()); + fflush(stderr); + + // Indicate termination if needed. + if (android_log_level == ANDROID_LOG_FATAL) { + __android_log_write(ANDROID_LOG_FATAL, "libprotobuf-native", + "terminating.\n"); + } +} + +#else void DefaultLogHandler(LogLevel level, const char* filename, int line, const string& message) { + if (level < GOOGLE_PROTOBUF_MIN_LOG_LEVEL) { + return; + } static const char* level_names[] = { "INFO", "WARNING", "ERROR", "FATAL" }; // We use fprintf() instead of cerr because we want this to work at static @@ -114,6 +166,7 @@ void DefaultLogHandler(LogLevel level, const char* filename, int line, level_names[level], filename, line, message.c_str()); fflush(stderr); // Needed on MSVC. } +#endif void NullLogHandler(LogLevel /* level */, const char* /* filename */, int /* line */, const string& /* message */) { @@ -148,6 +201,24 @@ LogMessage& LogMessage::operator<<(const char* value) { return *this; } +LogMessage& LogMessage::operator<<(const StringPiece& value) { + message_ += value.ToString(); + return *this; +} + +LogMessage& LogMessage::operator<<( + const ::google::protobuf::util::Status& status) { + message_ += status.ToString(); + return *this; +} + +LogMessage& LogMessage::operator<<(const uint128& value) { + std::ostringstream str; + str << value; + message_ += str.str(); + return *this; +} + // Since this is just for logging, we don't care if the current locale changes // the results -- in fact, we probably prefer that. So we use snprintf() // instead of Simple*toa(). @@ -167,10 +238,13 @@ LogMessage& LogMessage::operator<<(const char* value) { DECLARE_STREAM_OPERATOR(char , "%c" ) DECLARE_STREAM_OPERATOR(int , "%d" ) -DECLARE_STREAM_OPERATOR(uint , "%u" ) +DECLARE_STREAM_OPERATOR(unsigned int , "%u" ) DECLARE_STREAM_OPERATOR(long , "%ld") DECLARE_STREAM_OPERATOR(unsigned long, "%lu") DECLARE_STREAM_OPERATOR(double , "%g" ) +DECLARE_STREAM_OPERATOR(void* , "%p" ) +DECLARE_STREAM_OPERATOR(long long , "%" GOOGLE_LL_FORMAT "d") +DECLARE_STREAM_OPERATOR(unsigned long long, "%" GOOGLE_LL_FORMAT "u") #undef DECLARE_STREAM_OPERATOR LogMessage::LogMessage(LogLevel level, const char* filename, int line) @@ -239,86 +313,6 @@ namespace internal { FunctionClosure0::~FunctionClosure0() {} } void DoNothing() {} -// =================================================================== -// emulates google3/base/mutex.cc - -#ifdef _WIN32 - -struct Mutex::Internal { - CRITICAL_SECTION mutex; -#ifndef NDEBUG - // Used only to implement AssertHeld(). - DWORD thread_id; -#endif -}; - -Mutex::Mutex() - : mInternal(new Internal) { - InitializeCriticalSection(&mInternal->mutex); -} - -Mutex::~Mutex() { - DeleteCriticalSection(&mInternal->mutex); - delete mInternal; -} - -void Mutex::Lock() { - EnterCriticalSection(&mInternal->mutex); -#ifndef NDEBUG - mInternal->thread_id = GetCurrentThreadId(); -#endif -} - -void Mutex::Unlock() { -#ifndef NDEBUG - mInternal->thread_id = 0; -#endif - LeaveCriticalSection(&mInternal->mutex); -} - -void Mutex::AssertHeld() { -#ifndef NDEBUG - GOOGLE_DCHECK_EQ(mInternal->thread_id, GetCurrentThreadId()); -#endif -} - -#elif defined(HAVE_PTHREAD) - -struct Mutex::Internal { - pthread_mutex_t mutex; -}; - -Mutex::Mutex() - : mInternal(new Internal) { - pthread_mutex_init(&mInternal->mutex, NULL); -} - -Mutex::~Mutex() { - pthread_mutex_destroy(&mInternal->mutex); - delete mInternal; -} - -void Mutex::Lock() { - int result = pthread_mutex_lock(&mInternal->mutex); - if (result != 0) { - GOOGLE_LOG(FATAL) << "pthread_mutex_lock: " << strerror(result); - } -} - -void Mutex::Unlock() { - int result = pthread_mutex_unlock(&mInternal->mutex); - if (result != 0) { - GOOGLE_LOG(FATAL) << "pthread_mutex_unlock: " << strerror(result); - } -} - -void Mutex::AssertHeld() { - // pthreads dosn't provide a way to check which thread holds the mutex. - // TODO(kenton): Maybe keep track of locking thread ID like with WIN32? -} - -#endif - // =================================================================== // emulates google3/util/endian/endian.h // @@ -343,44 +337,44 @@ uint32 ghtonl(uint32 x) { namespace internal { typedef void OnShutdownFunc(); -vector* shutdown_functions = NULL; -Mutex* shutdown_functions_mutex = NULL; -GOOGLE_PROTOBUF_DECLARE_ONCE(shutdown_functions_init); +struct ShutdownData { + ~ShutdownData() { + std::reverse(functions.begin(), functions.end()); + for (auto pair : functions) pair.first(pair.second); + } -void InitShutdownFunctions() { - shutdown_functions = new vector; - shutdown_functions_mutex = new Mutex; -} + static ShutdownData* get() { + static auto* data = new ShutdownData; + return data; + } -inline void InitShutdownFunctionsOnce() { - GoogleOnceInit(&shutdown_functions_init, &InitShutdownFunctions); + std::vector> functions; + Mutex mutex; +}; + +static void RunZeroArgFunc(const void* arg) { + (reinterpret_cast(const_cast(arg)))(); } void OnShutdown(void (*func)()) { - InitShutdownFunctionsOnce(); - MutexLock lock(shutdown_functions_mutex); - shutdown_functions->push_back(func); + OnShutdownRun(RunZeroArgFunc, reinterpret_cast(func)); +} + +void OnShutdownRun(void (*f)(const void*), const void* arg) { + auto shutdown_data = ShutdownData::get(); + MutexLock lock(&shutdown_data->mutex); + shutdown_data->functions.push_back(std::make_pair(f, arg)); } } // namespace internal void ShutdownProtobufLibrary() { - internal::InitShutdownFunctionsOnce(); - - // We don't need to lock shutdown_functions_mutex because it's up to the - // caller to make sure that no one is using the library before this is - // called. - - // Make it safe to call this multiple times. - if (internal::shutdown_functions == NULL) return; - - for (int i = 0; i < internal::shutdown_functions->size(); i++) { - internal::shutdown_functions->at(i)(); + // This function should be called only once, but accepts multiple calls. + static bool is_shutdown = false; + if (!is_shutdown) { + delete internal::ShutdownData::get(); + is_shutdown = true; } - delete internal::shutdown_functions; - internal::shutdown_functions = NULL; - delete internal::shutdown_functions_mutex; - internal::shutdown_functions_mutex = NULL; } #if PROTOBUF_USE_EXCEPTIONS diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/common.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/common.h new file mode 100644 index 000000000..d35377ae5 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/common.h @@ -0,0 +1,242 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: kenton@google.com (Kenton Varda) and others +// +// Contains basic types and utilities used by the rest of the library. + +#ifndef GOOGLE_PROTOBUF_COMMON_H__ +#define GOOGLE_PROTOBUF_COMMON_H__ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// TODO(liujisi): Remove the following includes after the include clean-up. +#include +#include +#include + +#ifndef PROTOBUF_USE_EXCEPTIONS +#if defined(_MSC_VER) && defined(_CPPUNWIND) + #define PROTOBUF_USE_EXCEPTIONS 1 +#elif defined(__EXCEPTIONS) + #define PROTOBUF_USE_EXCEPTIONS 1 +#else + #define PROTOBUF_USE_EXCEPTIONS 0 +#endif +#endif + +#if PROTOBUF_USE_EXCEPTIONS +#include +#endif +#if defined(__APPLE__) +#include // for TARGET_OS_IPHONE +#endif + +#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE) +#include +#endif + +#if defined(_WIN32) && defined(GetMessage) +// Allow GetMessage to be used as a valid method name in protobuf classes. +// windows.h defines GetMessage() as a macro. Let's re-define it as an inline +// function. The inline function should be equivalent for C++ users. +inline BOOL GetMessage_Win32( + LPMSG lpMsg, HWND hWnd, + UINT wMsgFilterMin, UINT wMsgFilterMax) { + return GetMessage(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); +} +#undef GetMessage +inline BOOL GetMessage( + LPMSG lpMsg, HWND hWnd, + UINT wMsgFilterMin, UINT wMsgFilterMax) { + return GetMessage_Win32(lpMsg, hWnd, wMsgFilterMin, wMsgFilterMax); +} +#endif + +namespace std {} + +namespace google { +namespace protobuf { +namespace internal { + +// Some of these constants are macros rather than const ints so that they can +// be used in #if directives. + +// The current version, represented as a single integer to make comparison +// easier: major * 10^6 + minor * 10^3 + micro +#define GOOGLE_PROTOBUF_VERSION 3006001 + +// A suffix string for alpha, beta or rc releases. Empty for stable releases. +#define GOOGLE_PROTOBUF_VERSION_SUFFIX "" + +// The minimum library version which works with the current version of the +// headers. +#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION 3006001 + +// The minimum header version which works with the current version of +// the library. This constant should only be used by protoc's C++ code +// generator. +static const int kMinHeaderVersionForLibrary = 3006001; + +// The minimum protoc version which works with the current version of the +// headers. +#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION 3006001 + +// The minimum header version which works with the current version of +// protoc. This constant should only be used in VerifyVersion(). +static const int kMinHeaderVersionForProtoc = 3006001; + +// Verifies that the headers and libraries are compatible. Use the macro +// below to call this. +void LIBPROTOBUF_EXPORT VerifyVersion(int headerVersion, int minLibraryVersion, + const char* filename); + +// Converts a numeric version number to a string. +std::string LIBPROTOBUF_EXPORT VersionString(int version); + +} // namespace internal + +// Place this macro in your main() function (or somewhere before you attempt +// to use the protobuf library) to verify that the version you link against +// matches the headers you compiled against. If a version mismatch is +// detected, the process will abort. +#define GOOGLE_PROTOBUF_VERIFY_VERSION \ + ::google::protobuf::internal::VerifyVersion( \ + GOOGLE_PROTOBUF_VERSION, GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION, \ + __FILE__) + + +// =================================================================== +// from google3/util/utf8/public/unilib.h + +class StringPiece; +namespace internal { + +// Checks if the buffer contains structurally-valid UTF-8. Implemented in +// structurally_valid.cc. +LIBPROTOBUF_EXPORT bool IsStructurallyValidUTF8(const char* buf, int len); + +inline bool IsStructurallyValidUTF8(const std::string& str) { + return IsStructurallyValidUTF8(str.data(), static_cast(str.length())); +} + +// Returns initial number of bytes of structually valid UTF-8. +LIBPROTOBUF_EXPORT int UTF8SpnStructurallyValid(const StringPiece& str); + +// Coerce UTF-8 byte string in src_str to be +// a structurally-valid equal-length string by selectively +// overwriting illegal bytes with replace_char (typically ' ' or '?'). +// replace_char must be legal printable 7-bit Ascii 0x20..0x7e. +// src_str is read-only. +// +// Returns pointer to output buffer, src_str.data() if no changes were made, +// or idst if some bytes were changed. idst is allocated by the caller +// and must be at least as big as src_str +// +// Optimized for: all structurally valid and no byte copying is done. +// +LIBPROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid( + const StringPiece& str, char* dst, char replace_char); + +} // namespace internal + + +// =================================================================== +// Shutdown support. + +// Shut down the entire protocol buffers library, deleting all static-duration +// objects allocated by the library or by generated .pb.cc files. +// +// There are two reasons you might want to call this: +// * You use a draconian definition of "memory leak" in which you expect +// every single malloc() to have a corresponding free(), even for objects +// which live until program exit. +// * You are writing a dynamically-loaded library which needs to clean up +// after itself when the library is unloaded. +// +// It is safe to call this multiple times. However, it is not safe to use +// any other part of the protocol buffers library after +// ShutdownProtobufLibrary() has been called. Furthermore this call is not +// thread safe, user needs to synchronize multiple calls. +LIBPROTOBUF_EXPORT void ShutdownProtobufLibrary(); + +namespace internal { + +// Register a function to be called when ShutdownProtocolBuffers() is called. +LIBPROTOBUF_EXPORT void OnShutdown(void (*func)()); +// Run an arbitrary function on an arg +LIBPROTOBUF_EXPORT void OnShutdownRun(void (*f)(const void*), const void* arg); + +template +T* OnShutdownDelete(T* p) { + OnShutdownRun([](const void* p) { delete static_cast(p); }, p); + return p; +} + +} // namespace internal + +#if PROTOBUF_USE_EXCEPTIONS +class FatalException : public std::exception { + public: + FatalException(const char* filename, int line, const std::string& message) + : filename_(filename), line_(line), message_(message) {} + virtual ~FatalException() throw(); + + virtual const char* what() const throw(); + + const char* filename() const { return filename_; } + int line() const { return line_; } + const std::string& message() const { return message_; } + + private: + const char* filename_; + const int line_; + const std::string message_; +}; +#endif + +// This is at the end of the file instead of the beginning to work around a bug +// in some versions of MSVC. +using std::string; + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_COMMON_H__ diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/common_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/common_unittest.cc similarity index 94% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/common_unittest.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/common_unittest.cc index cb8920726..798a2a27f 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/common_unittest.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/common_unittest.cc @@ -31,6 +31,7 @@ // Author: kenton@google.com (Kenton Varda) #include +#include #include #include #include @@ -38,8 +39,6 @@ #include #include -#include "config.h" - namespace google { namespace protobuf { namespace { @@ -76,7 +75,7 @@ TEST(CommonTest, IntMinMaxConstants) { EXPECT_EQ(0, kuint64max + 1); } -vector captured_messages_; +std::vector captured_messages_; void CaptureLog(LogLevel level, const char* filename, int line, const string& message) { @@ -94,9 +93,9 @@ TEST(LoggingTest, DefaultLogging) { string text = GetCapturedTestStderr(); EXPECT_EQ( - "[libprotobuf INFO "__FILE__":" + SimpleItoa(line + 1) + "] A message.\n" - "[libprotobuf WARNING "__FILE__":" + SimpleItoa(line + 2) + "] A warning.\n" - "[libprotobuf ERROR "__FILE__":" + SimpleItoa(line + 3) + "] An error.\n", + "[libprotobuf INFO " __FILE__ ":" + SimpleItoa(line + 1) + "] A message.\n" + "[libprotobuf WARNING " __FILE__ ":" + SimpleItoa(line + 2) + "] A warning.\n" + "[libprotobuf ERROR " __FILE__ ":" + SimpleItoa(line + 3) + "] An error.\n", text); } @@ -127,10 +126,10 @@ TEST(LoggingTest, CaptureLogging) { ASSERT_EQ(2, captured_messages_.size()); EXPECT_EQ( - "2 "__FILE__":" + SimpleItoa(start_line + 1) + ": An error.", + "2 " __FILE__ ":" + SimpleItoa(start_line + 1) + ": An error.", captured_messages_[0]); EXPECT_EQ( - "1 "__FILE__":" + SimpleItoa(start_line + 2) + ": A warning.", + "1 " __FILE__ ":" + SimpleItoa(start_line + 2) + ": A warning.", captured_messages_[1]); } @@ -153,10 +152,10 @@ TEST(LoggingTest, SilenceLogging) { ASSERT_EQ(2, captured_messages_.size()); EXPECT_EQ( - "0 "__FILE__":" + SimpleItoa(line1) + ": Visible1", + "0 " __FILE__ ":" + SimpleItoa(line1) + ": Visible1", captured_messages_[0]); EXPECT_EQ( - "0 "__FILE__":" + SimpleItoa(line2) + ": Visible2", + "0 " __FILE__ ":" + SimpleItoa(line2) + ": Visible2", captured_messages_[1]); } diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/fastmem.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/fastmem.h new file mode 100644 index 000000000..1f1f6ed3d --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/fastmem.h @@ -0,0 +1,153 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2014 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Fast memory copying and comparison routines. +// strings::fastmemcmp_inlined() replaces memcmp() +// strings::memcpy_inlined() replaces memcpy() +// strings::memeq(a, b, n) replaces memcmp(a, b, n) == 0 +// +// strings::*_inlined() routines are inline versions of the +// routines exported by this module. Sometimes using the inlined +// versions is faster. Measure before using the inlined versions. +// +// Performance measurement: +// strings::fastmemcmp_inlined +// Analysis: memcmp, fastmemcmp_inlined, fastmemcmp +// 2012-01-30 + +#ifndef GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ +#define GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace internal { + +// Return true if the n bytes at a equal the n bytes at b. +// The regions are allowed to overlap. +// +// The performance is similar to the performance memcmp(), but faster for +// moderately-sized inputs, or inputs that share a common prefix and differ +// somewhere in their last 8 bytes. Further optimizations can be added later +// if it makes sense to do so.:w +inline bool memeq(const char* a, const char* b, size_t n) { + size_t n_rounded_down = n & ~static_cast(7); + if (GOOGLE_PREDICT_FALSE(n_rounded_down == 0)) { // n <= 7 + return memcmp(a, b, n) == 0; + } + // n >= 8 + uint64 u = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b); + uint64 v = GOOGLE_UNALIGNED_LOAD64(a + n - 8) ^ GOOGLE_UNALIGNED_LOAD64(b + n - 8); + if ((u | v) != 0) { // The first or last 8 bytes differ. + return false; + } + a += 8; + b += 8; + n = n_rounded_down - 8; + if (n > 128) { + // As of 2012, memcmp on x86-64 uses a big unrolled loop with SSE2 + // instructions, and while we could try to do something faster, it + // doesn't seem worth pursuing. + return memcmp(a, b, n) == 0; + } + for (; n >= 16; n -= 16) { + uint64 x = GOOGLE_UNALIGNED_LOAD64(a) ^ GOOGLE_UNALIGNED_LOAD64(b); + uint64 y = GOOGLE_UNALIGNED_LOAD64(a + 8) ^ GOOGLE_UNALIGNED_LOAD64(b + 8); + if ((x | y) != 0) { + return false; + } + a += 16; + b += 16; + } + // n must be 0 or 8 now because it was a multiple of 8 at the top of the loop. + return n == 0 || GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b); +} + +inline int fastmemcmp_inlined(const char *a, const char *b, size_t n) { + if (n >= 64) { + return memcmp(a, b, n); + } + const char* a_limit = a + n; + while (a + sizeof(uint64) <= a_limit && + GOOGLE_UNALIGNED_LOAD64(a) == GOOGLE_UNALIGNED_LOAD64(b)) { + a += sizeof(uint64); + b += sizeof(uint64); + } + if (a + sizeof(uint32) <= a_limit && + GOOGLE_UNALIGNED_LOAD32(a) == GOOGLE_UNALIGNED_LOAD32(b)) { + a += sizeof(uint32); + b += sizeof(uint32); + } + while (a < a_limit) { + int d = + static_cast(static_cast(*a++) - static_cast(*b++)); + if (d) return d; + } + return 0; +} + +// The standard memcpy operation is slow for variable small sizes. +// This implementation inlines the optimal realization for sizes 1 to 16. +// To avoid code bloat don't use it in case of not performance-critical spots, +// nor when you don't expect very frequent values of size <= 16. +inline void memcpy_inlined(char *dst, const char *src, size_t size) { + // Compiler inlines code with minimal amount of data movement when third + // parameter of memcpy is a constant. + switch (size) { + case 1: memcpy(dst, src, 1); break; + case 2: memcpy(dst, src, 2); break; + case 3: memcpy(dst, src, 3); break; + case 4: memcpy(dst, src, 4); break; + case 5: memcpy(dst, src, 5); break; + case 6: memcpy(dst, src, 6); break; + case 7: memcpy(dst, src, 7); break; + case 8: memcpy(dst, src, 8); break; + case 9: memcpy(dst, src, 9); break; + case 10: memcpy(dst, src, 10); break; + case 11: memcpy(dst, src, 11); break; + case 12: memcpy(dst, src, 12); break; + case 13: memcpy(dst, src, 13); break; + case 14: memcpy(dst, src, 14); break; + case 15: memcpy(dst, src, 15); break; + case 16: memcpy(dst, src, 16); break; + default: memcpy(dst, src, size); break; + } +} + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_FASTMEM_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/hash.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/hash.h new file mode 100644 index 000000000..fd8ba156a --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/hash.h @@ -0,0 +1,441 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: kenton@google.com (Kenton Varda) +// +// Deals with the fact that hash_map is not defined everywhere. + +#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__ +#define GOOGLE_PROTOBUF_STUBS_HASH_H__ + +#include +#include + +#define GOOGLE_PROTOBUF_HAVE_HASH_MAP 1 +#define GOOGLE_PROTOBUF_HAVE_HASH_SET 1 + +// Use C++11 unordered_{map|set} if available. +#if ((defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11) || \ + (((__cplusplus >= 201103L) || defined(__GXX_EXPERIMENTAL_CXX0X)) && \ + (__GLIBCXX__ > 20090421))) +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH + +// For XCode >= 4.6: the compiler is clang with libc++. +// For earlier XCode version: the compiler is gcc-4.2.1 with libstdc++. +// libc++ provides and friends even in non C++11 mode, +// and it does not provide the tr1 library. Therefore the following macro +// checks against this special case. +// Note that we should not test the __APPLE_CC__ version number or the +// __clang__ macro, since the new compiler can still use -stdlib=libstdc++, in +// which case is not compilable without -std=c++11 +#elif defined(__APPLE_CC__) +# if __GNUC__ >= 4 +# define GOOGLE_PROTOBUF_HAS_TR1 +# else +// Not tested for gcc < 4... These setting can compile under 4.2.1 though. +# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx +# include +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# endif + +// Version checks for gcc. +#elif defined(__GNUC__) +// For GCC 4.x+, use tr1::unordered_map/set; otherwise, follow the +// instructions from: +// https://gcc.gnu.org/onlinedocs/libstdc++/manual/backwards.html +# if __GNUC__ >= 4 +# define GOOGLE_PROTOBUF_HAS_TR1 +# elif __GNUC__ >= 3 +# include +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# if __GNUC__ == 3 && __GNUC_MINOR__ == 0 +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std // GCC 3.0 +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE __gnu_cxx // GCC 3.1 and later +# endif +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE +# include +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# endif + +// GCC <= 4.1 does not define std::tr1::hash for `long long int` or `long long unsigned int` +# if __GNUC__ == 4 && defined(__GNUC_MINOR__) && __GNUC_MINOR__ <= 1 +# undef GOOGLE_PROTOBUF_HAS_TR1 +# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP +# undef GOOGLE_PROTOBUF_HAVE_HASH_SET +# endif + +// Version checks for MSC. +// Apparently Microsoft decided to move hash_map *back* to the std namespace in +// MSVC 2010: +// http://blogs.msdn.com/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx +// And.. they are moved back to stdext in MSVC 2013 (haven't checked 2012). That +// said, use unordered_map for MSVC 2010 and beyond is our safest bet. +#elif defined(_MSC_VER) +# if _MSC_VER >= 1600 // Since Visual Studio 2010 +# define GOOGLE_PROTOBUF_HAS_CXX11_HASH +# define GOOGLE_PROTOBUF_HASH_COMPARE std::hash_compare +# elif _MSC_VER >= 1500 // Since Visual Studio 2008 +# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext +# include +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# define GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE +# elif _MSC_VER >= 1310 +# define GOOGLE_PROTOBUF_HASH_NAMESPACE stdext +# include +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# else +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std +# include +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS hash_map +# include +# define GOOGLE_PROTOBUF_HASH_SET_CLASS hash_set +# define GOOGLE_PROTOBUF_HASH_COMPARE stdext::hash_compare +# endif + +// **ADD NEW COMPILERS SUPPORT HERE.** +// For other compilers, undefine the macro and fallback to use std::map, in +// google/protobuf/stubs/hash.h +#else +# undef GOOGLE_PROTOBUF_HAVE_HASH_MAP +# undef GOOGLE_PROTOBUF_HAVE_HASH_SET +#endif + +#if defined(GOOGLE_PROTOBUF_HAS_CXX11_HASH) +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std +# include +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map +# include +# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#elif defined(GOOGLE_PROTOBUF_HAS_TR1) +# define GOOGLE_PROTOBUF_HASH_NAMESPACE std::tr1 +# include +# define GOOGLE_PROTOBUF_HASH_MAP_CLASS unordered_map +# include +# define GOOGLE_PROTOBUF_HASH_SET_CLASS unordered_set +#endif + +# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \ + namespace google { \ + namespace protobuf { +# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }} + +#undef GOOGLE_PROTOBUF_HAS_CXX11_HASH +#undef GOOGLE_PROTOBUF_HAS_TR1 + +#if defined(GOOGLE_PROTOBUF_HAVE_HASH_MAP) && \ + defined(GOOGLE_PROTOBUF_HAVE_HASH_SET) +#else +#define GOOGLE_PROTOBUF_MISSING_HASH +#include +#include +#endif + +namespace google { +namespace protobuf { + +#ifdef GOOGLE_PROTOBUF_MISSING_HASH +#undef GOOGLE_PROTOBUF_MISSING_HASH + +// This system doesn't have hash_map or hash_set. Emulate them using map and +// set. + +// Make hash be the same as less. Note that everywhere where custom +// hash functions are defined in the protobuf code, they are also defined such +// that they can be used as "less" functions, which is required by MSVC anyway. +template +struct hash { + // Dummy, just to make derivative hash functions compile. + int operator()(const Key& key) { + GOOGLE_LOG(FATAL) << "Should never be called."; + return 0; + } + + inline bool operator()(const Key& a, const Key& b) const { + return a < b; + } +}; + +// Make sure char* is compared by value. +template <> +struct hash { + // Dummy, just to make derivative hash functions compile. + int operator()(const char* key) { + GOOGLE_LOG(FATAL) << "Should never be called."; + return 0; + } + + inline bool operator()(const char* a, const char* b) const { + return strcmp(a, b) < 0; + } +}; + +template , + typename EqualKey = std::equal_to, + typename Alloc = std::allocator< std::pair > > +class hash_map : public std::map { + typedef std::map BaseClass; + + public: + hash_map(int a = 0, const HashFcn& b = HashFcn(), + const EqualKey& c = EqualKey(), + const Alloc& d = Alloc()) : BaseClass(b, d) {} + + HashFcn hash_function() const { return HashFcn(); } +}; + +template , + typename EqualKey = std::equal_to > +class hash_set : public std::set { + public: + hash_set(int = 0) {} + + HashFcn hash_function() const { return HashFcn(); } +}; + +#elif defined(_MSC_VER) && !defined(_STLPORT_VERSION) && \ + !(defined(_LIBCPP_STD_VER) && _LIBCPP_STD_VER >= 11) + +template +struct hash : public GOOGLE_PROTOBUF_HASH_COMPARE { +}; + +// MSVC's hash_compare hashes based on the string contents but +// compares based on the string pointer. WTF? +class CstringLess { + public: + inline bool operator()(const char* a, const char* b) const { + return strcmp(a, b) < 0; + } +}; + +template <> +struct hash + : public GOOGLE_PROTOBUF_HASH_COMPARE {}; + +#ifdef GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE + +template +struct InternalHashCompare : public GOOGLE_PROTOBUF_HASH_COMPARE { + InternalHashCompare() {} + InternalHashCompare(HashFcn hashfcn, EqualKey equalkey) + : hashfcn_(hashfcn), equalkey_(equalkey) {} + size_t operator()(const Key& key) const { return hashfcn_(key); } + bool operator()(const Key& key1, const Key& key2) const { + return !equalkey_(key1, key2); + } + HashFcn hashfcn_; + EqualKey equalkey_; +}; + +template , + typename EqualKey = std::equal_to, + typename Alloc = std::allocator< std::pair > > +class hash_map + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< + Key, Data, InternalHashCompare, Alloc> { + typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< + Key, Data, InternalHashCompare, Alloc> BaseClass; + + public: + hash_map(int a = 0, const HashFcn& b = HashFcn(), + const EqualKey& c = EqualKey(), const Alloc& d = Alloc()) + : BaseClass(InternalHashCompare(b, c), d) {} + + HashFcn hash_function() const { return HashFcn(); } +}; + +template , + typename EqualKey = std::equal_to > +class hash_set + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< + Key, InternalHashCompare > { + public: + hash_set(int = 0) {} + + HashFcn hash_function() const { return HashFcn(); } +}; + +#else // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE + +template , + typename EqualKey = std::equal_to, + typename Alloc = std::allocator< std::pair > > +class hash_map + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< + Key, Data, HashFcn, EqualKey, Alloc> { + typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< + Key, Data, HashFcn, EqualKey, Alloc> BaseClass; + + public: + hash_map(int a = 0, const HashFcn& b = HashFcn(), + const EqualKey& c = EqualKey(), + const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {} + + HashFcn hash_function() const { return HashFcn(); } +}; + +template , + typename EqualKey = std::equal_to > +class hash_set + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< + Key, HashFcn, EqualKey> { + public: + hash_set(int = 0) {} + + HashFcn hash_function() const { return HashFcn(); } +}; +#endif // GOOGLE_PROTOBUF_CONTAINERS_NEED_HASH_COMPARE + +#else // defined(_MSC_VER) && !defined(_STLPORT_VERSION) + +template +struct hash : public GOOGLE_PROTOBUF_HASH_NAMESPACE::hash { +}; + +template +struct hash { + inline size_t operator()(const Key* key) const { + return reinterpret_cast(key); + } +}; + +// Unlike the old SGI version, the TR1 "hash" does not special-case char*. So, +// we go ahead and provide our own implementation. +template <> +struct hash { + inline size_t operator()(const char* str) const { + size_t result = 0; + for (; *str != '\0'; str++) { + result = 5 * result + static_cast(*str); + } + return result; + } +}; + +template<> +struct hash { + size_t operator()(bool x) const { + return static_cast(x); + } +}; + +template , + typename EqualKey = std::equal_to, + typename Alloc = std::allocator< std::pair > > +class hash_map + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< + Key, Data, HashFcn, EqualKey, Alloc> { + typedef GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_MAP_CLASS< + Key, Data, HashFcn, EqualKey, Alloc> BaseClass; + + public: + hash_map(int a = 0, const HashFcn& b = HashFcn(), + const EqualKey& c = EqualKey(), + const Alloc& d = Alloc()) : BaseClass(a, b, c, d) {} + + HashFcn hash_function() const { return HashFcn(); } +}; + +template , + typename EqualKey = std::equal_to > +class hash_set + : public GOOGLE_PROTOBUF_HASH_NAMESPACE::GOOGLE_PROTOBUF_HASH_SET_CLASS< + Key, HashFcn, EqualKey> { + public: + hash_set(int = 0) {} + + HashFcn hash_function() const { return HashFcn(); } +}; + +#endif // !GOOGLE_PROTOBUF_MISSING_HASH + +template <> +struct hash { + inline size_t operator()(const string& key) const { + return hash()(key.c_str()); + } + + static const size_t bucket_size = 4; + static const size_t min_buckets = 8; + inline bool operator()(const string& a, const string& b) const { + return a < b; + } +}; + +template +struct hash > { + inline size_t operator()(const std::pair& key) const { + size_t first_hash = hash()(key.first); + size_t second_hash = hash()(key.second); + + // FIXME(kenton): What is the best way to compute this hash? I have + // no idea! This seems a bit better than an XOR. + return first_hash * ((1 << 16) - 1) + second_hash; + } + + static const size_t bucket_size = 4; + static const size_t min_buckets = 8; + inline bool operator()(const std::pair& a, + const std::pair& b) const { + return a < b; + } +}; + +// Used by GCC/SGI STL only. (Why isn't this provided by the standard +// library? :( ) +struct streq { + inline bool operator()(const char* a, const char* b) const { + return strcmp(a, b) == 0; + } +}; + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_HASH_H__ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/int128.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/int128.cc new file mode 100644 index 000000000..a50908014 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/int128.cc @@ -0,0 +1,201 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include +#include // NOLINT(readability/streams) +#include + +namespace google { +namespace protobuf { + +const uint128_pod kuint128max = { + static_cast(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF)), + static_cast(GOOGLE_LONGLONG(0xFFFFFFFFFFFFFFFF)) +}; + +// Returns the 0-based position of the last set bit (i.e., most significant bit) +// in the given uint64. The argument may not be 0. +// +// For example: +// Given: 5 (decimal) == 101 (binary) +// Returns: 2 +#define STEP(T, n, pos, sh) \ + do { \ + if ((n) >= (static_cast(1) << (sh))) { \ + (n) = (n) >> (sh); \ + (pos) |= (sh); \ + } \ + } while (0) +static inline int Fls64(uint64 n) { + GOOGLE_DCHECK_NE(0, n); + int pos = 0; + STEP(uint64, n, pos, 0x20); + uint32 n32 = n; + STEP(uint32, n32, pos, 0x10); + STEP(uint32, n32, pos, 0x08); + STEP(uint32, n32, pos, 0x04); + return pos + ((GOOGLE_ULONGLONG(0x3333333322221100) >> (n32 << 2)) & 0x3); +} +#undef STEP + +// Like Fls64() above, but returns the 0-based position of the last set bit +// (i.e., most significant bit) in the given uint128. The argument may not be 0. +static inline int Fls128(uint128 n) { + if (uint64 hi = Uint128High64(n)) { + return Fls64(hi) + 64; + } + return Fls64(Uint128Low64(n)); +} + +// Long division/modulo for uint128 implemented using the shift-subtract +// division algorithm adapted from: +// http://stackoverflow.com/questions/5386377/division-without-using +void uint128::DivModImpl(uint128 dividend, uint128 divisor, + uint128* quotient_ret, uint128* remainder_ret) { + if (divisor == 0) { + GOOGLE_LOG(FATAL) << "Division or mod by zero: dividend.hi=" << dividend.hi_ + << ", lo=" << dividend.lo_; + } + + if (divisor > dividend) { + *quotient_ret = 0; + *remainder_ret = dividend; + return; + } + + if (divisor == dividend) { + *quotient_ret = 1; + *remainder_ret = 0; + return; + } + + uint128 denominator = divisor; + uint128 position = 1; + uint128 quotient = 0; + + // Left aligns the MSB of the denominator and the dividend. + int shift = Fls128(dividend) - Fls128(denominator); + denominator <<= shift; + position <<= shift; + + // Uses shift-subtract algorithm to divide dividend by denominator. The + // remainder will be left in dividend. + while (position > 0) { + if (dividend >= denominator) { + dividend -= denominator; + quotient |= position; + } + position >>= 1; + denominator >>= 1; + } + + *quotient_ret = quotient; + *remainder_ret = dividend; +} + +uint128& uint128::operator/=(const uint128& divisor) { + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(*this, divisor, "ient, &remainder); + *this = quotient; + return *this; +} +uint128& uint128::operator%=(const uint128& divisor) { + uint128 quotient = 0; + uint128 remainder = 0; + DivModImpl(*this, divisor, "ient, &remainder); + *this = remainder; + return *this; +} + +std::ostream& operator<<(std::ostream& o, const uint128& b) { + std::ios_base::fmtflags flags = o.flags(); + + // Select a divisor which is the largest power of the base < 2^64. + uint128 div; + std::streamsize div_base_log; + switch (flags & std::ios::basefield) { + case std::ios::hex: + div = static_cast(GOOGLE_ULONGLONG(0x1000000000000000)); // 16^15 + div_base_log = 15; + break; + case std::ios::oct: + div = static_cast(GOOGLE_ULONGLONG(01000000000000000000000)); // 8^21 + div_base_log = 21; + break; + default: // std::ios::dec + div = static_cast(GOOGLE_ULONGLONG(10000000000000000000)); // 10^19 + div_base_log = 19; + break; + } + + // Now piece together the uint128 representation from three chunks of + // the original value, each less than "div" and therefore representable + // as a uint64. + std::ostringstream os; + std::ios_base::fmtflags copy_mask = + std::ios::basefield | std::ios::showbase | std::ios::uppercase; + os.setf(flags & copy_mask, copy_mask); + uint128 high = b; + uint128 low; + uint128::DivModImpl(high, div, &high, &low); + uint128 mid; + uint128::DivModImpl(high, div, &high, &mid); + if (high.lo_ != 0) { + os << high.lo_; + os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); + os << mid.lo_; + os << std::setw(div_base_log); + } else if (mid.lo_ != 0) { + os << mid.lo_; + os << std::noshowbase << std::setfill('0') << std::setw(div_base_log); + } + os << low.lo_; + std::string rep = os.str(); + + // Add the requisite padding. + std::streamsize width = o.width(0); + if (width > rep.size()) { + if ((flags & std::ios::adjustfield) == std::ios::left) { + rep.append(width - rep.size(), o.fill()); + } else { + rep.insert(static_cast(0), + width - rep.size(), o.fill()); + } + } + + // Stream the final representation in a single "<<" call. + return o << rep; +} + +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/int128.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/int128.h new file mode 100644 index 000000000..1499bb76d --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/int128.h @@ -0,0 +1,383 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. +#ifndef GOOGLE_PROTOBUF_STUBS_INT128_H_ +#define GOOGLE_PROTOBUF_STUBS_INT128_H_ + +#include + +#include + +namespace google { +namespace protobuf { + +struct uint128_pod; + +// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is +// available. +#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR +# define UINT128_CONSTEXPR constexpr +#else +# define UINT128_CONSTEXPR +#endif + +// An unsigned 128-bit integer type. Thread-compatible. +class LIBPROTOBUF_EXPORT uint128 { + public: + UINT128_CONSTEXPR uint128(); // Sets to 0, but don't trust on this behavior. + UINT128_CONSTEXPR uint128(uint64 top, uint64 bottom); +#ifndef SWIG + UINT128_CONSTEXPR uint128(int bottom); + UINT128_CONSTEXPR uint128(uint32 bottom); // Top 96 bits = 0 +#endif + UINT128_CONSTEXPR uint128(uint64 bottom); // hi_ = 0 + UINT128_CONSTEXPR uint128(const uint128_pod &val); + + // Trivial copy constructor, assignment operator and destructor. + + void Initialize(uint64 top, uint64 bottom); + + // Arithmetic operators. + uint128& operator+=(const uint128& b); + uint128& operator-=(const uint128& b); + uint128& operator*=(const uint128& b); + // Long division/modulo for uint128. + uint128& operator/=(const uint128& b); + uint128& operator%=(const uint128& b); + uint128 operator++(int); + uint128 operator--(int); + uint128& operator<<=(int); + uint128& operator>>=(int); + uint128& operator&=(const uint128& b); + uint128& operator|=(const uint128& b); + uint128& operator^=(const uint128& b); + uint128& operator++(); + uint128& operator--(); + + friend uint64 Uint128Low64(const uint128& v); + friend uint64 Uint128High64(const uint128& v); + + // We add "std::" to avoid including all of port.h. + LIBPROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o, + const uint128& b); + + private: + static void DivModImpl(uint128 dividend, uint128 divisor, + uint128* quotient_ret, uint128* remainder_ret); + + // Little-endian memory order optimizations can benefit from + // having lo_ first, hi_ last. + // See util/endian/endian.h and Load128/Store128 for storing a uint128. + uint64 lo_; + uint64 hi_; + + // Not implemented, just declared for catching automatic type conversions. + uint128(uint8); + uint128(uint16); + uint128(float v); + uint128(double v); +}; + +// This is a POD form of uint128 which can be used for static variables which +// need to be operated on as uint128. +struct uint128_pod { + // Note: The ordering of fields is different than 'class uint128' but the + // same as its 2-arg constructor. This enables more obvious initialization + // of static instances, which is the primary reason for this struct in the + // first place. This does not seem to defeat any optimizations wrt + // operations involving this struct. + uint64 hi; + uint64 lo; +}; + +LIBPROTOBUF_EXPORT extern const uint128_pod kuint128max; + +// allow uint128 to be logged +LIBPROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o, + const uint128& b); + +// Methods to access low and high pieces of 128-bit value. +// Defined externally from uint128 to facilitate conversion +// to native 128-bit types when compilers support them. +inline uint64 Uint128Low64(const uint128& v) { return v.lo_; } +inline uint64 Uint128High64(const uint128& v) { return v.hi_; } + +// TODO: perhaps it would be nice to have int128, a signed 128-bit type? + +// -------------------------------------------------------------------------- +// Implementation details follow +// -------------------------------------------------------------------------- +inline bool operator==(const uint128& lhs, const uint128& rhs) { + return (Uint128Low64(lhs) == Uint128Low64(rhs) && + Uint128High64(lhs) == Uint128High64(rhs)); +} +inline bool operator!=(const uint128& lhs, const uint128& rhs) { + return !(lhs == rhs); +} + +inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {} +inline UINT128_CONSTEXPR uint128::uint128(uint64 top, uint64 bottom) + : lo_(bottom), hi_(top) {} +inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v) + : lo_(v.lo), hi_(v.hi) {} +inline UINT128_CONSTEXPR uint128::uint128(uint64 bottom) + : lo_(bottom), hi_(0) {} +#ifndef SWIG +inline UINT128_CONSTEXPR uint128::uint128(uint32 bottom) + : lo_(bottom), hi_(0) {} +inline UINT128_CONSTEXPR uint128::uint128(int bottom) + : lo_(bottom), hi_(static_cast((bottom < 0) ? -1 : 0)) {} +#endif + +#undef UINT128_CONSTEXPR + +inline void uint128::Initialize(uint64 top, uint64 bottom) { + hi_ = top; + lo_ = bottom; +} + +// Comparison operators. + +#define CMP128(op) \ +inline bool operator op(const uint128& lhs, const uint128& rhs) { \ + return (Uint128High64(lhs) == Uint128High64(rhs)) ? \ + (Uint128Low64(lhs) op Uint128Low64(rhs)) : \ + (Uint128High64(lhs) op Uint128High64(rhs)); \ +} + +CMP128(<) +CMP128(>) +CMP128(>=) +CMP128(<=) + +#undef CMP128 + +// Unary operators + +inline uint128 operator-(const uint128& val) { + const uint64 hi_flip = ~Uint128High64(val); + const uint64 lo_flip = ~Uint128Low64(val); + const uint64 lo_add = lo_flip + 1; + if (lo_add < lo_flip) { + return uint128(hi_flip + 1, lo_add); + } + return uint128(hi_flip, lo_add); +} + +inline bool operator!(const uint128& val) { + return !Uint128High64(val) && !Uint128Low64(val); +} + +// Logical operators. + +inline uint128 operator~(const uint128& val) { + return uint128(~Uint128High64(val), ~Uint128Low64(val)); +} + +#define LOGIC128(op) \ +inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \ + return uint128(Uint128High64(lhs) op Uint128High64(rhs), \ + Uint128Low64(lhs) op Uint128Low64(rhs)); \ +} + +LOGIC128(|) +LOGIC128(&) +LOGIC128(^) + +#undef LOGIC128 + +#define LOGICASSIGN128(op) \ +inline uint128& uint128::operator op(const uint128& other) { \ + hi_ op other.hi_; \ + lo_ op other.lo_; \ + return *this; \ +} + +LOGICASSIGN128(|=) +LOGICASSIGN128(&=) +LOGICASSIGN128(^=) + +#undef LOGICASSIGN128 + +// Shift operators. + +inline uint128 operator<<(const uint128& val, int amount) { + // uint64 shifts of >= 64 are undefined, so we will need some special-casing. + if (amount < 64) { + if (amount == 0) { + return val; + } + uint64 new_hi = (Uint128High64(val) << amount) | + (Uint128Low64(val) >> (64 - amount)); + uint64 new_lo = Uint128Low64(val) << amount; + return uint128(new_hi, new_lo); + } else if (amount < 128) { + return uint128(Uint128Low64(val) << (amount - 64), 0); + } else { + return uint128(0, 0); + } +} + +inline uint128 operator>>(const uint128& val, int amount) { + // uint64 shifts of >= 64 are undefined, so we will need some special-casing. + if (amount < 64) { + if (amount == 0) { + return val; + } + uint64 new_hi = Uint128High64(val) >> amount; + uint64 new_lo = (Uint128Low64(val) >> amount) | + (Uint128High64(val) << (64 - amount)); + return uint128(new_hi, new_lo); + } else if (amount < 128) { + return uint128(0, Uint128High64(val) >> (amount - 64)); + } else { + return uint128(0, 0); + } +} + +inline uint128& uint128::operator<<=(int amount) { + // uint64 shifts of >= 64 are undefined, so we will need some special-casing. + if (amount < 64) { + if (amount != 0) { + hi_ = (hi_ << amount) | (lo_ >> (64 - amount)); + lo_ = lo_ << amount; + } + } else if (amount < 128) { + hi_ = lo_ << (amount - 64); + lo_ = 0; + } else { + hi_ = 0; + lo_ = 0; + } + return *this; +} + +inline uint128& uint128::operator>>=(int amount) { + // uint64 shifts of >= 64 are undefined, so we will need some special-casing. + if (amount < 64) { + if (amount != 0) { + lo_ = (lo_ >> amount) | (hi_ << (64 - amount)); + hi_ = hi_ >> amount; + } + } else if (amount < 128) { + lo_ = hi_ >> (amount - 64); + hi_ = 0; + } else { + lo_ = 0; + hi_ = 0; + } + return *this; +} + +inline uint128 operator+(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) += rhs; +} + +inline uint128 operator-(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) -= rhs; +} + +inline uint128 operator*(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) *= rhs; +} + +inline uint128 operator/(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) /= rhs; +} + +inline uint128 operator%(const uint128& lhs, const uint128& rhs) { + return uint128(lhs) %= rhs; +} + +inline uint128& uint128::operator+=(const uint128& b) { + hi_ += b.hi_; + uint64 lolo = lo_ + b.lo_; + if (lolo < lo_) + ++hi_; + lo_ = lolo; + return *this; +} + +inline uint128& uint128::operator-=(const uint128& b) { + hi_ -= b.hi_; + if (b.lo_ > lo_) + --hi_; + lo_ -= b.lo_; + return *this; +} + +inline uint128& uint128::operator*=(const uint128& b) { + uint64 a96 = hi_ >> 32; + uint64 a64 = hi_ & 0xffffffffu; + uint64 a32 = lo_ >> 32; + uint64 a00 = lo_ & 0xffffffffu; + uint64 b96 = b.hi_ >> 32; + uint64 b64 = b.hi_ & 0xffffffffu; + uint64 b32 = b.lo_ >> 32; + uint64 b00 = b.lo_ & 0xffffffffu; + // multiply [a96 .. a00] x [b96 .. b00] + // terms higher than c96 disappear off the high side + // terms c96 and c64 are safe to ignore carry bit + uint64 c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96; + uint64 c64 = a64 * b00 + a32 * b32 + a00 * b64; + this->hi_ = (c96 << 32) + c64; + this->lo_ = 0; + // add terms after this one at a time to capture carry + *this += uint128(a32 * b00) << 32; + *this += uint128(a00 * b32) << 32; + *this += a00 * b00; + return *this; +} + +inline uint128 uint128::operator++(int) { + uint128 tmp(*this); + *this += 1; + return tmp; +} + +inline uint128 uint128::operator--(int) { + uint128 tmp(*this); + *this -= 1; + return tmp; +} + +inline uint128& uint128::operator++() { + *this += 1; + return *this; +} + +inline uint128& uint128::operator--() { + *this -= 1; + return *this; +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_INT128_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/int128_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/int128_unittest.cc new file mode 100644 index 000000000..1ec899ad7 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/int128_unittest.cc @@ -0,0 +1,513 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include +#include +#include + +#include +#include + +namespace google { +namespace protobuf { + +TEST(Int128, AllTests) { + uint128 zero(0); + uint128 one(1); + uint128 one_2arg(0, 1); + uint128 two(0, 2); + uint128 three(0, 3); + uint128 big(2000, 2); + uint128 big_minus_one(2000, 1); + uint128 bigger(2001, 1); + uint128 biggest(kuint128max); + uint128 high_low(1, 0); + uint128 low_high(0, kuint64max); + EXPECT_LT(one, two); + EXPECT_GT(two, one); + EXPECT_LT(one, big); + EXPECT_LT(one, big); + EXPECT_EQ(one, one_2arg); + EXPECT_NE(one, two); + EXPECT_GT(big, one); + EXPECT_GE(big, two); + EXPECT_GE(big, big_minus_one); + EXPECT_GT(big, big_minus_one); + EXPECT_LT(big_minus_one, big); + EXPECT_LE(big_minus_one, big); + EXPECT_NE(big_minus_one, big); + EXPECT_LT(big, biggest); + EXPECT_LE(big, biggest); + EXPECT_GT(biggest, big); + EXPECT_GE(biggest, big); + EXPECT_EQ(big, ~~big); + EXPECT_EQ(one, one | one); + EXPECT_EQ(big, big | big); + EXPECT_EQ(one, one | zero); + EXPECT_EQ(one, one & one); + EXPECT_EQ(big, big & big); + EXPECT_EQ(zero, one & zero); + EXPECT_EQ(zero, big & ~big); + EXPECT_EQ(zero, one ^ one); + EXPECT_EQ(zero, big ^ big); + EXPECT_EQ(one, one ^ zero); + + // Shift operators. + EXPECT_EQ(big, big << 0); + EXPECT_EQ(big, big >> 0); + EXPECT_GT(big << 1, big); + EXPECT_LT(big >> 1, big); + EXPECT_EQ(big, (big << 10) >> 10); + EXPECT_EQ(big, (big >> 1) << 1); + EXPECT_EQ(one, (one << 80) >> 80); + EXPECT_EQ(zero, (one >> 80) << 80); + EXPECT_EQ(zero, big >> 128); + EXPECT_EQ(zero, big << 128); + + // Shift assignments. + uint128 big_copy = big; + EXPECT_EQ(big << 0, big_copy <<= 0); + big_copy = big; + EXPECT_EQ(big >> 0, big_copy >>= 0); + big_copy = big; + EXPECT_EQ(big << 1, big_copy <<= 1); + big_copy = big; + EXPECT_EQ(big >> 1, big_copy >>= 1); + big_copy = big; + EXPECT_EQ(big << 10, big_copy <<= 10); + big_copy = big; + EXPECT_EQ(big >> 10, big_copy >>= 10); + big_copy = big; + EXPECT_EQ(big << 64, big_copy <<= 64); + big_copy = big; + EXPECT_EQ(big >> 64, big_copy >>= 64); + big_copy = big; + EXPECT_EQ(big << 73, big_copy <<= 73); + big_copy = big; + EXPECT_EQ(big >> 73, big_copy >>= 73); + big_copy = big; + EXPECT_EQ(big << 128, big_copy <<= 128); + big_copy = big; + EXPECT_EQ(big >> 128, big_copy >>= 128); + + EXPECT_EQ(Uint128High64(biggest), kuint64max); + EXPECT_EQ(Uint128Low64(biggest), kuint64max); + EXPECT_EQ(zero + one, one); + EXPECT_EQ(one + one, two); + EXPECT_EQ(big_minus_one + one, big); + EXPECT_EQ(one - one, zero); + EXPECT_EQ(one - zero, one); + EXPECT_EQ(zero - one, biggest); + EXPECT_EQ(big - big, zero); + EXPECT_EQ(big - one, big_minus_one); + EXPECT_EQ(big + kuint64max, bigger); + EXPECT_EQ(biggest + 1, zero); + EXPECT_EQ(zero - 1, biggest); + EXPECT_EQ(high_low - one, low_high); + EXPECT_EQ(low_high + one, high_low); + EXPECT_EQ(Uint128High64((uint128(1) << 64) - 1), 0); + EXPECT_EQ(Uint128Low64((uint128(1) << 64) - 1), kuint64max); + EXPECT_TRUE(!!one); + EXPECT_TRUE(!!high_low); + EXPECT_FALSE(!!zero); + EXPECT_FALSE(!one); + EXPECT_FALSE(!high_low); + EXPECT_TRUE(!zero); + EXPECT_TRUE(zero == 0); + EXPECT_FALSE(zero != 0); + EXPECT_FALSE(one == 0); + EXPECT_TRUE(one != 0); + + uint128 test = zero; + EXPECT_EQ(++test, one); + EXPECT_EQ(test, one); + EXPECT_EQ(test++, one); + EXPECT_EQ(test, two); + EXPECT_EQ(test -= 2, zero); + EXPECT_EQ(test, zero); + EXPECT_EQ(test += 2, two); + EXPECT_EQ(test, two); + EXPECT_EQ(--test, one); + EXPECT_EQ(test, one); + EXPECT_EQ(test--, one); + EXPECT_EQ(test, zero); + EXPECT_EQ(test |= three, three); + EXPECT_EQ(test &= one, one); + EXPECT_EQ(test ^= three, two); + EXPECT_EQ(test >>= 1, one); + EXPECT_EQ(test <<= 1, two); + + EXPECT_EQ(big, -(-big)); + EXPECT_EQ(two, -((-one) - 1)); + EXPECT_EQ(kuint128max, -one); + EXPECT_EQ(zero, -zero); + + GOOGLE_LOG(INFO) << one; + GOOGLE_LOG(INFO) << big_minus_one; +} + +TEST(Int128, PodTests) { + uint128_pod pod = { 12345, 67890 }; + uint128 from_pod(pod); + EXPECT_EQ(12345, Uint128High64(from_pod)); + EXPECT_EQ(67890, Uint128Low64(from_pod)); + + uint128 zero(0); + uint128_pod zero_pod = {0, 0}; + uint128 one(1); + uint128_pod one_pod = {0, 1}; + uint128 two(2); + uint128_pod two_pod = {0, 2}; + uint128 three(3); + uint128_pod three_pod = {0, 3}; + uint128 big(1, 0); + uint128_pod big_pod = {1, 0}; + + EXPECT_EQ(zero, zero_pod); + EXPECT_EQ(zero_pod, zero); + EXPECT_EQ(zero_pod, zero_pod); + EXPECT_EQ(one, one_pod); + EXPECT_EQ(one_pod, one); + EXPECT_EQ(one_pod, one_pod); + EXPECT_EQ(two, two_pod); + EXPECT_EQ(two_pod, two); + EXPECT_EQ(two_pod, two_pod); + + EXPECT_NE(one, two_pod); + EXPECT_NE(one_pod, two); + EXPECT_NE(one_pod, two_pod); + + EXPECT_LT(one, two_pod); + EXPECT_LT(one_pod, two); + EXPECT_LT(one_pod, two_pod); + EXPECT_LE(one, one_pod); + EXPECT_LE(one_pod, one); + EXPECT_LE(one_pod, one_pod); + EXPECT_LE(one, two_pod); + EXPECT_LE(one_pod, two); + EXPECT_LE(one_pod, two_pod); + + EXPECT_GT(two, one_pod); + EXPECT_GT(two_pod, one); + EXPECT_GT(two_pod, one_pod); + EXPECT_GE(two, two_pod); + EXPECT_GE(two_pod, two); + EXPECT_GE(two_pod, two_pod); + EXPECT_GE(two, one_pod); + EXPECT_GE(two_pod, one); + EXPECT_GE(two_pod, one_pod); + + EXPECT_EQ(three, one | two_pod); + EXPECT_EQ(three, one_pod | two); + EXPECT_EQ(three, one_pod | two_pod); + EXPECT_EQ(one, three & one_pod); + EXPECT_EQ(one, three_pod & one); + EXPECT_EQ(one, three_pod & one_pod); + EXPECT_EQ(two, three ^ one_pod); + EXPECT_EQ(two, three_pod ^ one); + EXPECT_EQ(two, three_pod ^ one_pod); + EXPECT_EQ(two, three & (~one)); + EXPECT_EQ(three, ~~three); + + EXPECT_EQ(two, two_pod << 0); + EXPECT_EQ(two, one_pod << 1); + EXPECT_EQ(big, one_pod << 64); + EXPECT_EQ(zero, one_pod << 128); + EXPECT_EQ(two, two_pod >> 0); + EXPECT_EQ(one, two_pod >> 1); + EXPECT_EQ(one, big_pod >> 64); + + EXPECT_EQ(one, zero + one_pod); + EXPECT_EQ(one, zero_pod + one); + EXPECT_EQ(one, zero_pod + one_pod); + EXPECT_EQ(one, two - one_pod); + EXPECT_EQ(one, two_pod - one); + EXPECT_EQ(one, two_pod - one_pod); +} + +TEST(Int128, OperatorAssignReturnRef) { + uint128 v(1); + (v += 4) -= 3; + EXPECT_EQ(2, v); +} + +TEST(Int128, Multiply) { + uint128 a, b, c; + + // Zero test. + a = 0; + b = 0; + c = a * b; + EXPECT_EQ(0, c); + + // Max carries. + a = uint128(0) - 1; + b = uint128(0) - 1; + c = a * b; + EXPECT_EQ(1, c); + + // Self-operation with max carries. + c = uint128(0) - 1; + c *= c; + EXPECT_EQ(1, c); + + // 1-bit x 1-bit. + for (int i = 0; i < 64; ++i) { + for (int j = 0; j < 64; ++j) { + a = uint128(1) << i; + b = uint128(1) << j; + c = a * b; + EXPECT_EQ(uint128(1) << (i+j), c); + } + } + + // Verified with dc. + a = uint128(GOOGLE_ULONGLONG(0xffffeeeeddddcccc), + GOOGLE_ULONGLONG(0xbbbbaaaa99998888)); + b = uint128(GOOGLE_ULONGLONG(0x7777666655554444), + GOOGLE_ULONGLONG(0x3333222211110000)); + c = a * b; + EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x530EDA741C71D4C3), + GOOGLE_ULONGLONG(0xBF25975319080000)), c); + EXPECT_EQ(0, c - b * a); + EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); + + // Verified with dc. + a = uint128(GOOGLE_ULONGLONG(0x0123456789abcdef), + GOOGLE_ULONGLONG(0xfedcba9876543210)); + b = uint128(GOOGLE_ULONGLONG(0x02468ace13579bdf), + GOOGLE_ULONGLONG(0xfdb97531eca86420)); + c = a * b; + EXPECT_EQ(uint128(GOOGLE_ULONGLONG(0x97a87f4f261ba3f2), + GOOGLE_ULONGLONG(0x342d0bbf48948200)), c); + EXPECT_EQ(0, c - b * a); + EXPECT_EQ(a*a - b*b, (a+b) * (a-b)); +} + +TEST(Int128, AliasTests) { + uint128 x1(1, 2); + uint128 x2(2, 4); + x1 += x1; + EXPECT_EQ(x2, x1); + + uint128 x3(1, static_cast(1) << 63); + uint128 x4(3, 0); + x3 += x3; + EXPECT_EQ(x4, x3); +} + +#ifdef PROTOBUF_HAS_DEATH_TEST +TEST(Int128, DivideByZeroCheckFails) { + uint128 a = 0; + uint128 b = 0; + EXPECT_DEATH(a / b, "Division or mod by zero:"); + a = 123; + EXPECT_DEATH(a / b, "Division or mod by zero:"); +} + +TEST(Int128, ModByZeroCheckFails) { + uint128 a = 0; + uint128 b = 0; + EXPECT_DEATH(a % b, "Division or mod by zero:"); + a = 123; + EXPECT_DEATH(a % b, "Division or mod by zero:"); +} +#endif // PROTOBUF_HAS_DEATH_TEST + +TEST(Int128, DivideAndMod) { + // a := q * b + r + uint128 a, b, q, r; + + // Zero test. + a = 0; + b = 123; + q = a / b; + r = a % b; + EXPECT_EQ(0, q); + EXPECT_EQ(0, r); + + a = uint128(GOOGLE_ULONGLONG(0x530eda741c71d4c3), + GOOGLE_ULONGLONG(0xbf25975319080000)); + q = uint128(GOOGLE_ULONGLONG(0x4de2cab081), + GOOGLE_ULONGLONG(0x14c34ab4676e4bab)); + b = uint128(0x1110001); + r = uint128(0x3eb455); + ASSERT_EQ(a, q * b + r); // Sanity-check. + + uint128 result_q, result_r; + result_q = a / b; + result_r = a % b; + EXPECT_EQ(q, result_q); + EXPECT_EQ(r, result_r); + + // Try the other way around. + std::swap(q, b); + result_q = a / b; + result_r = a % b; + EXPECT_EQ(q, result_q); + EXPECT_EQ(r, result_r); + // Restore. + std::swap(b, q); + + // Dividend < divisor; result should be q:0 r:. + std::swap(a, b); + result_q = a / b; + result_r = a % b; + EXPECT_EQ(0, result_q); + EXPECT_EQ(a, result_r); + // Try the other way around. + std::swap(a, q); + result_q = a / b; + result_r = a % b; + EXPECT_EQ(0, result_q); + EXPECT_EQ(a, result_r); + // Restore. + std::swap(q, a); + std::swap(b, a); + + // Try a large remainder. + b = a / 2 + 1; + uint128 expected_r(GOOGLE_ULONGLONG(0x29876d3a0e38ea61), + GOOGLE_ULONGLONG(0xdf92cba98c83ffff)); + // Sanity checks. + ASSERT_EQ(a / 2 - 1, expected_r); + ASSERT_EQ(a, b + expected_r); + result_q = a / b; + result_r = a % b; + EXPECT_EQ(1, result_q); + EXPECT_EQ(expected_r, result_r); +} + +static uint64 RandomUint64() { + uint64 v1 = rand(); + uint64 v2 = rand(); + uint64 v3 = rand(); + return v1 * v2 + v3; +} + +TEST(Int128, DivideAndModRandomInputs) { + const int kNumIters = 1 << 18; + for (int i = 0; i < kNumIters; ++i) { + const uint128 a(RandomUint64(), RandomUint64()); + const uint128 b(RandomUint64(), RandomUint64()); + if (b == 0) { + continue; // Avoid a div-by-zero. + } + const uint128 q = a / b; + const uint128 r = a % b; + ASSERT_EQ(a, b * q + r); + } +} + +#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR +TEST(Int128, ConstexprTest) { + constexpr uint128 zero; + constexpr uint128 one = 1; + constexpr uint128_pod pod = {2, 3}; + constexpr uint128 from_pod = pod; + constexpr uint128 minus_two = -2; + EXPECT_EQ(one, uint128(1)); + EXPECT_EQ(from_pod, uint128(2, 3)); + EXPECT_EQ(minus_two, uint128(-1ULL, -2ULL)); +} + +TEST(Int128, Traits) { + EXPECT_TRUE(std::is_trivially_copy_constructible::value); + EXPECT_TRUE(std::is_trivially_copy_assignable::value); + EXPECT_TRUE(std::is_trivially_destructible::value); +} +#endif // GOOGLE_PROTOBUF_HAS_CONSTEXPR + +TEST(Int128, OStream) { + struct { + uint128 val; + std::ios_base::fmtflags flags; + std::streamsize width; + char fill; + const char* rep; + } cases[] = { + // zero with different bases + {uint128(0), std::ios::dec, 0, '_', "0"}, + {uint128(0), std::ios::oct, 0, '_', "0"}, + {uint128(0), std::ios::hex, 0, '_', "0"}, + // crossover between lo_ and hi_ + {uint128(0, -1), std::ios::dec, 0, '_', "18446744073709551615"}, + {uint128(0, -1), std::ios::oct, 0, '_', "1777777777777777777777"}, + {uint128(0, -1), std::ios::hex, 0, '_', "ffffffffffffffff"}, + {uint128(1, 0), std::ios::dec, 0, '_', "18446744073709551616"}, + {uint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"}, + {uint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"}, + // just the top bit + {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::dec, 0, '_', + "170141183460469231731687303715884105728"}, + {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::oct, 0, '_', + "2000000000000000000000000000000000000000000"}, + {uint128(GOOGLE_ULONGLONG(0x8000000000000000), 0), std::ios::hex, 0, '_', + "80000000000000000000000000000000"}, + // maximum uint128 value + {uint128(-1, -1), std::ios::dec, 0, '_', + "340282366920938463463374607431768211455"}, + {uint128(-1, -1), std::ios::oct, 0, '_', + "3777777777777777777777777777777777777777777"}, + {uint128(-1, -1), std::ios::hex, 0, '_', + "ffffffffffffffffffffffffffffffff"}, + // uppercase + {uint128(-1, -1), std::ios::hex | std::ios::uppercase, 0, '_', + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"}, + // showbase + {uint128(1), std::ios::dec | std::ios::showbase, 0, '_', "1"}, + {uint128(1), std::ios::oct | std::ios::showbase, 0, '_', "01"}, + {uint128(1), std::ios::hex | std::ios::showbase, 0, '_', "0x1"}, + // showbase does nothing on zero + {uint128(0), std::ios::dec | std::ios::showbase, 0, '_', "0"}, + {uint128(0), std::ios::oct | std::ios::showbase, 0, '_', "0"}, + {uint128(0), std::ios::hex | std::ios::showbase, 0, '_', "0"}, + // showpos does nothing on unsigned types + {uint128(1), std::ios::dec | std::ios::showpos, 0, '_', "1"}, + // padding + {uint128(9), std::ios::dec, 6, '_', "_____9"}, + {uint128(12345), std::ios::dec, 6, '_', "_12345"}, + // left adjustment + {uint128(9), std::ios::dec | std::ios::left, 6, '_', "9_____"}, + {uint128(12345), std::ios::dec | std::ios::left, 6, '_', "12345_"}, + }; + for (size_t i = 0; i < GOOGLE_ARRAYSIZE(cases); ++i) { + std::ostringstream os; + os.flags(cases[i].flags); + os.width(cases[i].width); + os.fill(cases[i].fill); + os << cases[i].val; + EXPECT_EQ(cases[i].rep, os.str()); + } +} +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/io_win32.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/io_win32.cc new file mode 100644 index 000000000..4407facb4 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/io_win32.cc @@ -0,0 +1,414 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: laszlocsomor@google.com (Laszlo Csomor) +// +// Implementation for long-path-aware open/mkdir/access/etc. on Windows, as well +// as for the supporting utility functions. +// +// These functions convert the input path to an absolute Windows path +// with "\\?\" prefix, then pass that to _wopen/_wmkdir/_waccess/etc. +// (declared in ) respectively. This allows working with files/directories +// whose paths are longer than MAX_PATH (260 chars). +// +// This file is only used on Windows, it's empty on other platforms. + +#if defined(_WIN32) + +// Comment this out to fall back to using the ANSI versions (open, mkdir, ...) +// instead of the Unicode ones (_wopen, _wmkdir, ...). Doing so can be useful to +// debug failing tests if that's caused by the long path support. +#define SUPPORT_LONGPATHS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +namespace win32 { +namespace { + +using std::string; +using std::wstring; + +template +struct CharTraits { + static bool is_alpha(char_type ch); +}; + +template <> +struct CharTraits { + static bool is_alpha(char ch) { return isalpha(ch); } +}; + +template <> +struct CharTraits { + static bool is_alpha(wchar_t ch) { return iswalpha(ch); } +}; + +template +bool null_or_empty(const char_type* s) { + return s == NULL || *s == 0; +} + +// Returns true if the path starts with a drive letter, e.g. "c:". +// Note that this won't check for the "\" after the drive letter, so this also +// returns true for "c:foo" (which is "c:\${PWD}\foo"). +// This check requires that a path not have a longpath prefix ("\\?\"). +template +bool has_drive_letter(const char_type* ch) { + return CharTraits::is_alpha(ch[0]) && ch[1] == ':'; +} + +// Returns true if the path starts with a longpath prefix ("\\?\"). +template +bool has_longpath_prefix(const char_type* path) { + return path[0] == '\\' && path[1] == '\\' && path[2] == '?' && + path[3] == '\\'; +} + +template +bool is_separator(char_type c) { + return c == '/' || c == '\\'; +} + +// Returns true if the path starts with a drive specifier (e.g. "c:\"). +template +bool is_path_absolute(const char_type* path) { + return has_drive_letter(path) && is_separator(path[2]); +} + +template +bool is_drive_relative(const char_type* path) { + return has_drive_letter(path) && (path[2] == 0 || !is_separator(path[2])); +} + +wstring join_paths(const wstring& path1, const wstring& path2) { + if (path1.empty() || is_path_absolute(path2.c_str()) || + has_longpath_prefix(path2.c_str())) { + return path2; + } + if (path2.empty()) { + return path1; + } + + if (is_separator(path1[path1.size() - 1])) { + return is_separator(path2[0]) ? (path1 + path2.substr(1)) + : (path1 + path2); + } else { + return is_separator(path2[0]) ? (path1 + path2) + : (path1 + L'\\' + path2); + } +} + +wstring normalize(wstring path) { + if (has_longpath_prefix(path.c_str())) { + path = path.substr(4); + } + + static const wstring dot(L"."); + static const wstring dotdot(L".."); + const WCHAR* p = path.c_str(); + + std::vector segments; + int segment_start = -1; + // Find the path segments in `path` (separated by "/"). + for (int i = 0;; ++i) { + if (!is_separator(p[i]) && p[i] != L'\0') { + // The current character does not end a segment, so start one unless it's + // already started. + if (segment_start < 0) { + segment_start = i; + } + } else if (segment_start >= 0 && i > segment_start) { + // The current character is "/" or "\0", so this ends a segment. + // Add that to `segments` if there's anything to add; handle "." and "..". + wstring segment(p, segment_start, i - segment_start); + segment_start = -1; + if (segment == dotdot) { + if (!segments.empty() && + (!has_drive_letter(segments[0].c_str()) || segments.size() > 1)) { + segments.pop_back(); + } + } else if (segment != dot && !segment.empty()) { + segments.push_back(segment); + } + } + if (p[i] == L'\0') { + break; + } + } + + // Handle the case when `path` is just a drive specifier (or some degenerate + // form of it, e.g. "c:\.."). + if (segments.size() == 1 && segments[0].size() == 2 && + has_drive_letter(segments[0].c_str())) { + return segments[0] + L'\\'; + } + + // Join all segments. + bool first = true; + std::wstringstream result; + for (int i = 0; i < segments.size(); ++i) { + if (!first) { + result << L'\\'; + } + first = false; + result << segments[i]; + } + // Preserve trailing separator if the input contained it. + if (!path.empty() && is_separator(p[path.size() - 1])) { + result << L'\\'; + } + return result.str(); +} + +bool as_windows_path(const char* path, wstring* result) { + if (null_or_empty(path)) { + result->clear(); + return true; + } + wstring wpath; + if (!strings::utf8_to_wcs(path, &wpath)) { + return false; + } + if (has_longpath_prefix(wpath.c_str())) { + *result = wpath; + return true; + } + if (is_separator(path[0]) || is_drive_relative(path)) { + return false; + } + + + if (!is_path_absolute(wpath.c_str())) { + int size = ::GetCurrentDirectoryW(0, NULL); + if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + return false; + } + std::unique_ptr wcwd(new WCHAR[size]); + ::GetCurrentDirectoryW(size, wcwd.get()); + wpath = join_paths(wcwd.get(), wpath); + } + wpath = normalize(wpath); + if (!has_longpath_prefix(wpath.c_str())) { + // Add the "\\?\" prefix unconditionally. This way we prevent the Win32 API + // from processing the path and "helpfully" removing trailing dots from the + // path, for example. + // See https://github.com/bazelbuild/bazel/issues/2935 + wpath = wstring(L"\\\\?\\") + wpath; + } + *result = wpath; + return true; +} + +} // namespace + +int open(const char* path, int flags, int mode) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wopen(wpath.c_str(), flags, mode); +#else + return ::_open(path, flags, mode); +#endif +} + +int mkdir(const char* path, int _mode) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wmkdir(wpath.c_str()); +#else // not SUPPORT_LONGPATHS + return ::_mkdir(path); +#endif // not SUPPORT_LONGPATHS +} + +int access(const char* path, int mode) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_waccess(wpath.c_str(), mode); +#else + return ::_access(path, mode); +#endif +} + +int chdir(const char* path) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wchdir(wpath.c_str()); +#else + return ::_chdir(path); +#endif +} + +int stat(const char* path, struct _stat* buffer) { +#ifdef SUPPORT_LONGPATHS + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return -1; + } + return ::_wstat(wpath.c_str(), buffer); +#else // not SUPPORT_LONGPATHS + return ::_stat(path, buffer); +#endif // not SUPPORT_LONGPATHS +} + +FILE* fopen(const char* path, const char* mode) { +#ifdef SUPPORT_LONGPATHS + if (null_or_empty(path)) { + errno = EINVAL; + return NULL; + } + wstring wpath; + if (!as_windows_path(path, &wpath)) { + errno = ENOENT; + return NULL; + } + wstring wmode; + if (!strings::utf8_to_wcs(mode, &wmode)) { + errno = EINVAL; + return NULL; + } + return ::_wfopen(wpath.c_str(), wmode.c_str()); +#else + return ::fopen(path, mode); +#endif +} + +int close(int fd) { return ::close(fd); } + +int dup(int fd) { return ::_dup(fd); } + +int dup2(int fd1, int fd2) { return ::_dup2(fd1, fd2); } + +int read(int fd, void* buffer, size_t size) { + return ::_read(fd, buffer, size); +} + +int setmode(int fd, int mode) { return ::_setmode(fd, mode); } + +int write(int fd, const void* buffer, size_t size) { + return ::_write(fd, buffer, size); +} + +wstring testonly_utf8_to_winpath(const char* path) { + wstring wpath; + return as_windows_path(path, &wpath) ? wpath : wstring(); +} + +namespace strings { + +bool wcs_to_mbs(const WCHAR* s, string* out, bool outUtf8) { + if (null_or_empty(s)) { + out->clear(); + return true; + } + BOOL usedDefaultChar = FALSE; + SetLastError(0); + int size = WideCharToMultiByte( + outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, NULL, 0, NULL, + outUtf8 ? NULL : &usedDefaultChar); + if ((size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) + || usedDefaultChar) { + return false; + } + std::unique_ptr astr(new CHAR[size]); + WideCharToMultiByte( + outUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, astr.get(), size, NULL, NULL); + out->assign(astr.get()); + return true; +} + +bool mbs_to_wcs(const char* s, wstring* out, bool inUtf8) { + if (null_or_empty(s)) { + out->clear(); + return true; + } + + SetLastError(0); + int size = + MultiByteToWideChar(inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, NULL, 0); + if (size == 0 && GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + return false; + } + std::unique_ptr wstr(new WCHAR[size]); + MultiByteToWideChar( + inUtf8 ? CP_UTF8 : CP_ACP, 0, s, -1, wstr.get(), size + 1); + out->assign(wstr.get()); + return true; +} + +bool utf8_to_wcs(const char* input, wstring* out) { + return mbs_to_wcs(input, out, true); +} + +bool wcs_to_utf8(const wchar_t* input, string* out) { + return wcs_to_mbs(input, out, true); +} + +} // namespace strings +} // namespace win32 +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // defined(_WIN32) diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/io_win32.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/io_win32.h new file mode 100644 index 000000000..9e17d2530 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/io_win32.h @@ -0,0 +1,115 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: laszlocsomor@google.com (Laszlo Csomor) +// +// This file contains the declarations for Windows implementations of +// commonly used POSIX functions such as open(2) and access(2), as well +// as macro definitions for flags of these functions. +// +// By including this file you'll redefine open/access/etc. to +// ::google::protobuf::internal::win32::{open/access/etc.}. +// Make sure you don't include a header that attempts to redeclare or +// redefine these functions, that'll lead to confusing compilation +// errors. It's best to #include this file as the last one to ensure that. +// +// This file is only used on Windows, it's empty on other platforms. + +#ifndef GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__ +#define GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__ + +#if defined(_WIN32) + +#include +#include + +// Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the +// following functions already, except for mkdir. +namespace google { +namespace protobuf { +namespace internal { +namespace win32 { + +LIBPROTOBUF_EXPORT FILE* fopen(const char* path, const char* mode); +LIBPROTOBUF_EXPORT int access(const char* path, int mode); +LIBPROTOBUF_EXPORT int chdir(const char* path); +LIBPROTOBUF_EXPORT int close(int fd); +LIBPROTOBUF_EXPORT int dup(int fd); +LIBPROTOBUF_EXPORT int dup2(int fd1, int fd2); +LIBPROTOBUF_EXPORT int mkdir(const char* path, int _mode); +LIBPROTOBUF_EXPORT int open(const char* path, int flags, int mode = 0); +LIBPROTOBUF_EXPORT int read(int fd, void* buffer, size_t size); +LIBPROTOBUF_EXPORT int setmode(int fd, int mode); +LIBPROTOBUF_EXPORT int stat(const char* path, struct _stat* buffer); +LIBPROTOBUF_EXPORT int write(int fd, const void* buffer, size_t size); +LIBPROTOBUF_EXPORT std::wstring testonly_utf8_to_winpath(const char* path); + +namespace strings { + +// Convert from UTF-16 to Active-Code-Page-encoded or to UTF-8-encoded text. +LIBPROTOBUF_EXPORT bool wcs_to_mbs( + const wchar_t* s, std::string* out, bool outUtf8); + +// Convert from Active-Code-Page-encoded or UTF-8-encoded text to UTF-16. +LIBPROTOBUF_EXPORT bool mbs_to_wcs( + const char* s, std::wstring* out, bool inUtf8); + +// Convert from UTF-8-encoded text to UTF-16. +LIBPROTOBUF_EXPORT bool utf8_to_wcs(const char* input, std::wstring* out); + +// Convert from UTF-16-encoded text to UTF-8. +LIBPROTOBUF_EXPORT bool wcs_to_utf8(const wchar_t* input, std::string* out); + +} // namespace strings + +} // namespace win32 +} // namespace internal +} // namespace protobuf +} // namespace google + +#ifndef W_OK +#define W_OK 02 // not defined by MSVC for whatever reason +#endif + +#ifndef F_OK +#define F_OK 00 // not defined by MSVC for whatever reason +#endif + +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif + +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif + +#endif // defined(_WIN32) + +#endif // GOOGLE_PROTOBUF_STUBS_IO_WIN32_H__ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/io_win32_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/io_win32_unittest.cc new file mode 100644 index 000000000..c933757c7 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/io_win32_unittest.cc @@ -0,0 +1,452 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: laszlocsomor@google.com (Laszlo Csomor) +// +// Unit tests for long-path-aware open/mkdir/access/etc. on Windows, as well as +// for the supporting utility functions. +// +// This file is only used on Windows, it's empty on other platforms. + +#if defined(_WIN32) + +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +namespace win32 { +namespace { + +const char kUtf8Text[] = { + 'h', 'i', ' ', + // utf-8: 11010000 10011111, utf-16: 100 0001 1111 = 0x041F + 0xd0, 0x9f, + // utf-8: 11010001 10000000, utf-16: 100 0100 0000 = 0x0440 + 0xd1, 0x80, + // utf-8: 11010000 10111000, utf-16: 100 0011 1000 = 0x0438 + 0xd0, 0xb8, + // utf-8: 11010000 10110010, utf-16: 100 0011 0010 = 0x0432 + 0xd0, 0xb2, + // utf-8: 11010000 10110101, utf-16: 100 0011 0101 = 0x0435 + 0xd0, 0xb5, + // utf-8: 11010001 10000010, utf-16: 100 0100 0010 = 0x0442 + 0xd1, 0x82, 0 +}; + +const wchar_t kUtf16Text[] = { + L'h', L'i', L' ', + L'\x41f', L'\x440', L'\x438', L'\x432', L'\x435', L'\x442', 0 +}; + +using std::string; +using std::wstring; + +class IoWin32Test : public ::testing::Test { + public: + void SetUp(); + void TearDown(); + + protected: + bool CreateAllUnder(wstring path); + bool DeleteAllUnder(wstring path); + + WCHAR working_directory[MAX_PATH]; + string test_tmpdir; + wstring wtest_tmpdir; +}; + +#define ASSERT_INITIALIZED \ + { \ + EXPECT_FALSE(test_tmpdir.empty()); \ + EXPECT_FALSE(wtest_tmpdir.empty()); \ + } + +namespace { +void StripTrailingSlashes(string* str) { + int i = str->size() - 1; + for (; i >= 0 && ((*str)[i] == '/' || (*str)[i] == '\\'); --i) {} + str->resize(i+1); +} + +bool GetEnvVarAsUtf8(const WCHAR* name, string* result) { + DWORD size = ::GetEnvironmentVariableW(name, NULL, 0); + if (size > 0 && GetLastError() != ERROR_ENVVAR_NOT_FOUND) { + std::unique_ptr wcs(new WCHAR[size]); + ::GetEnvironmentVariableW(name, wcs.get(), size); + // GetEnvironmentVariableA retrieves an Active-Code-Page-encoded text which + // we'd first need to convert to UTF-16 then to UTF-8, because there seems + // to be no API function to do that conversion directly. + // GetEnvironmentVariableW retrieves an UTF-16-encoded text, which we need + // to convert to UTF-8. + return strings::wcs_to_utf8(wcs.get(), result); + } else { + return false; + } +} + +bool GetCwdAsUtf8(string* result) { + DWORD size = ::GetCurrentDirectoryW(0, NULL); + if (size > 0) { + std::unique_ptr wcs(new WCHAR[size]); + ::GetCurrentDirectoryW(size, wcs.get()); + // GetCurrentDirectoryA retrieves an Active-Code-Page-encoded text which + // we'd first need to convert to UTF-16 then to UTF-8, because there seems + // to be no API function to do that conversion directly. + // GetCurrentDirectoryW retrieves an UTF-16-encoded text, which we need + // to convert to UTF-8. + return strings::wcs_to_utf8(wcs.get(), result); + } else { + return false; + } +} + +} // namespace + +void IoWin32Test::SetUp() { + test_tmpdir.clear(); + wtest_tmpdir.clear(); + EXPECT_GT(::GetCurrentDirectoryW(MAX_PATH, working_directory), 0); + + string tmp; + bool ok = false; + if (!ok) { + // Bazel sets this environment variable when it runs tests. + ok = GetEnvVarAsUtf8(L"TEST_TMPDIR", &tmp); + } + if (!ok) { + // Bazel 0.8.0 sets this environment for every build and test action. + ok = GetEnvVarAsUtf8(L"TEMP", &tmp); + } + if (!ok) { + // Bazel 0.8.0 sets this environment for every build and test action. + ok = GetEnvVarAsUtf8(L"TMP", &tmp); + } + if (!ok) { + // Fall back to using the current directory. + ok = GetCwdAsUtf8(&tmp); + } + if (!ok || tmp.empty()) { + FAIL() << "Cannot find a temp directory."; + } + + StripTrailingSlashes(&tmp); + std::stringstream result; + // Deleting files and directories is asynchronous on Windows, and if TearDown + // just deleted the previous temp directory, sometimes we cannot recreate the + // same directory. + // Use a counter so every test method gets its own temp directory. + static unsigned int counter = 0; + result << tmp << "\\w32tst" << counter++ << ".tmp"; + test_tmpdir = result.str(); + wtest_tmpdir = testonly_utf8_to_winpath(test_tmpdir.c_str()); + ASSERT_FALSE(wtest_tmpdir.empty()); + ASSERT_TRUE(DeleteAllUnder(wtest_tmpdir)); + ASSERT_TRUE(CreateAllUnder(wtest_tmpdir)); +} + +void IoWin32Test::TearDown() { + if (!wtest_tmpdir.empty()) { + DeleteAllUnder(wtest_tmpdir); + } + ::SetCurrentDirectoryW(working_directory); +} + +bool IoWin32Test::CreateAllUnder(wstring path) { + // Prepend UNC prefix if the path doesn't have it already. Don't bother + // checking if the path is shorter than MAX_PATH, let's just do it + // unconditionally. + if (path.find(L"\\\\?\\") != 0) { + path = wstring(L"\\\\?\\") + path; + } + if (::CreateDirectoryW(path.c_str(), NULL) || + GetLastError() == ERROR_ALREADY_EXISTS || + GetLastError() == ERROR_ACCESS_DENIED) { + return true; + } + if (GetLastError() == ERROR_PATH_NOT_FOUND) { + size_t pos = path.find_last_of(L'\\'); + if (pos != wstring::npos) { + wstring parent(path, 0, pos); + if (CreateAllUnder(parent) && CreateDirectoryW(path.c_str(), NULL)) { + return true; + } + } + } + return false; +} + +bool IoWin32Test::DeleteAllUnder(wstring path) { + static const wstring kDot(L"."); + static const wstring kDotDot(L".."); + + // Prepend UNC prefix if the path doesn't have it already. Don't bother + // checking if the path is shorter than MAX_PATH, let's just do it + // unconditionally. + if (path.find(L"\\\\?\\") != 0) { + path = wstring(L"\\\\?\\") + path; + } + // Append "\" if necessary. + if (path[path.size() - 1] != L'\\') { + path.push_back(L'\\'); + } + + WIN32_FIND_DATAW metadata; + HANDLE handle = ::FindFirstFileW((path + L"*").c_str(), &metadata); + if (handle == INVALID_HANDLE_VALUE) { + return true; // directory doesn't exist + } + + bool result = true; + do { + wstring childname = metadata.cFileName; + if (kDot != childname && kDotDot != childname) { + wstring childpath = path + childname; + if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) { + // If this is not a junction, delete its contents recursively. + // Finally delete this directory/junction too. + if (((metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0 && + !DeleteAllUnder(childpath)) || + !::RemoveDirectoryW(childpath.c_str())) { + result = false; + break; + } + } else { + if (!::DeleteFileW(childpath.c_str())) { + result = false; + break; + } + } + } + } while (::FindNextFileW(handle, &metadata)); + ::FindClose(handle); + return result; +} + +TEST_F(IoWin32Test, AccessTest) { + ASSERT_INITIALIZED; + + string path = test_tmpdir; + while (path.size() < MAX_PATH - 30) { + path += "\\accesstest"; + EXPECT_EQ(mkdir(path.c_str(), 0644), 0); + } + string file = path + "\\file.txt"; + int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644); + if (fd > 0) { + EXPECT_EQ(close(fd), 0); + } else { + EXPECT_TRUE(false); + } + + EXPECT_EQ(access(test_tmpdir.c_str(), F_OK), 0); + EXPECT_EQ(access(path.c_str(), F_OK), 0); + EXPECT_EQ(access(path.c_str(), W_OK), 0); + EXPECT_EQ(access(file.c_str(), F_OK | W_OK), 0); + EXPECT_NE(access((file + ".blah").c_str(), F_OK), 0); + EXPECT_NE(access((file + ".blah").c_str(), W_OK), 0); + + EXPECT_EQ(access(".", F_OK), 0); + EXPECT_EQ(access(".", W_OK), 0); + EXPECT_EQ(access((test_tmpdir + "/accesstest").c_str(), F_OK | W_OK), 0); + ASSERT_EQ(access((test_tmpdir + "/./normalize_me/.././accesstest").c_str(), + F_OK | W_OK), + 0); + EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", F_OK), 0); + EXPECT_NE(access("io_win32_unittest.AccessTest.nonexistent", W_OK), 0); + + ASSERT_EQ(access("c:bad", F_OK), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(access("/tmp/bad", F_OK), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(access("\\bad", F_OK), -1); + ASSERT_EQ(errno, ENOENT); +} + +TEST_F(IoWin32Test, OpenTest) { + ASSERT_INITIALIZED; + + string path = test_tmpdir; + while (path.size() < MAX_PATH) { + path += "\\opentest"; + EXPECT_EQ(mkdir(path.c_str(), 0644), 0); + } + string file = path + "\\file.txt"; + int fd = open(file.c_str(), O_CREAT | O_WRONLY, 0644); + if (fd > 0) { + EXPECT_EQ(write(fd, "hello", 5), 5); + EXPECT_EQ(close(fd), 0); + } else { + EXPECT_TRUE(false); + } + + ASSERT_EQ(open("c:bad.txt", O_CREAT | O_WRONLY, 0644), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(open("/tmp/bad.txt", O_CREAT | O_WRONLY, 0644), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(open("\\bad.txt", O_CREAT | O_WRONLY, 0644), -1); + ASSERT_EQ(errno, ENOENT); +} + +TEST_F(IoWin32Test, MkdirTest) { + ASSERT_INITIALIZED; + + string path = test_tmpdir; + do { + path += "\\mkdirtest"; + ASSERT_EQ(mkdir(path.c_str(), 0644), 0); + } while (path.size() <= MAX_PATH); + + ASSERT_EQ(mkdir("c:bad", 0644), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(mkdir("/tmp/bad", 0644), -1); + ASSERT_EQ(errno, ENOENT); + ASSERT_EQ(mkdir("\\bad", 0644), -1); + ASSERT_EQ(errno, ENOENT); +} + +TEST_F(IoWin32Test, MkdirTestNonAscii) { + ASSERT_INITIALIZED; + + // Create a non-ASCII path. + // Ensure that we can create the directory using SetCurrentDirectoryW. + EXPECT_TRUE(CreateDirectoryW((wtest_tmpdir + L"\\1").c_str(), NULL)); + EXPECT_TRUE(CreateDirectoryW((wtest_tmpdir + L"\\1\\" + kUtf16Text).c_str(), NULL)); + // Ensure that we can create a very similarly named directory using mkdir. + // We don't attemp to delete and recreate the same directory, because on + // Windows, deleting files and directories seems to be asynchronous. + EXPECT_EQ(mkdir((test_tmpdir + "\\2").c_str(), 0644), 0); + EXPECT_EQ(mkdir((test_tmpdir + "\\2\\" + kUtf8Text).c_str(), 0644), 0); +} + +TEST_F(IoWin32Test, ChdirTest) { + string path("C:\\"); + EXPECT_EQ(access(path.c_str(), F_OK), 0); + ASSERT_EQ(chdir(path.c_str()), 0); + + // Do not try to chdir into the test_tmpdir, it may already contain directory + // names with trailing dots. + // Instead test here with an obviously dot-trailed path. If the win32_chdir + // function would not convert the path to absolute and prefix with "\\?\" then + // the Win32 API would ignore the trailing dot, but because of the prefixing + // there'll be no path processing done, so we'll actually attempt to chdir + // into "C:\some\path\foo." + path = test_tmpdir + "/foo."; + EXPECT_EQ(mkdir(path.c_str(), 644), 0); + EXPECT_EQ(access(path.c_str(), F_OK), 0); + ASSERT_NE(chdir(path.c_str()), 0); +} + +TEST_F(IoWin32Test, ChdirTestNonAscii) { + ASSERT_INITIALIZED; + + // Create a directory with a non-ASCII path and ensure we can cd into it. + wstring wNonAscii(wtest_tmpdir + L"\\" + kUtf16Text); + string nonAscii; + EXPECT_TRUE(strings::wcs_to_utf8(wNonAscii.c_str(), &nonAscii)); + EXPECT_TRUE(CreateDirectoryW(wNonAscii.c_str(), NULL)); + WCHAR cwd[MAX_PATH]; + EXPECT_TRUE(GetCurrentDirectoryW(MAX_PATH, cwd)); + // Ensure that we can cd into the path using SetCurrentDirectoryW. + EXPECT_TRUE(SetCurrentDirectoryW(wNonAscii.c_str())); + EXPECT_TRUE(SetCurrentDirectoryW(cwd)); + // Ensure that we can cd into the path using chdir. + ASSERT_EQ(chdir(nonAscii.c_str()), 0); + // Ensure that the GetCurrentDirectoryW returns the desired path. + EXPECT_TRUE(GetCurrentDirectoryW(MAX_PATH, cwd)); + ASSERT_EQ(wNonAscii, cwd); +} + +TEST_F(IoWin32Test, AsWindowsPathTest) { + DWORD size = GetCurrentDirectoryW(0, NULL); + std::unique_ptr cwd_str(new wchar_t[size]); + EXPECT_GT(GetCurrentDirectoryW(size, cwd_str.get()), 0); + wstring cwd = wstring(L"\\\\?\\") + cwd_str.get(); + + ASSERT_EQ(testonly_utf8_to_winpath("relative_mkdirtest"), + cwd + L"\\relative_mkdirtest"); + ASSERT_EQ(testonly_utf8_to_winpath("preserve//\\trailing///"), + cwd + L"\\preserve\\trailing\\"); + ASSERT_EQ(testonly_utf8_to_winpath("./normalize_me\\/../blah"), + cwd + L"\\blah"); + std::ostringstream relpath; + for (wchar_t* p = cwd_str.get(); *p; ++p) { + if (*p == '/' || *p == '\\') { + relpath << "../"; + } + } + relpath << ".\\/../\\./beyond-toplevel"; + ASSERT_EQ(testonly_utf8_to_winpath(relpath.str().c_str()), + wstring(L"\\\\?\\") + cwd_str.get()[0] + L":\\beyond-toplevel"); + + // Absolute unix paths lack drive letters, driveless absolute windows paths + // do too. Neither can be converted to a drive-specifying absolute Windows + // path. + ASSERT_EQ(testonly_utf8_to_winpath("/absolute/unix/path"), L""); + // Though valid on Windows, we also don't support UNC paths (\\UNC\\blah). + ASSERT_EQ(testonly_utf8_to_winpath("\\driveless\\absolute"), L""); + // Though valid in cmd.exe, drive-relative paths are not supported. + ASSERT_EQ(testonly_utf8_to_winpath("c:foo"), L""); + ASSERT_EQ(testonly_utf8_to_winpath("c:/foo"), L"\\\\?\\c:\\foo"); + ASSERT_EQ(testonly_utf8_to_winpath("\\\\?\\C:\\foo"), L"\\\\?\\C:\\foo"); +} + +TEST_F(IoWin32Test, Utf8Utf16ConversionTest) { + string mbs; + wstring wcs; + ASSERT_TRUE(strings::utf8_to_wcs(kUtf8Text, &wcs)); + ASSERT_TRUE(strings::wcs_to_utf8(kUtf16Text, &mbs)); + ASSERT_EQ(wcs, kUtf16Text); + ASSERT_EQ(mbs, kUtf8Text); +} + +} // namespace +} // namespace win32 +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // defined(_WIN32) + diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/logging.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/logging.h new file mode 100644 index 000000000..f69605d9f --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/logging.h @@ -0,0 +1,237 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_LOGGING_H_ +#define GOOGLE_PROTOBUF_STUBS_LOGGING_H_ + +#include +#include + +// =================================================================== +// emulates google3/base/logging.h + +namespace google { +namespace protobuf { + +enum LogLevel { + LOGLEVEL_INFO, // Informational. This is never actually used by + // libprotobuf. + LOGLEVEL_WARNING, // Warns about issues that, although not technically a + // problem now, could cause problems in the future. For + // example, a // warning will be printed when parsing a + // message that is near the message size limit. + LOGLEVEL_ERROR, // An error occurred which should never happen during + // normal use. + LOGLEVEL_FATAL, // An error occurred from which the library cannot + // recover. This usually indicates a programming error + // in the code which calls the library, especially when + // compiled in debug mode. + +#ifdef NDEBUG + LOGLEVEL_DFATAL = LOGLEVEL_ERROR +#else + LOGLEVEL_DFATAL = LOGLEVEL_FATAL +#endif +}; + +class StringPiece; +namespace util { +class Status; +} +class uint128; +namespace internal { + +class LogFinisher; + +class LIBPROTOBUF_EXPORT LogMessage { + public: + LogMessage(LogLevel level, const char* filename, int line); + ~LogMessage(); + + LogMessage& operator<<(const std::string& value); + LogMessage& operator<<(const char* value); + LogMessage& operator<<(char value); + LogMessage& operator<<(int value); + LogMessage& operator<<(uint value); + LogMessage& operator<<(long value); + LogMessage& operator<<(unsigned long value); + LogMessage& operator<<(long long value); + LogMessage& operator<<(unsigned long long value); + LogMessage& operator<<(double value); + LogMessage& operator<<(void* value); + LogMessage& operator<<(const StringPiece& value); + LogMessage& operator<<(const ::google::protobuf::util::Status& status); + LogMessage& operator<<(const uint128& value); + + private: + friend class LogFinisher; + void Finish(); + + LogLevel level_; + const char* filename_; + int line_; + std::string message_; +}; + +// Used to make the entire "LOG(BLAH) << etc." expression have a void return +// type and print a newline after each message. +class LIBPROTOBUF_EXPORT LogFinisher { + public: + void operator=(LogMessage& other); +}; + +template +bool IsOk(T status) { return status.ok(); } +template<> +inline bool IsOk(bool status) { return status; } + +} // namespace internal + +// Undef everything in case we're being mixed with some other Google library +// which already defined them itself. Presumably all Google libraries will +// support the same syntax for these so it should not be a big deal if they +// end up using our definitions instead. +#undef GOOGLE_LOG +#undef GOOGLE_LOG_IF + +#undef GOOGLE_CHECK +#undef GOOGLE_CHECK_OK +#undef GOOGLE_CHECK_EQ +#undef GOOGLE_CHECK_NE +#undef GOOGLE_CHECK_LT +#undef GOOGLE_CHECK_LE +#undef GOOGLE_CHECK_GT +#undef GOOGLE_CHECK_GE +#undef GOOGLE_CHECK_NOTNULL + +#undef GOOGLE_DLOG +#undef GOOGLE_DCHECK +#undef GOOGLE_DCHECK_OK +#undef GOOGLE_DCHECK_EQ +#undef GOOGLE_DCHECK_NE +#undef GOOGLE_DCHECK_LT +#undef GOOGLE_DCHECK_LE +#undef GOOGLE_DCHECK_GT +#undef GOOGLE_DCHECK_GE + +#define GOOGLE_LOG(LEVEL) \ + ::google::protobuf::internal::LogFinisher() = \ + ::google::protobuf::internal::LogMessage( \ + ::google::protobuf::LOGLEVEL_##LEVEL, __FILE__, __LINE__) +#define GOOGLE_LOG_IF(LEVEL, CONDITION) \ + !(CONDITION) ? (void)0 : GOOGLE_LOG(LEVEL) + +#define GOOGLE_CHECK(EXPRESSION) \ + GOOGLE_LOG_IF(FATAL, !(EXPRESSION)) << "CHECK failed: " #EXPRESSION ": " +#define GOOGLE_CHECK_OK(A) GOOGLE_CHECK(::google::protobuf::internal::IsOk(A)) +#define GOOGLE_CHECK_EQ(A, B) GOOGLE_CHECK((A) == (B)) +#define GOOGLE_CHECK_NE(A, B) GOOGLE_CHECK((A) != (B)) +#define GOOGLE_CHECK_LT(A, B) GOOGLE_CHECK((A) < (B)) +#define GOOGLE_CHECK_LE(A, B) GOOGLE_CHECK((A) <= (B)) +#define GOOGLE_CHECK_GT(A, B) GOOGLE_CHECK((A) > (B)) +#define GOOGLE_CHECK_GE(A, B) GOOGLE_CHECK((A) >= (B)) + +namespace internal { +template +T* CheckNotNull(const char* /* file */, int /* line */, + const char* name, T* val) { + if (val == NULL) { + GOOGLE_LOG(FATAL) << name; + } + return val; +} +} // namespace internal +#define GOOGLE_CHECK_NOTNULL(A) \ + ::google::protobuf::internal::CheckNotNull(\ + __FILE__, __LINE__, "'" #A "' must not be NULL", (A)) + +#ifdef NDEBUG + +#define GOOGLE_DLOG(LEVEL) GOOGLE_LOG_IF(LEVEL, false) + +#define GOOGLE_DCHECK(EXPRESSION) while(false) GOOGLE_CHECK(EXPRESSION) +#define GOOGLE_DCHECK_OK(E) GOOGLE_DCHECK(::google::protobuf::internal::IsOk(E)) +#define GOOGLE_DCHECK_EQ(A, B) GOOGLE_DCHECK((A) == (B)) +#define GOOGLE_DCHECK_NE(A, B) GOOGLE_DCHECK((A) != (B)) +#define GOOGLE_DCHECK_LT(A, B) GOOGLE_DCHECK((A) < (B)) +#define GOOGLE_DCHECK_LE(A, B) GOOGLE_DCHECK((A) <= (B)) +#define GOOGLE_DCHECK_GT(A, B) GOOGLE_DCHECK((A) > (B)) +#define GOOGLE_DCHECK_GE(A, B) GOOGLE_DCHECK((A) >= (B)) + +#else // NDEBUG + +#define GOOGLE_DLOG GOOGLE_LOG + +#define GOOGLE_DCHECK GOOGLE_CHECK +#define GOOGLE_DCHECK_OK GOOGLE_CHECK_OK +#define GOOGLE_DCHECK_EQ GOOGLE_CHECK_EQ +#define GOOGLE_DCHECK_NE GOOGLE_CHECK_NE +#define GOOGLE_DCHECK_LT GOOGLE_CHECK_LT +#define GOOGLE_DCHECK_LE GOOGLE_CHECK_LE +#define GOOGLE_DCHECK_GT GOOGLE_CHECK_GT +#define GOOGLE_DCHECK_GE GOOGLE_CHECK_GE + +#endif // !NDEBUG + +typedef void LogHandler(LogLevel level, const char* filename, int line, + const std::string& message); + +// The protobuf library sometimes writes warning and error messages to +// stderr. These messages are primarily useful for developers, but may +// also help end users figure out a problem. If you would prefer that +// these messages be sent somewhere other than stderr, call SetLogHandler() +// to set your own handler. This returns the old handler. Set the handler +// to NULL to ignore log messages (but see also LogSilencer, below). +// +// Obviously, SetLogHandler is not thread-safe. You should only call it +// at initialization time, and probably not from library code. If you +// simply want to suppress log messages temporarily (e.g. because you +// have some code that tends to trigger them frequently and you know +// the warnings are not important to you), use the LogSilencer class +// below. +LIBPROTOBUF_EXPORT LogHandler* SetLogHandler(LogHandler* new_func); + +// Create a LogSilencer if you want to temporarily suppress all log +// messages. As long as any LogSilencer objects exist, non-fatal +// log messages will be discarded (the current LogHandler will *not* +// be called). Constructing a LogSilencer is thread-safe. You may +// accidentally suppress log messages occurring in another thread, but +// since messages are generally for debugging purposes only, this isn't +// a big deal. If you want to intercept log messages, use SetLogHandler(). +class LIBPROTOBUF_EXPORT LogSilencer { + public: + LogSilencer(); + ~LogSilencer(); +}; + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_LOGGING_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/macros.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/macros.h new file mode 100644 index 000000000..0e9a9ec19 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/macros.h @@ -0,0 +1,168 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +#ifndef GOOGLE_PROTOBUF_MACROS_H__ +#define GOOGLE_PROTOBUF_MACROS_H__ + +#include + +namespace google { +namespace protobuf { + +#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS +#define GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeName) \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +#undef GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS +#define GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ + TypeName(); \ + TypeName(const TypeName&); \ + void operator=(const TypeName&) + +// =================================================================== +// from google3/base/basictypes.h + +// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr. +// The expression is a compile-time constant, and therefore can be +// used in defining new arrays, for example. +// +// GOOGLE_ARRAYSIZE catches a few type errors. If you see a compiler error +// +// "warning: division by zero in ..." +// +// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer. +// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays. +// +// The following comments are on the implementation details, and can +// be ignored by the users. +// +// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in +// the array) and sizeof(*(arr)) (the # of bytes in one array +// element). If the former is divisible by the latter, perhaps arr is +// indeed an array, in which case the division result is the # of +// elements in the array. Otherwise, arr cannot possibly be an array, +// and we generate a compiler error to prevent the code from +// compiling. +// +// Since the size of bool is implementation-defined, we need to cast +// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final +// result has type size_t. +// +// This macro is not perfect as it wrongfully accepts certain +// pointers, namely where the pointer size is divisible by the pointee +// size. Since all our code has to go through a 32-bit compiler, +// where a pointer is 4 bytes, this means all pointers to a type whose +// size is 3 or greater than 4 will be (righteously) rejected. +// +// Kudos to Jorg Brown for this simple and elegant implementation. + +#undef GOOGLE_ARRAYSIZE +#define GOOGLE_ARRAYSIZE(a) \ + ((sizeof(a) / sizeof(*(a))) / \ + static_cast(!(sizeof(a) % sizeof(*(a))))) + +// The COMPILE_ASSERT macro can be used to verify that a compile time +// expression is true. For example, you could use it to verify the +// size of a static array: +// +// COMPILE_ASSERT(ARRAYSIZE(content_type_names) == CONTENT_NUM_TYPES, +// content_type_names_incorrect_size); +// +// or to make sure a struct is smaller than a certain size: +// +// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large); +// +// The second argument to the macro is the name of the variable. If +// the expression is false, most compilers will issue a warning/error +// containing the name of the variable. + +namespace internal { + +template +struct CompileAssert { +}; + +} // namespace internal + +#undef GOOGLE_COMPILE_ASSERT +#if __cplusplus >= 201103L +#define GOOGLE_COMPILE_ASSERT(expr, msg) static_assert(expr, #msg) +#else +#define GOOGLE_COMPILE_ASSERT(expr, msg) \ + ::google::protobuf::internal::CompileAssert<(bool(expr))> \ + msg[bool(expr) ? 1 : -1]; \ + (void)msg +// Implementation details of COMPILE_ASSERT: +// +// - COMPILE_ASSERT works by defining an array type that has -1 +// elements (and thus is invalid) when the expression is false. +// +// - The simpler definition +// +// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1] +// +// does not work, as gcc supports variable-length arrays whose sizes +// are determined at run-time (this is gcc's extension and not part +// of the C++ standard). As a result, gcc fails to reject the +// following code with the simple definition: +// +// int foo; +// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is +// // not a compile-time constant. +// +// - By using the type CompileAssert<(bool(expr))>, we ensures that +// expr is a compile-time constant. (Template arguments must be +// determined at compile-time.) +// +// - The outter parentheses in CompileAssert<(bool(expr))> are necessary +// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written +// +// CompileAssert +// +// instead, these compilers will refuse to compile +// +// COMPILE_ASSERT(5 > 0, some_message); +// +// (They seem to think the ">" in "5 > 0" marks the end of the +// template argument list.) +// +// - The array size is (bool(expr) ? 1 : -1), instead of simply +// +// ((expr) ? 1 : -1). +// +// This is to avoid running into a bug in MS VC 7.1, which +// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1. +#endif // __cplusplus >= 201103L + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_MACROS_H__ diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/map_util.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/map_util.h similarity index 98% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/map_util.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/map_util.h index 7495cb6ae..3e6d381f4 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/map_util.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/map_util.h @@ -208,7 +208,7 @@ typename Collection::value_type::second_type::element_type& FindLinkedPtrOrDie(const Collection& collection, const typename Collection::value_type::first_type& key) { typename Collection::const_iterator it = collection.find(key); - CHECK(it != collection.end()) << "key not found: " << key; + GOOGLE_CHECK(it != collection.end()) << "key not found: " << key; // Since linked_ptr::operator*() is a const member returning a non const, // we do not need a version of this function taking a non const collection. return *it->second; @@ -337,14 +337,15 @@ bool InsertIfNotPresent( template void InsertOrDie(Collection* const collection, const typename Collection::value_type& value) { - CHECK(InsertIfNotPresent(collection, value)) << "duplicate value: " << value; + GOOGLE_CHECK(InsertIfNotPresent(collection, value)) + << "duplicate value: " << value; } // Same as above except doesn't log the value on error. template void InsertOrDieNoPrint(Collection* const collection, const typename Collection::value_type& value) { - CHECK(InsertIfNotPresent(collection, value)) << "duplicate value."; + GOOGLE_CHECK(InsertIfNotPresent(collection, value)) << "duplicate value."; } // Inserts the key-value pair into the collection. Dies if key was already @@ -353,7 +354,6 @@ template void InsertOrDie(Collection* const collection, const typename Collection::value_type::first_type& key, const typename Collection::value_type::second_type& data) { - typedef typename Collection::value_type value_type; GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key: " << key; } @@ -364,7 +364,6 @@ void InsertOrDieNoPrint( Collection* const collection, const typename Collection::value_type::first_type& key, const typename Collection::value_type::second_type& data) { - typedef typename Collection::value_type value_type; GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key."; } @@ -655,7 +654,8 @@ InsertOrReturnExisting( // delete EraseKeyReturnValuePtr(&my_map, "abc"); // // Use returned value: -// scoped_ptr value_ptr(EraseKeyReturnValuePtr(&my_map, "abc")); +// std::unique_ptr value_ptr( +// EraseKeyReturnValuePtr(&my_map, "abc")); // if (value_ptr.get()) // value_ptr->DoSomething(); // @@ -709,7 +709,7 @@ void AppendKeysFromMap(const MapContainer& map_container, // without the complexity of a SFINAE-based solution.) template void AppendKeysFromMap(const MapContainer& map_container, - vector* key_container) { + std::vector* key_container) { GOOGLE_CHECK(key_container != NULL); // We now have the opportunity to call reserve(). Calling reserve() every // time is a bad idea for some use cases: libstdc++'s implementation of @@ -753,7 +753,7 @@ void AppendValuesFromMap(const MapContainer& map_container, // without the complexity of a SFINAE-based solution.) template void AppendValuesFromMap(const MapContainer& map_container, - vector* value_container) { + std::vector* value_container) { GOOGLE_CHECK(value_container != NULL); // See AppendKeysFromMap for why this is done. if (value_container->empty()) { diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mathlimits.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mathlimits.cc new file mode 100644 index 000000000..0373b2bb9 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mathlimits.cc @@ -0,0 +1,144 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// All Rights Reserved. +// +// Author: Maxim Lifantsev +// + +#include + +#include + +namespace google { +namespace protobuf { + +// MSVC++ 2005 and older compilers think the header declaration was a +// definition, and erroneously flag these as a duplicate definition. +#if defined(COMPILER_MSVC) || __cpluscplus < 201103L + +#define DEF_COMMON_LIMITS(Type) +#define DEF_UNSIGNED_INT_LIMITS(Type) +#define DEF_SIGNED_INT_LIMITS(Type) +#define DEF_PRECISION_LIMITS(Type) + +#else + +#define DEF_COMMON_LIMITS(Type) \ +const bool MathLimits::kIsSigned; \ +const bool MathLimits::kIsInteger; \ +const int MathLimits::kMin10Exp; \ +const int MathLimits::kMax10Exp; + +#define DEF_UNSIGNED_INT_LIMITS(Type) \ +DEF_COMMON_LIMITS(Type) \ +const Type MathLimits::kPosMin; \ +const Type MathLimits::kPosMax; \ +const Type MathLimits::kMin; \ +const Type MathLimits::kMax; \ +const Type MathLimits::kEpsilon; \ +const Type MathLimits::kStdError; + +#define DEF_SIGNED_INT_LIMITS(Type) \ +DEF_UNSIGNED_INT_LIMITS(Type) \ +const Type MathLimits::kNegMin; \ +const Type MathLimits::kNegMax; + +#define DEF_PRECISION_LIMITS(Type) \ +const int MathLimits::kPrecisionDigits; + +#endif // not COMPILER_MSVC + +// http://en.wikipedia.org/wiki/Quadruple_precision_floating-point_format#Double-double_arithmetic +// With some compilers (gcc 4.6.x) on some platforms (powerpc64), +// "long double" is implemented as a pair of double: "double double" format. +// This causes a problem with epsilon (eps). +// eps is the smallest positive number such that 1.0 + eps > 1.0 +// +// Normal format: 1.0 + e = 1.0...01 // N-1 zeros for N fraction bits +// D-D format: 1.0 + e = 1.000...0001 // epsilon can be very small +// +// In the normal format, 1.0 + e has to fit in one stretch of bits. +// The maximum rounding error is half of eps. +// +// In the double-double format, 1.0 + e splits across two doubles: +// 1.0 in the high double, e in the low double, and they do not have to +// be contiguous. The maximum rounding error on a value close to 1.0 is +// much larger than eps. +// +// Some code checks for errors by comparing a computed value to a golden +// value +/- some multiple of the maximum rounding error. The maximum +// rounding error is not available so we use eps as an approximation +// instead. That fails when long double is in the double-double format. +// Therefore, we define kStdError as a multiple of +// max(DBL_EPSILON * DBL_EPSILON, kEpsilon) rather than a multiple of kEpsilon. + +#define DEF_FP_LIMITS(Type, PREFIX) \ +DEF_COMMON_LIMITS(Type) \ +const Type MathLimits::kPosMin = PREFIX##_MIN; \ +const Type MathLimits::kPosMax = PREFIX##_MAX; \ +const Type MathLimits::kMin = -MathLimits::kPosMax; \ +const Type MathLimits::kMax = MathLimits::kPosMax; \ +const Type MathLimits::kNegMin = -MathLimits::kPosMin; \ +const Type MathLimits::kNegMax = -MathLimits::kPosMax; \ +const Type MathLimits::kEpsilon = PREFIX##_EPSILON; \ +/* 32 is 5 bits of mantissa error; should be adequate for common errors */ \ +const Type MathLimits::kStdError = \ + 32 * (DBL_EPSILON * DBL_EPSILON > MathLimits::kEpsilon \ + ? DBL_EPSILON * DBL_EPSILON : MathLimits::kEpsilon); \ +DEF_PRECISION_LIMITS(Type) \ +const Type MathLimits::kNaN = HUGE_VAL - HUGE_VAL; \ +const Type MathLimits::kPosInf = HUGE_VAL; \ +const Type MathLimits::kNegInf = -HUGE_VAL; + +// The following are *not* casts! +DEF_SIGNED_INT_LIMITS(int8) +DEF_SIGNED_INT_LIMITS(int16) // NOLINT(readability/casting) +DEF_SIGNED_INT_LIMITS(int32) // NOLINT(readability/casting) +DEF_SIGNED_INT_LIMITS(int64) // NOLINT(readability/casting) +DEF_UNSIGNED_INT_LIMITS(uint8) +DEF_UNSIGNED_INT_LIMITS(uint16) // NOLINT(readability/casting) +DEF_UNSIGNED_INT_LIMITS(uint32) // NOLINT(readability/casting) +DEF_UNSIGNED_INT_LIMITS(uint64) // NOLINT(readability/casting) + +DEF_SIGNED_INT_LIMITS(long int) +DEF_UNSIGNED_INT_LIMITS(unsigned long int) + +DEF_FP_LIMITS(float, FLT) +DEF_FP_LIMITS(double, DBL) +DEF_FP_LIMITS(long double, LDBL); + +#undef DEF_COMMON_LIMITS +#undef DEF_SIGNED_INT_LIMITS +#undef DEF_UNSIGNED_INT_LIMITS +#undef DEF_FP_LIMITS +#undef DEF_PRECISION_LIMITS +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mathlimits.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mathlimits.h new file mode 100644 index 000000000..9c9d0e9a2 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mathlimits.h @@ -0,0 +1,303 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// All Rights Reserved. +// +// Author: Maxim Lifantsev +// +// Useful integer and floating point limits and type traits. +// +// This partially replaces/duplictes numeric_limits<> from . +// We get a Google-style class that we have a greater control over +// and thus can add new features to it or fix whatever happens to be broken in +// numeric_limits for the compilers we use. +// + +#ifndef UTIL_MATH_MATHLIMITS_H__ +#define UTIL_MATH_MATHLIMITS_H__ + +// Note that for Windows we do something different because it does not support +// the plain isinf and isnan. +#if __cplusplus >= 201103L +// GCC 4.9 has a bug that makes isinf and isnan ambigious when both +// and get pulled into the same translation unit. We use the ones in +// std:: namespace explicitly for C++11 +#include +#define GOOGLE_PROTOBUF_USE_STD_CMATH +#elif _GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC +// libstdc++ header undefines the global macros and put functions in +// std:: namespace even before C++11. Use the ones in std:: instead too. +#include +#define GOOGLE_PROTOBUF_USE_STD_CMATH +#else +#include +#endif + +#include + +#include + +#include + +// ========================================================================= // + +// Useful integer and floating point limits and type traits. +// This is just for the documentation; +// real members are defined in our specializations below. +namespace google { +namespace protobuf { +template struct MathLimits { + // Type name. + typedef T Type; + // Unsigned version of the Type with the same byte size. + // Same as Type for floating point and unsigned types. + typedef T UnsignedType; + // If the type supports negative values. + static const bool kIsSigned; + // If the type supports only integer values. + static const bool kIsInteger; + // Magnitude-wise smallest representable positive value. + static const Type kPosMin; + // Magnitude-wise largest representable positive value. + static const Type kPosMax; + // Smallest representable value. + static const Type kMin; + // Largest representable value. + static const Type kMax; + // Magnitude-wise smallest representable negative value. + // Present only if kIsSigned. + static const Type kNegMin; + // Magnitude-wise largest representable negative value. + // Present only if kIsSigned. + static const Type kNegMax; + // Smallest integer x such that 10^x is representable. + static const int kMin10Exp; + // Largest integer x such that 10^x is representable. + static const int kMax10Exp; + // Smallest positive value such that Type(1) + kEpsilon != Type(1) + static const Type kEpsilon; + // Typical rounding error that is enough to cover + // a few simple floating-point operations. + // Slightly larger than kEpsilon to account for a few rounding errors. + // Is zero if kIsInteger. + static const Type kStdError; + // Number of decimal digits of mantissa precision. + // Present only if !kIsInteger. + static const int kPrecisionDigits; + // Not a number, i.e. result of 0/0. + // Present only if !kIsInteger. + static const Type kNaN; + // Positive infinity, i.e. result of 1/0. + // Present only if !kIsInteger. + static const Type kPosInf; + // Negative infinity, i.e. result of -1/0. + // Present only if !kIsInteger. + static const Type kNegInf; + + // NOTE: Special floating point values behave + // in a special (but mathematically-logical) way + // in terms of (in)equalty comparison and mathematical operations + // -- see out unittest for examples. + + // Special floating point value testers. + // Present in integer types for convenience. + static bool IsFinite(const Type x); + static bool IsNaN(const Type x); + static bool IsInf(const Type x); + static bool IsPosInf(const Type x); + static bool IsNegInf(const Type x); +}; + +// ========================================================================= // + +// All #define-s below are simply to refactor the declarations of +// MathLimits template specializations. +// They are all #undef-ined below. + +// The hoop-jumping in *_INT_(MAX|MIN) below is so that the compiler does not +// get an overflow while computing the constants. + +#define SIGNED_INT_MAX(Type) \ + (((Type(1) << (sizeof(Type)*8 - 2)) - 1) + (Type(1) << (sizeof(Type)*8 - 2))) + +#define SIGNED_INT_MIN(Type) \ + (-(Type(1) << (sizeof(Type)*8 - 2)) - (Type(1) << (sizeof(Type)*8 - 2))) + +#define UNSIGNED_INT_MAX(Type) \ + (((Type(1) << (sizeof(Type)*8 - 1)) - 1) + (Type(1) << (sizeof(Type)*8 - 1))) + +// Compile-time selected log10-related constants for integer types. +#define SIGNED_MAX_10_EXP(Type) \ + (sizeof(Type) == 1 ? 2 : ( \ + sizeof(Type) == 2 ? 4 : ( \ + sizeof(Type) == 4 ? 9 : ( \ + sizeof(Type) == 8 ? 18 : -1)))) + +#define UNSIGNED_MAX_10_EXP(Type) \ + (sizeof(Type) == 1 ? 2 : ( \ + sizeof(Type) == 2 ? 4 : ( \ + sizeof(Type) == 4 ? 9 : ( \ + sizeof(Type) == 8 ? 19 : -1)))) + +#define DECL_INT_LIMIT_FUNCS \ + static bool IsFinite(const Type /*x*/) { return true; } \ + static bool IsNaN(const Type /*x*/) { return false; } \ + static bool IsInf(const Type /*x*/) { return false; } \ + static bool IsPosInf(const Type /*x*/) { return false; } \ + static bool IsNegInf(const Type /*x*/) { return false; } + +#define DECL_SIGNED_INT_LIMITS(IntType, UnsignedIntType) \ +template<> \ +struct LIBPROTOBUF_EXPORT MathLimits { \ + typedef IntType Type; \ + typedef UnsignedIntType UnsignedType; \ + static const bool kIsSigned = true; \ + static const bool kIsInteger = true; \ + static const Type kPosMin = 1; \ + static const Type kPosMax = SIGNED_INT_MAX(Type); \ + static const Type kMin = SIGNED_INT_MIN(Type); \ + static const Type kMax = kPosMax; \ + static const Type kNegMin = -1; \ + static const Type kNegMax = kMin; \ + static const int kMin10Exp = 0; \ + static const int kMax10Exp = SIGNED_MAX_10_EXP(Type); \ + static const Type kEpsilon = 1; \ + static const Type kStdError = 0; \ + DECL_INT_LIMIT_FUNCS \ +}; + +#define DECL_UNSIGNED_INT_LIMITS(IntType) \ +template<> \ +struct LIBPROTOBUF_EXPORT MathLimits { \ + typedef IntType Type; \ + typedef IntType UnsignedType; \ + static const bool kIsSigned = false; \ + static const bool kIsInteger = true; \ + static const Type kPosMin = 1; \ + static const Type kPosMax = UNSIGNED_INT_MAX(Type); \ + static const Type kMin = 0; \ + static const Type kMax = kPosMax; \ + static const int kMin10Exp = 0; \ + static const int kMax10Exp = UNSIGNED_MAX_10_EXP(Type); \ + static const Type kEpsilon = 1; \ + static const Type kStdError = 0; \ + DECL_INT_LIMIT_FUNCS \ +}; + +DECL_SIGNED_INT_LIMITS(signed char, unsigned char) +DECL_SIGNED_INT_LIMITS(signed short int, unsigned short int) +DECL_SIGNED_INT_LIMITS(signed int, unsigned int) +DECL_SIGNED_INT_LIMITS(signed long int, unsigned long int) +DECL_SIGNED_INT_LIMITS(signed long long int, unsigned long long int) +DECL_UNSIGNED_INT_LIMITS(unsigned char) +DECL_UNSIGNED_INT_LIMITS(unsigned short int) +DECL_UNSIGNED_INT_LIMITS(unsigned int) +DECL_UNSIGNED_INT_LIMITS(unsigned long int) +DECL_UNSIGNED_INT_LIMITS(unsigned long long int) + +#undef DECL_SIGNED_INT_LIMITS +#undef DECL_UNSIGNED_INT_LIMITS +#undef SIGNED_INT_MAX +#undef SIGNED_INT_MIN +#undef UNSIGNED_INT_MAX +#undef SIGNED_MAX_10_EXP +#undef UNSIGNED_MAX_10_EXP +#undef DECL_INT_LIMIT_FUNCS + +// For non-Windows builds we use the std:: versions of isinf and isnan if they +// are available; see the comment about at the top of this file for the +// details on why we need to do this. +#ifdef GOOGLE_PROTOBUF_USE_STD_CMATH +#define ISINF std::isinf +#define ISNAN std::isnan +#else +#define ISINF isinf +#define ISNAN isnan +#endif + +// ========================================================================= // +#if WIN32 && !__MINGW32__ // Lacks built-in isnan() and isinf() +#define DECL_FP_LIMIT_FUNCS \ + static bool IsFinite(const Type x) { return _finite(x); } \ + static bool IsNaN(const Type x) { return _isnan(x); } \ + static bool IsInf(const Type x) { return (_fpclass(x) & (_FPCLASS_NINF | _FPCLASS_PINF)) != 0; } \ + static bool IsPosInf(const Type x) { return _fpclass(x) == _FPCLASS_PINF; } \ + static bool IsNegInf(const Type x) { return _fpclass(x) == _FPCLASS_NINF; } +#else +#define DECL_FP_LIMIT_FUNCS \ + static bool IsFinite(const Type x) { return !ISINF(x) && !ISNAN(x); } \ + static bool IsNaN(const Type x) { return ISNAN(x); } \ + static bool IsInf(const Type x) { return ISINF(x); } \ + static bool IsPosInf(const Type x) { return ISINF(x) && x > 0; } \ + static bool IsNegInf(const Type x) { return ISINF(x) && x < 0; } +#endif + +// We can't put floating-point constant values in the header here because +// such constants are not considered to be primitive-type constants by gcc. +// CAVEAT: Hence, they are going to be initialized only during +// the global objects construction time. +#define DECL_FP_LIMITS(FP_Type, PREFIX) \ +template<> \ +struct LIBPROTOBUF_EXPORT MathLimits { \ + typedef FP_Type Type; \ + typedef FP_Type UnsignedType; \ + static const bool kIsSigned = true; \ + static const bool kIsInteger = false; \ + static const Type kPosMin; \ + static const Type kPosMax; \ + static const Type kMin; \ + static const Type kMax; \ + static const Type kNegMin; \ + static const Type kNegMax; \ + static const int kMin10Exp = PREFIX##_MIN_10_EXP; \ + static const int kMax10Exp = PREFIX##_MAX_10_EXP; \ + static const Type kEpsilon; \ + static const Type kStdError; \ + static const int kPrecisionDigits = PREFIX##_DIG; \ + static const Type kNaN; \ + static const Type kPosInf; \ + static const Type kNegInf; \ + DECL_FP_LIMIT_FUNCS \ +}; + +DECL_FP_LIMITS(float, FLT) +DECL_FP_LIMITS(double, DBL) +DECL_FP_LIMITS(long double, LDBL) + +#undef ISINF +#undef ISNAN +#undef DECL_FP_LIMITS +#undef DECL_FP_LIMIT_FUNCS + +// ========================================================================= // +} // namespace protobuf +} // namespace google + +#endif // UTIL_MATH_MATHLIMITS_H__ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mathutil.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mathutil.h new file mode 100644 index 000000000..8a9f69a0b --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mathutil.h @@ -0,0 +1,141 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. +#ifndef GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ +#define GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ + +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +template +bool AlmostEquals(T a, T b) { + return a == b; +} +template<> +inline bool AlmostEquals(float a, float b) { + return fabs(a - b) < 32 * FLT_EPSILON; +} + +template<> +inline bool AlmostEquals(double a, double b) { + return fabs(a - b) < 32 * DBL_EPSILON; +} +} // namespace internal + +class MathUtil { + public: + template + static T Sign(T value) { + if (value == T(0) || MathLimits::IsNaN(value)) { + return value; + } + return value > T(0) ? 1 : -1; + } + + template + static bool AlmostEquals(T a, T b) { + return ::google::protobuf::internal::AlmostEquals(a, b); + } + + // Largest of two values. + // Works correctly for special floating point values. + // Note: 0.0 and -0.0 are not differentiated by Max (Max(0.0, -0.0) is -0.0), + // which should be OK because, although they (can) have different + // bit representation, they are observably the same when examined + // with arithmetic and (in)equality operators. + template + static T Max(const T x, const T y) { + return MathLimits::IsNaN(x) || x > y ? x : y; + } + + // Absolute value of x + // Works correctly for unsigned types and + // for special floating point values. + // Note: 0.0 and -0.0 are not differentiated by Abs (Abs(0.0) is -0.0), + // which should be OK: see the comment for Max above. + template + static T Abs(const T x) { + return x > T(0) ? x : -x; + } + + // Absolute value of the difference between two numbers. + // Works correctly for signed types and special floating point values. + template + static typename MathLimits::UnsignedType AbsDiff(const T x, const T y) { + // Carries out arithmetic as unsigned to avoid overflow. + typedef typename MathLimits::UnsignedType R; + return x > y ? R(x) - R(y) : R(y) - R(x); + } + + // If two (usually floating point) numbers are within a certain + // fraction of their magnitude or within a certain absolute margin of error. + // This is the same as the following but faster: + // WithinFraction(x, y, fraction) || WithinMargin(x, y, margin) + // E.g. WithinFraction(0.0, 1e-10, 1e-5) is false but + // WithinFractionOrMargin(0.0, 1e-10, 1e-5, 1e-5) is true. + template + static bool WithinFractionOrMargin(const T x, const T y, + const T fraction, const T margin); +}; + +template +bool MathUtil::WithinFractionOrMargin(const T x, const T y, + const T fraction, const T margin) { + // Not just "0 <= fraction" to fool the compiler for unsigned types. + GOOGLE_DCHECK((T(0) < fraction || T(0) == fraction) && + fraction < T(1) && + margin >= T(0)); + + // Template specialization will convert the if() condition to a constant, + // which will cause the compiler to generate code for either the "if" part + // or the "then" part. In this way we avoid a compiler warning + // about a potential integer overflow in crosstool v12 (gcc 4.3.1). + if (MathLimits::kIsInteger) { + return x == y; + } else { + // IsFinite checks are to make kPosInf and kNegInf not within fraction + if (!MathLimits::IsFinite(x) && !MathLimits::IsFinite(y)) { + return false; + } + T relative_margin = static_cast(fraction * Max(Abs(x), Abs(y))); + return AbsDiff(x, y) <= Max(margin, relative_margin); + } +} + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mutex.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mutex.h new file mode 100644 index 000000000..b9b7d2e1b --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/mutex.h @@ -0,0 +1,130 @@ +// Copyright (c) 2006, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_MUTEX_H_ +#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_ + +#include + +#include + +// =================================================================== +// emulates google3/base/mutex.h +namespace google { +namespace protobuf { +namespace internal { + +#define GOOGLE_PROTOBUF_LINKER_INITIALIZED + +// Mutex is a natural type to wrap. As both google and other organization have +// specialized mutexes. gRPC also provides an injection mechanism for custom +// mutexes. +class LIBPROTOBUF_EXPORT WrappedMutex { + public: + WrappedMutex() = default; + void Lock() { mu_.lock(); } + void Unlock() { mu_.unlock(); } + // Crash if this Mutex is not held exclusively by this thread. + // May fail to crash when it should; will never crash when it should not. + void AssertHeld() const {} + + private: + std::mutex mu_; +}; + +using Mutex = WrappedMutex; + +// MutexLock(mu) acquires mu when constructed and releases it when destroyed. +class LIBPROTOBUF_EXPORT MutexLock { + public: + explicit MutexLock(Mutex *mu) : mu_(mu) { this->mu_->Lock(); } + ~MutexLock() { this->mu_->Unlock(); } + private: + Mutex *const mu_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLock); +}; + +// TODO(kenton): Implement these? Hard to implement portably. +typedef MutexLock ReaderMutexLock; +typedef MutexLock WriterMutexLock; + +// MutexLockMaybe is like MutexLock, but is a no-op when mu is NULL. +class LIBPROTOBUF_EXPORT MutexLockMaybe { + public: + explicit MutexLockMaybe(Mutex *mu) : + mu_(mu) { if (this->mu_ != NULL) { this->mu_->Lock(); } } + ~MutexLockMaybe() { if (this->mu_ != NULL) { this->mu_->Unlock(); } } + private: + Mutex *const mu_; + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe); +}; + +#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL) +template +class ThreadLocalStorage { + public: + ThreadLocalStorage() { + pthread_key_create(&key_, &ThreadLocalStorage::Delete); + } + ~ThreadLocalStorage() { + pthread_key_delete(key_); + } + T* Get() { + T* result = static_cast(pthread_getspecific(key_)); + if (result == NULL) { + result = new T(); + pthread_setspecific(key_, result); + } + return result; + } + private: + static void Delete(void* value) { + delete static_cast(value); + } + pthread_key_t key_; + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage); +}; +#endif + +} // namespace internal + +// We made these internal so that they would show up as such in the docs, +// but we don't want to stick "internal::" in front of them everywhere. +using internal::Mutex; +using internal::MutexLock; +using internal::ReaderMutexLock; +using internal::WriterMutexLock; +using internal::MutexLockMaybe; + + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_MUTEX_H_ diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/once.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/once.h similarity index 75% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/once.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/once.h index cc62bbaab..f3835ccd0 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/once.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/once.h @@ -78,87 +78,51 @@ #ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__ #define GOOGLE_PROTOBUF_STUBS_ONCE_H__ -#include -#include +#include +#include namespace google { namespace protobuf { +namespace internal { -#ifdef GOOGLE_PROTOBUF_NO_THREAD_SAFETY - -typedef bool ProtobufOnceType; - -#define GOOGLE_PROTOBUF_ONCE_INIT false - -inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) { - if (!*once) { - *once = true; - init_func(); - } +using once_flag = std::once_flag; +template +void call_once(Args&&... args ) { + std::call_once(std::forward(args)...); } -template -inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg), - Arg arg) { - if (!*once) { - *once = true; - init_func(arg); - } -} +} // namespace internal -#else - -enum { - ONCE_STATE_UNINITIALIZED = 0, - ONCE_STATE_EXECUTING_CLOSURE = 1, - ONCE_STATE_DONE = 2 -}; - -typedef internal::AtomicWord ProtobufOnceType; - -#define GOOGLE_PROTOBUF_ONCE_INIT ::google::protobuf::ONCE_STATE_UNINITIALIZED - -LIBPROTOBUF_EXPORT -void GoogleOnceInitImpl(ProtobufOnceType* once, Closure* closure); +// TODO(gerbens) remove this once third_party is fully extracted +using ProtobufOnceType = internal::once_flag; inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)()) { - if (internal::Acquire_Load(once) != ONCE_STATE_DONE) { - internal::FunctionClosure0 func(init_func, false); - GoogleOnceInitImpl(once, &func); - } + std::call_once(*once, init_func); } template -inline void GoogleOnceInit(ProtobufOnceType* once, void (*init_func)(Arg*), - Arg* arg) { - if (internal::Acquire_Load(once) != ONCE_STATE_DONE) { - internal::FunctionClosure1 func(init_func, false, arg); - GoogleOnceInitImpl(once, &func); - } +inline void GoogleOnceInitArg(ProtobufOnceType* once, void (*init_func)(Arg*), + Arg* arg) { + std::call_once(*once, init_func, arg); } -#endif // GOOGLE_PROTOBUF_NO_THREAD_SAFETY - class GoogleOnceDynamic { public: - GoogleOnceDynamic() : state_(GOOGLE_PROTOBUF_ONCE_INIT) { } - // If this->Init() has not been called before by any thread, // execute (*func_with_arg)(arg) then return. // Otherwise, wait until that prior invocation has finished // executing its function, then return. template void Init(void (*func_with_arg)(T*), T* arg) { - GoogleOnceInit(&this->state_, - func_with_arg, - arg); + GoogleOnceInitArg(&this->state_, func_with_arg, arg); } private: ProtobufOnceType state_; }; +#define GOOGLE_PROTOBUF_ONCE_TYPE ::google::protobuf::ProtobufOnceType #define GOOGLE_PROTOBUF_DECLARE_ONCE(NAME) \ - ::google::protobuf::ProtobufOnceType NAME = GOOGLE_PROTOBUF_ONCE_INIT + ::google::protobuf::ProtobufOnceType NAME } // namespace protobuf } // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/platform_macros.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/platform_macros.h similarity index 77% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/platform_macros.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/platform_macros.h index 7956d076d..c3a64dd2b 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/platform_macros.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/platform_macros.h @@ -31,8 +31,6 @@ #ifndef GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ #define GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ -#include - #define GOOGLE_PROTOBUF_PLATFORM_ERROR \ #error "Host platform was not detected as supported by protobuf" @@ -49,9 +47,12 @@ #elif defined(__QNX__) #define GOOGLE_PROTOBUF_ARCH_ARM_QNX 1 #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 -#elif defined(__ARMEL__) +#elif defined(_M_ARM) || defined(__ARMEL__) #define GOOGLE_PROTOBUF_ARCH_ARM 1 #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 +#elif defined(_M_ARM64) +#define GOOGLE_PROTOBUF_ARCH_ARM 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 #elif defined(__aarch64__) #define GOOGLE_PROTOBUF_ARCH_AARCH64 1 #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 @@ -67,11 +68,17 @@ #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 #elif defined(sparc) #define GOOGLE_PROTOBUF_ARCH_SPARC 1 -#ifdef SOLARIS_64BIT_ENABLED +#if defined(__sparc_v9__) || defined(__sparcv9) || defined(__arch64__) #define GOOGLE_PROTOBUF_ARCH_64_BIT 1 #else #define GOOGLE_PROTOBUF_ARCH_32_BIT 1 #endif +#elif defined(_POWER) || defined(__powerpc64__) || defined(__PPC64__) +#define GOOGLE_PROTOBUF_ARCH_POWER 1 +#define GOOGLE_PROTOBUF_ARCH_64_BIT 1 +#elif defined(__PPC__) +#define GOOGLE_PROTOBUF_ARCH_PPC 1 +#define GOOGLE_PROTOBUF_ARCH_32_BIT 1 #elif defined(__GNUC__) # if (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)) // We fallback to the generic Clang/GCC >= 4.7 implementation in atomicops.h @@ -92,12 +99,30 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR #if defined(__APPLE__) #define GOOGLE_PROTOBUF_OS_APPLE +#include +#if TARGET_OS_IPHONE +#define GOOGLE_PROTOBUF_OS_IPHONE +#endif +#elif defined(__EMSCRIPTEN__) +#define GOOGLE_PROTOBUF_OS_EMSCRIPTEN #elif defined(__native_client__) #define GOOGLE_PROTOBUF_OS_NACL #elif defined(sun) #define GOOGLE_PROTOBUF_OS_SOLARIS +#elif defined(_AIX) +#define GOOGLE_PROTOBUF_OS_AIX +#elif defined(__ANDROID__) +#define GOOGLE_PROTOBUF_OS_ANDROID #endif #undef GOOGLE_PROTOBUF_PLATFORM_ERROR +#if defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE) || defined(__OpenBSD__) +// Android ndk does not support the __thread keyword very well yet. Here +// we use pthread_key_create()/pthread_getspecific()/... methods for +// TLS support on android. +// iOS and OpenBSD also do not support the __thread keyword. +#define GOOGLE_PROTOBUF_NO_THREADLOCAL +#endif + #endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/port.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/port.h new file mode 100644 index 000000000..6b52305f9 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/port.h @@ -0,0 +1,542 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +#ifndef GOOGLE_PROTOBUF_STUBS_PORT_H_ +#define GOOGLE_PROTOBUF_STUBS_PORT_H_ + +#include +#include +#include +#include +#include +#if defined(__osf__) +// Tru64 lacks stdint.h, but has inttypes.h which defines a superset of +// what stdint.h would define. +#include +#elif !defined(_MSC_VER) +#include +#endif + +#include + +#undef PROTOBUF_LITTLE_ENDIAN +#ifdef _WIN32 + // Assuming windows is always little-endian. + // TODO(xiaofeng): The PROTOBUF_LITTLE_ENDIAN is not only used for + // optimization but also for correctness. We should define an + // different macro to test the big-endian code path in coded_stream. + #if !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif + #if _MSC_VER >= 1300 && !defined(__INTEL_COMPILER) + // If MSVC has "/RTCc" set, it will complain about truncating casts at + // runtime. This file contains some intentional truncating casts. + #pragma runtime_checks("c", off) + #endif +#else + #include // __BYTE_ORDER + #if defined(__OpenBSD__) + #include + #endif + #if ((defined(__LITTLE_ENDIAN__) && !defined(__BIG_ENDIAN__)) || \ + (defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(BYTE_ORDER) && BYTE_ORDER == LITTLE_ENDIAN)) && \ + !defined(PROTOBUF_DISABLE_LITTLE_ENDIAN_OPT_FOR_TEST) + #define PROTOBUF_LITTLE_ENDIAN 1 + #endif +#endif +#if defined(_MSC_VER) && defined(PROTOBUF_USE_DLLS) + #ifdef LIBPROTOBUF_EXPORTS + #define LIBPROTOBUF_EXPORT __declspec(dllexport) + #else + #define LIBPROTOBUF_EXPORT __declspec(dllimport) + #endif + #ifdef LIBPROTOC_EXPORTS + #define LIBPROTOC_EXPORT __declspec(dllexport) + #else + #define LIBPROTOC_EXPORT __declspec(dllimport) + #endif +#else + #define LIBPROTOBUF_EXPORT + #define LIBPROTOC_EXPORT +#endif + +// These #includes are for the byte swap functions declared later on. +#ifdef _MSC_VER +#include // NOLINT(build/include) +#include +#elif defined(__APPLE__) +#include +#elif defined(__GLIBC__) || defined(__BIONIC__) || defined(__CYGWIN__) +#include // IWYU pragma: export +#endif + +#define PROTOBUF_RUNTIME_DEPRECATED(message) + +// =================================================================== +// from google3/base/port.h + +#if (defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L || \ + (defined(_MSC_VER) && _MSC_VER >= 1900)) +// Define this to 1 if the code is compiled in C++11 mode; leave it +// undefined otherwise. Do NOT define it to 0 -- that causes +// '#ifdef LANG_CXX11' to behave differently from '#if LANG_CXX11'. +#define LANG_CXX11 1 +#endif + +#if LANG_CXX11 && !defined(__NVCC__) +#define PROTOBUF_CXX11 1 +#else +#define PROTOBUF_CXX11 0 +#endif + +#if PROTOBUF_CXX11 +#define PROTOBUF_FINAL final +#else +#define PROTOBUF_FINAL +#endif + +namespace google { +namespace protobuf { + +typedef unsigned int uint; + +#ifdef _MSC_VER +typedef signed __int8 int8; +typedef __int16 int16; +typedef __int32 int32; +typedef __int64 int64; + +typedef unsigned __int8 uint8; +typedef unsigned __int16 uint16; +typedef unsigned __int32 uint32; +typedef unsigned __int64 uint64; +#else +typedef int8_t int8; +typedef int16_t int16; +typedef int32_t int32; +typedef int64_t int64; + +typedef uint8_t uint8; +typedef uint16_t uint16; +typedef uint32_t uint32; +typedef uint64_t uint64; +#endif + +// long long macros to be used because gcc and vc++ use different suffixes, +// and different size specifiers in format strings +#undef GOOGLE_LONGLONG +#undef GOOGLE_ULONGLONG +#undef GOOGLE_LL_FORMAT + +#ifdef _MSC_VER +#define GOOGLE_LONGLONG(x) x##I64 +#define GOOGLE_ULONGLONG(x) x##UI64 +#define GOOGLE_LL_FORMAT "I64" // As in printf("%I64d", ...) +#else +// By long long, we actually mean int64. +#define GOOGLE_LONGLONG(x) x##LL +#define GOOGLE_ULONGLONG(x) x##ULL +// Used to format real long long integers. +#define GOOGLE_LL_FORMAT "ll" // As in "%lld". Note that "q" is poor form also. +#endif + +static const int32 kint32max = 0x7FFFFFFF; +static const int32 kint32min = -kint32max - 1; +static const int64 kint64max = GOOGLE_LONGLONG(0x7FFFFFFFFFFFFFFF); +static const int64 kint64min = -kint64max - 1; +static const uint32 kuint32max = 0xFFFFFFFFu; +static const uint64 kuint64max = GOOGLE_ULONGLONG(0xFFFFFFFFFFFFFFFF); + +// ------------------------------------------------------------------- +// Annotations: Some parts of the code have been annotated in ways that might +// be useful to some compilers or tools, but are not supported universally. +// You can #define these annotations yourself if the default implementation +// is not right for you. + +#ifndef GOOGLE_ATTRIBUTE_ALWAYS_INLINE +#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +// For functions we want to force inline. +// Introduced in gcc 3.1. +#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE __attribute__ ((always_inline)) +#else +// Other compilers will have to figure it out for themselves. +#define GOOGLE_ATTRIBUTE_ALWAYS_INLINE +#endif +#endif + +#define GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE GOOGLE_ATTRIBUTE_ALWAYS_INLINE + +#ifndef GOOGLE_ATTRIBUTE_NOINLINE +#if defined(__GNUC__) && (__GNUC__ > 3 ||(__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +// For functions we want to force not inline. +// Introduced in gcc 3.1. +#define GOOGLE_ATTRIBUTE_NOINLINE __attribute__ ((noinline)) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) +// Seems to have been around since at least Visual Studio 2005 +#define GOOGLE_ATTRIBUTE_NOINLINE __declspec(noinline) +#else +// Other compilers will have to figure it out for themselves. +#define GOOGLE_ATTRIBUTE_NOINLINE +#endif +#endif + +#define GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE GOOGLE_ATTRIBUTE_NOINLINE + +#ifndef GOOGLE_ATTRIBUTE_FUNC_ALIGN +#if defined(__clang__) || \ + defined(__GNUC__) && (__GNUC__ > 4 ||(__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) +// Function alignment attribute introduced in gcc 4.3 +#define GOOGLE_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__ ((aligned(bytes))) +#else +#define GOOGLE_ATTRIBUTE_FUNC_ALIGN(bytes) +#endif +#endif + +#define GOOGLE_PROTOBUF_ATTRIBUTE_FUNC_ALIGN(bytes) \ + GOOGLE_ATTRIBUTE_FUNC_ALIGN(bytes) + +#ifndef GOOGLE_PREDICT_TRUE +#ifdef __GNUC__ +// Provided at least since GCC 3.0. +#define GOOGLE_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) +#else +#define GOOGLE_PREDICT_TRUE(x) (x) +#endif +#endif + +#ifndef GOOGLE_PREDICT_FALSE +#ifdef __GNUC__ +// Provided at least since GCC 3.0. +#define GOOGLE_PREDICT_FALSE(x) (__builtin_expect(x, 0)) +#else +#define GOOGLE_PREDICT_FALSE(x) (x) +#endif +#endif + +#ifndef GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL +#ifdef __GNUC__ +#define GOOGLE_PROTOBUF_ATTRIBUTE_RETURNS_NONNULL \ + __attribute__((returns_nonnull)) +#endif +#endif + +// Delimits a block of code which may write to memory which is simultaneously +// written by other threads, but which has been determined to be thread-safe +// (e.g. because it is an idempotent write). +#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN +#define GOOGLE_SAFE_CONCURRENT_WRITES_BEGIN() +#endif +#ifndef GOOGLE_SAFE_CONCURRENT_WRITES_END +#define GOOGLE_SAFE_CONCURRENT_WRITES_END() +#endif + +#define GOOGLE_GUARDED_BY(x) +#define GOOGLE_ATTRIBUTE_COLD + +#ifdef GOOGLE_PROTOBUF_DONT_USE_UNALIGNED +# define GOOGLE_PROTOBUF_USE_UNALIGNED 0 +#else +# if defined(_M_X64) || defined(__x86_64__) || defined(_M_IX86) || defined(__i386__) +# define GOOGLE_PROTOBUF_USE_UNALIGNED 1 +# else +# define GOOGLE_PROTOBUF_USE_UNALIGNED 0 +# endif +#endif + +#define GOOGLE_PROTOBUF_ATTRIBUTE_COLD GOOGLE_ATTRIBUTE_COLD + +#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\ + defined(MEMORY_SANITIZER) + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus +uint16_t __sanitizer_unaligned_load16(const void *p); +uint32_t __sanitizer_unaligned_load32(const void *p); +uint64_t __sanitizer_unaligned_load64(const void *p); +void __sanitizer_unaligned_store16(void *p, uint16_t v); +void __sanitizer_unaligned_store32(void *p, uint32_t v); +void __sanitizer_unaligned_store64(void *p, uint64_t v); +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) { + return __sanitizer_unaligned_load16(p); +} + +inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) { + return __sanitizer_unaligned_load32(p); +} + +inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) { + return __sanitizer_unaligned_load64(p); +} + +inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) { + __sanitizer_unaligned_store16(p, v); +} + +inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) { + __sanitizer_unaligned_store32(p, v); +} + +inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) { + __sanitizer_unaligned_store64(p, v); +} + +#elif GOOGLE_PROTOBUF_USE_UNALIGNED + +#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast(_p)) +#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast(_p)) +#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast(_p)) + +#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast(_p) = (_val)) +#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast(_p) = (_val)) +#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast(_p) = (_val)) + +#else +inline uint16 GOOGLE_UNALIGNED_LOAD16(const void *p) { + uint16 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint32 GOOGLE_UNALIGNED_LOAD32(const void *p) { + uint32 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline uint64 GOOGLE_UNALIGNED_LOAD64(const void *p) { + uint64 t; + memcpy(&t, p, sizeof t); + return t; +} + +inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16 v) { + memcpy(p, &v, sizeof v); +} + +inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32 v) { + memcpy(p, &v, sizeof v); +} + +inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64 v) { + memcpy(p, &v, sizeof v); +} +#endif + +#if defined(GOOGLE_PROTOBUF_OS_NACL) \ + || (defined(__ANDROID__) && defined(__clang__) \ + && (__clang_major__ == 3 && __clang_minor__ == 8) \ + && (__clang_patchlevel__ < 275480)) +# define GOOGLE_PROTOBUF_USE_PORTABLE_LOG2 +#endif + +#if defined(_MSC_VER) +#define GOOGLE_THREAD_LOCAL __declspec(thread) +#else +#define GOOGLE_THREAD_LOCAL __thread +#endif + +// The following guarantees declaration of the byte swap functions. +#ifdef _MSC_VER +#define bswap_16(x) _byteswap_ushort(x) +#define bswap_32(x) _byteswap_ulong(x) +#define bswap_64(x) _byteswap_uint64(x) + +#elif defined(__APPLE__) +// Mac OS X / Darwin features +#define bswap_16(x) OSSwapInt16(x) +#define bswap_32(x) OSSwapInt32(x) +#define bswap_64(x) OSSwapInt64(x) + +#elif !defined(__GLIBC__) && !defined(__BIONIC__) && !defined(__CYGWIN__) + +static inline uint16 bswap_16(uint16 x) { + return static_cast(((x & 0xFF) << 8) | ((x & 0xFF00) >> 8)); +} +#define bswap_16(x) bswap_16(x) +static inline uint32 bswap_32(uint32 x) { + return (((x & 0xFF) << 24) | + ((x & 0xFF00) << 8) | + ((x & 0xFF0000) >> 8) | + ((x & 0xFF000000) >> 24)); +} +#define bswap_32(x) bswap_32(x) +static inline uint64 bswap_64(uint64 x) { + return (((x & GOOGLE_ULONGLONG(0xFF)) << 56) | + ((x & GOOGLE_ULONGLONG(0xFF00)) << 40) | + ((x & GOOGLE_ULONGLONG(0xFF0000)) << 24) | + ((x & GOOGLE_ULONGLONG(0xFF000000)) << 8) | + ((x & GOOGLE_ULONGLONG(0xFF00000000)) >> 8) | + ((x & GOOGLE_ULONGLONG(0xFF0000000000)) >> 24) | + ((x & GOOGLE_ULONGLONG(0xFF000000000000)) >> 40) | + ((x & GOOGLE_ULONGLONG(0xFF00000000000000)) >> 56)); +} +#define bswap_64(x) bswap_64(x) + +#endif + +// =================================================================== +// from google3/util/bits/bits.h + +class Bits { + public: + static uint32 Log2FloorNonZero(uint32 n) { +#if defined(__GNUC__) + return 31 ^ static_cast(__builtin_clz(n)); +#elif defined(_MSC_VER) + unsigned long where; + _BitScanReverse(&where, n); + return where; +#else + return Log2FloorNonZero_Portable(n); +#endif + } + + static uint32 Log2FloorNonZero64(uint64 n) { + // Older versions of clang run into an instruction-selection failure when + // it encounters __builtin_clzll: + // https://bugs.chromium.org/p/nativeclient/issues/detail?id=4395 + // This includes arm-nacl-clang and clang in older Android NDK versions. + // To work around this, when we build with those we use the portable + // implementation instead. +#if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_USE_PORTABLE_LOG2) + return 63 ^ static_cast(__builtin_clzll(n)); +#elif defined(_MSC_VER) && defined(_M_X64) + unsigned long where; + _BitScanReverse64(&where, n); + return where; +#else + return Log2FloorNonZero64_Portable(n); +#endif + } + private: + static int Log2FloorNonZero_Portable(uint32 n) { + if (n == 0) + return -1; + int log = 0; + uint32 value = n; + for (int i = 4; i >= 0; --i) { + int shift = (1 << i); + uint32 x = value >> shift; + if (x != 0) { + value = x; + log += shift; + } + } + assert(value == 1); + return log; + } + + static int Log2FloorNonZero64_Portable(uint64 n) { + const uint32 topbits = static_cast(n >> 32); + if (topbits == 0) { + // Top bits are zero, so scan in bottom bits + return static_cast(Log2FloorNonZero(static_cast(n))); + } else { + return 32 + static_cast(Log2FloorNonZero(topbits)); + } + } +}; + +// =================================================================== +// from google3/util/endian/endian.h +LIBPROTOBUF_EXPORT uint32 ghtonl(uint32 x); + +class BigEndian { + public: +#ifdef PROTOBUF_LITTLE_ENDIAN + + static uint16 FromHost16(uint16 x) { return bswap_16(x); } + static uint16 ToHost16(uint16 x) { return bswap_16(x); } + + static uint32 FromHost32(uint32 x) { return bswap_32(x); } + static uint32 ToHost32(uint32 x) { return bswap_32(x); } + + static uint64 FromHost64(uint64 x) { return bswap_64(x); } + static uint64 ToHost64(uint64 x) { return bswap_64(x); } + + static bool IsLittleEndian() { return true; } + +#else + + static uint16 FromHost16(uint16 x) { return x; } + static uint16 ToHost16(uint16 x) { return x; } + + static uint32 FromHost32(uint32 x) { return x; } + static uint32 ToHost32(uint32 x) { return x; } + + static uint64 FromHost64(uint64 x) { return x; } + static uint64 ToHost64(uint64 x) { return x; } + + static bool IsLittleEndian() { return false; } + +#endif /* ENDIAN */ + + // Functions to do unaligned loads and stores in big-endian order. + static uint16 Load16(const void *p) { + return ToHost16(GOOGLE_UNALIGNED_LOAD16(p)); + } + + static void Store16(void *p, uint16 v) { + GOOGLE_UNALIGNED_STORE16(p, FromHost16(v)); + } + + static uint32 Load32(const void *p) { + return ToHost32(GOOGLE_UNALIGNED_LOAD32(p)); + } + + static void Store32(void *p, uint32 v) { + GOOGLE_UNALIGNED_STORE32(p, FromHost32(v)); + } + + static uint64 Load64(const void *p) { + return ToHost64(GOOGLE_UNALIGNED_LOAD64(p)); + } + + static void Store64(void *p, uint64 v) { + GOOGLE_UNALIGNED_STORE64(p, FromHost64(v)); + } +}; + +#ifndef GOOGLE_ATTRIBUTE_SECTION_VARIABLE +#define GOOGLE_ATTRIBUTE_SECTION_VARIABLE(name) +#endif + +#define GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(name) + +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_PORT_H_ diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/atomicops_internals_pnacl.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/singleton.h similarity index 60% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/atomicops_internals_pnacl.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/singleton.h index b10ac02c4..2e6ccbdb6 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/atomicops_internals_pnacl.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/singleton.h @@ -1,5 +1,5 @@ // Protocol Buffers - Google's data interchange format -// Copyright 2012 Google Inc. All rights reserved. +// Copyright 2014 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without @@ -27,47 +27,41 @@ // 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. +#ifndef GOOGLE_PROTOBUF_STUBS_SINGLETON_H__ +#define GOOGLE_PROTOBUF_STUBS_SINGLETON_H__ -// This file is an internal atomic implementation, use atomicops.h instead. - -#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ -#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ +#include +#include namespace google { namespace protobuf { namespace internal { +template +class Singleton { + public: + static T* get() { + GoogleOnceInit(&once_, &Singleton::Init); + return instance_; + } + static void ShutDown() { + delete instance_; + instance_ = NULL; + } + private: + static void Init() { + instance_ = new T(); + } + static ProtobufOnceType once_; + static T* instance_; +}; -inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - return __sync_val_compare_and_swap(ptr, old_value, new_value); -} - -inline void MemoryBarrier() { - __sync_synchronize(); -} - -inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value) { - Atomic32 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value); - MemoryBarrier(); - return ret; -} - -inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) { - MemoryBarrier(); - *ptr = value; -} - -inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) { - Atomic32 value = *ptr; - MemoryBarrier(); - return value; -} +template +ProtobufOnceType Singleton::once_; +template +T* Singleton::instance_ = NULL; } // namespace internal } // namespace protobuf } // namespace google -#endif // GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_ +#endif // GOOGLE_PROTOBUF_STUBS_SINGLETON_H__ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status.cc new file mode 100644 index 000000000..2bfbe0b42 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status.cc @@ -0,0 +1,134 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace error { +inline string CodeEnumToString(error::Code code) { + switch (code) { + case OK: + return "OK"; + case CANCELLED: + return "CANCELLED"; + case UNKNOWN: + return "UNKNOWN"; + case INVALID_ARGUMENT: + return "INVALID_ARGUMENT"; + case DEADLINE_EXCEEDED: + return "DEADLINE_EXCEEDED"; + case NOT_FOUND: + return "NOT_FOUND"; + case ALREADY_EXISTS: + return "ALREADY_EXISTS"; + case PERMISSION_DENIED: + return "PERMISSION_DENIED"; + case UNAUTHENTICATED: + return "UNAUTHENTICATED"; + case RESOURCE_EXHAUSTED: + return "RESOURCE_EXHAUSTED"; + case FAILED_PRECONDITION: + return "FAILED_PRECONDITION"; + case ABORTED: + return "ABORTED"; + case OUT_OF_RANGE: + return "OUT_OF_RANGE"; + case UNIMPLEMENTED: + return "UNIMPLEMENTED"; + case INTERNAL: + return "INTERNAL"; + case UNAVAILABLE: + return "UNAVAILABLE"; + case DATA_LOSS: + return "DATA_LOSS"; + } + + // No default clause, clang will abort if a code is missing from + // above switch. + return "UNKNOWN"; +} +} // namespace error. + +const Status Status::OK = Status(); +const Status Status::CANCELLED = Status(error::CANCELLED, ""); +const Status Status::UNKNOWN = Status(error::UNKNOWN, ""); + +Status::Status() : error_code_(error::OK) { +} + +Status::Status(error::Code error_code, StringPiece error_message) + : error_code_(error_code) { + if (error_code != error::OK) { + error_message_ = error_message.ToString(); + } +} + +Status::Status(const Status& other) + : error_code_(other.error_code_), error_message_(other.error_message_) { +} + +Status& Status::operator=(const Status& other) { + error_code_ = other.error_code_; + error_message_ = other.error_message_; + return *this; +} + +bool Status::operator==(const Status& x) const { + return error_code_ == x.error_code_ && + error_message_ == x.error_message_; +} + +string Status::ToString() const { + if (error_code_ == error::OK) { + return "OK"; + } else { + if (error_message_.empty()) { + return error::CodeEnumToString(error_code_); + } else { + return error::CodeEnumToString(error_code_) + ":" + + error_message_; + } + } +} + +std::ostream& operator<<(std::ostream& os, const Status& x) { + os << x.ToString(); + return os; +} + +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status.h new file mode 100644 index 000000000..c5d38f0b4 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status.h @@ -0,0 +1,116 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. +#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUS_H_ + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace error { +// These values must match error codes defined in google/rpc/code.proto. +enum Code { + OK = 0, + CANCELLED = 1, + UNKNOWN = 2, + INVALID_ARGUMENT = 3, + DEADLINE_EXCEEDED = 4, + NOT_FOUND = 5, + ALREADY_EXISTS = 6, + PERMISSION_DENIED = 7, + UNAUTHENTICATED = 16, + RESOURCE_EXHAUSTED = 8, + FAILED_PRECONDITION = 9, + ABORTED = 10, + OUT_OF_RANGE = 11, + UNIMPLEMENTED = 12, + INTERNAL = 13, + UNAVAILABLE = 14, + DATA_LOSS = 15, +}; +} // namespace error + +class LIBPROTOBUF_EXPORT Status { + public: + // Creates a "successful" status. + Status(); + + // Create a status in the canonical error space with the specified + // code, and error message. If "code == 0", error_message is + // ignored and a Status object identical to Status::OK is + // constructed. + Status(error::Code error_code, StringPiece error_message); + Status(const Status&); + Status& operator=(const Status& x); + ~Status() {} + + // Some pre-defined Status objects + static const Status OK; // Identical to 0-arg constructor + static const Status CANCELLED; + static const Status UNKNOWN; + + // Accessor + bool ok() const { + return error_code_ == error::OK; + } + int error_code() const { + return error_code_; + } + StringPiece error_message() const { + return error_message_; + } + + bool operator==(const Status& x) const; + bool operator!=(const Status& x) const { + return !operator==(x); + } + + // Return a combination of the error code name and message. + string ToString() const; + + private: + error::Code error_code_; + string error_message_; +}; + +// Prints a human-readable representation of 'x' to 'os'. +LIBPROTOBUF_EXPORT std::ostream& operator<<(std::ostream& os, const Status& x); + +#define EXPECT_OK(value) EXPECT_TRUE((value).ok()) + +} // namespace util +} // namespace protobuf +} // namespace google +#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status_macros.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status_macros.h new file mode 100644 index 000000000..743e79a72 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status_macros.h @@ -0,0 +1,89 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// From: util/task/contrib/status_macros/status_macros.h + +#ifndef GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_ + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace util { + +// Run a command that returns a util::Status. If the called code returns an +// error status, return that status up out of this method too. +// +// Example: +// RETURN_IF_ERROR(DoThings(4)); +#define RETURN_IF_ERROR(expr) \ + do { \ + /* Using _status below to avoid capture problems if expr is "status". */ \ + const ::google::protobuf::util::Status _status = (expr); \ + if (GOOGLE_PREDICT_FALSE(!_status.ok())) return _status; \ + } while (0) + +// Internal helper for concatenating macro values. +#define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y +#define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y) + +template +Status DoAssignOrReturn(T& lhs, StatusOr result) { + if (result.ok()) { + lhs = result.ValueOrDie(); + } + return result.status(); +} + +#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \ + Status status = DoAssignOrReturn(lhs, (rexpr)); \ + if (GOOGLE_PREDICT_FALSE(!status.ok())) return status; + +// Executes an expression that returns a util::StatusOr, extracting its value +// into the variable defined by lhs (or returning on error). +// +// Example: Assigning to an existing value +// ValueType value; +// ASSIGN_OR_RETURN(value, MaybeGetValue(arg)); +// +// WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used +// in a single statement (e.g. as the body of an if statement without {})! +#define ASSIGN_OR_RETURN(lhs, rexpr) \ + ASSIGN_OR_RETURN_IMPL( \ + STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr); + +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STATUS_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status_test.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status_test.cc new file mode 100644 index 000000000..c70c33c47 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/status_test.cc @@ -0,0 +1,131 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace { +TEST(Status, Empty) { + util::Status status; + EXPECT_EQ(util::error::OK, util::Status::OK.error_code()); + EXPECT_EQ("OK", util::Status::OK.ToString()); +} + +TEST(Status, GenericCodes) { + EXPECT_EQ(util::error::OK, util::Status::OK.error_code()); + EXPECT_EQ(util::error::CANCELLED, util::Status::CANCELLED.error_code()); + EXPECT_EQ(util::error::UNKNOWN, util::Status::UNKNOWN.error_code()); +} + +TEST(Status, ConstructorZero) { + util::Status status(util::error::OK, "msg"); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("OK", status.ToString()); +} + +TEST(Status, CheckOK) { + util::Status status; + GOOGLE_CHECK_OK(status); + GOOGLE_CHECK_OK(status) << "Failed"; + GOOGLE_DCHECK_OK(status) << "Failed"; +} + +TEST(Status, ErrorMessage) { + util::Status status(util::error::INVALID_ARGUMENT, ""); + EXPECT_FALSE(status.ok()); + EXPECT_EQ("", status.error_message().ToString()); + EXPECT_EQ("INVALID_ARGUMENT", status.ToString()); + status = util::Status(util::error::INVALID_ARGUMENT, "msg"); + EXPECT_FALSE(status.ok()); + EXPECT_EQ("msg", status.error_message().ToString()); + EXPECT_EQ("INVALID_ARGUMENT:msg", status.ToString()); + status = util::Status(util::error::OK, "msg"); + EXPECT_TRUE(status.ok()); + EXPECT_EQ("", status.error_message().ToString()); + EXPECT_EQ("OK", status.ToString()); +} + +TEST(Status, Copy) { + util::Status a(util::error::UNKNOWN, "message"); + util::Status b(a); + ASSERT_EQ(a.ToString(), b.ToString()); +} + +TEST(Status, Assign) { + util::Status a(util::error::UNKNOWN, "message"); + util::Status b; + b = a; + ASSERT_EQ(a.ToString(), b.ToString()); +} + +TEST(Status, AssignEmpty) { + util::Status a(util::error::UNKNOWN, "message"); + util::Status b; + a = b; + ASSERT_EQ(string("OK"), a.ToString()); + ASSERT_TRUE(b.ok()); + ASSERT_TRUE(a.ok()); +} + +TEST(Status, EqualsOK) { + ASSERT_EQ(util::Status::OK, util::Status()); +} + +TEST(Status, EqualsSame) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = util::Status(util::error::CANCELLED, "message"); + ASSERT_EQ(a, b); +} + +TEST(Status, EqualsCopy) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = a; + ASSERT_EQ(a, b); +} + +TEST(Status, EqualsDifferentCode) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = util::Status(util::error::UNKNOWN, "message"); + ASSERT_NE(a, b); +} + +TEST(Status, EqualsDifferentMessage) { + const util::Status a = util::Status(util::error::CANCELLED, "message"); + const util::Status b = util::Status(util::error::CANCELLED, "another"); + ASSERT_NE(a, b); +} +} // namespace +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/statusor.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/statusor.cc new file mode 100644 index 000000000..48d1402ae --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/statusor.cc @@ -0,0 +1,46 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +namespace google { +namespace protobuf { +namespace util { +namespace internal { + +void StatusOrHelper::Crash(const Status& status) { + GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error " + << status.ToString(); +} + +} // namespace internal +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/statusor.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/statusor.h new file mode 100644 index 000000000..29f869ad5 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/statusor.h @@ -0,0 +1,259 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// StatusOr is the union of a Status object and a T +// object. StatusOr models the concept of an object that is either a +// usable value, or an error Status explaining why such a value is +// not present. To this end, StatusOr does not allow its Status +// value to be Status::OK. Further, StatusOr does not allow the +// contained pointer to be NULL. +// +// The primary use-case for StatusOr is as the return value of a +// function which may fail. +// +// Example client usage for a StatusOr, where T is not a pointer: +// +// StatusOr result = DoBigCalculationThatCouldFail(); +// if (result.ok()) { +// float answer = result.ValueOrDie(); +// printf("Big calculation yielded: %f", answer); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example client usage for a StatusOr: +// +// StatusOr result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr foo(result.ValueOrDie()); +// foo->DoSomethingCool(); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example client usage for a StatusOr>: +// +// StatusOr> result = FooFactory::MakeNewFoo(arg); +// if (result.ok()) { +// std::unique_ptr foo = result.ConsumeValueOrDie(); +// foo->DoSomethingCool(); +// } else { +// LOG(ERROR) << result.status(); +// } +// +// Example factory implementation returning StatusOr: +// +// StatusOr FooFactory::MakeNewFoo(int arg) { +// if (arg <= 0) { +// return ::util::Status(::util::error::INVALID_ARGUMENT, +// "Arg must be positive"); +// } else { +// return new Foo(arg); +// } +// } +// + +#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ +#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ + +#include +#include +#include + +#include + +namespace google { +namespace protobuf { +namespace util { + +template +class StatusOr { + template friend class StatusOr; + + public: + // Construct a new StatusOr with Status::UNKNOWN status + StatusOr(); + + // Construct a new StatusOr with the given non-ok status. After calling + // this constructor, calls to ValueOrDie() will CHECK-fail. + // + // NOTE: Not explicit - we want to use StatusOr as a return + // value, so it is convenient and sensible to be able to do 'return + // Status()' when the return type is StatusOr. + // + // REQUIRES: status != Status::OK. This requirement is DCHECKed. + // In optimized builds, passing Status::OK here will have the effect + // of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const Status& status); // NOLINT + + // Construct a new StatusOr with the given value. If T is a plain pointer, + // value must not be NULL. After calling this constructor, calls to + // ValueOrDie() will succeed, and calls to status() will return OK. + // + // NOTE: Not explicit - we want to use StatusOr as a return type + // so it is convenient and sensible to be able to do 'return T()' + // when when the return type is StatusOr. + // + // REQUIRES: if T is a plain pointer, value != NULL. This requirement is + // DCHECKed. In optimized builds, passing a NULL pointer here will have + // the effect of passing PosixErrorSpace::EINVAL as a fallback. + StatusOr(const T& value); // NOLINT + + // Copy constructor. + StatusOr(const StatusOr& other); + + // Conversion copy constructor, T must be copy constructible from U + template + StatusOr(const StatusOr& other); + + // Assignment operator. + StatusOr& operator=(const StatusOr& other); + + // Conversion assignment operator, T must be assignable from U + template + StatusOr& operator=(const StatusOr& other); + + // Returns a reference to our status. If this contains a T, then + // returns Status::OK. + const Status& status() const; + + // Returns this->status().ok() + bool ok() const; + + // Returns a reference to our current value, or CHECK-fails if !this->ok(). + // If you need to initialize a T object from the stored value, + // ConsumeValueOrDie() may be more efficient. + const T& ValueOrDie() const; + + private: + Status status_; + T value_; +}; + +//////////////////////////////////////////////////////////////////////////////// +// Implementation details for StatusOr + +namespace internal { + +class LIBPROTOBUF_EXPORT StatusOrHelper { + public: + // Move type-agnostic error handling to the .cc. + static void Crash(const util::Status& status); + + // Customized behavior for StatusOr vs. StatusOr + template + struct Specialize; +}; + +template +struct StatusOrHelper::Specialize { + // For non-pointer T, a reference can never be NULL. + static inline bool IsValueNull(const T& t) { return false; } +}; + +template +struct StatusOrHelper::Specialize { + static inline bool IsValueNull(const T* t) { return t == NULL; } +}; + +} // namespace internal + +template +inline StatusOr::StatusOr() + : status_(util::Status::UNKNOWN) { +} + +template +inline StatusOr::StatusOr(const Status& status) { + if (status.ok()) { + status_ = Status(error::INTERNAL, "Status::OK is not a valid argument."); + } else { + status_ = status; + } +} + +template +inline StatusOr::StatusOr(const T& value) { + if (internal::StatusOrHelper::Specialize::IsValueNull(value)) { + status_ = Status(error::INTERNAL, "NULL is not a vaild argument."); + } else { + status_ = Status::OK; + value_ = value; + } +} + +template +inline StatusOr::StatusOr(const StatusOr& other) + : status_(other.status_), value_(other.value_) { +} + +template +inline StatusOr& StatusOr::operator=(const StatusOr& other) { + status_ = other.status_; + value_ = other.value_; + return *this; +} + +template +template +inline StatusOr::StatusOr(const StatusOr& other) + : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) { +} + +template +template +inline StatusOr& StatusOr::operator=(const StatusOr& other) { + status_ = other.status_; + if (status_.ok()) value_ = other.value_; + return *this; +} + +template +inline const Status& StatusOr::status() const { + return status_; +} + +template +inline bool StatusOr::ok() const { + return status().ok(); +} + +template +inline const T& StatusOr::ValueOrDie() const { + if (!status_.ok()) { + internal::StatusOrHelper::Crash(status_); + } + return value_; +} +} // namespace util +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/statusor_test.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/statusor_test.cc new file mode 100644 index 000000000..6e2a9e554 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/statusor_test.cc @@ -0,0 +1,274 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace util { +namespace { + +class Base1 { + public: + virtual ~Base1() {} + int pad; +}; + +class Base2 { + public: + virtual ~Base2() {} + int yetotherpad; +}; + +class Derived : public Base1, public Base2 { + public: + virtual ~Derived() {} + int evenmorepad; +}; + +class CopyNoAssign { + public: + explicit CopyNoAssign(int value) : foo(value) {} + CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {} + int foo; + private: + const CopyNoAssign& operator=(const CopyNoAssign&); +}; + +TEST(StatusOr, TestDefaultCtor) { + StatusOr thing; + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::UNKNOWN, thing.status()); +} + +TEST(StatusOr, TestStatusCtor) { + StatusOr thing(Status::CANCELLED); + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::CANCELLED, thing.status()); +} + +TEST(StatusOr, TestValueCtor) { + const int kI = 4; + StatusOr thing(kI); + EXPECT_TRUE(thing.ok()); + EXPECT_EQ(kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestCopyCtorStatusOk) { + const int kI = 4; + StatusOr original(kI); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie()); +} + +TEST(StatusOr, TestCopyCtorStatusNotOk) { + StatusOr original(Status::CANCELLED); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestCopyCtorStatusOKConverting) { + const int kI = 4; + StatusOr original(kI); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie()); +} + +TEST(StatusOr, TestCopyCtorStatusNotOkConverting) { + StatusOr original(Status::CANCELLED); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestAssignmentStatusOk) { + const int kI = 4; + StatusOr source(kI); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie()); +} + +TEST(StatusOr, TestAssignmentStatusNotOk) { + StatusOr source(Status::CANCELLED); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestAssignmentStatusOKConverting) { + const int kI = 4; + StatusOr source(kI); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_DOUBLE_EQ(source.ValueOrDie(), target.ValueOrDie()); +} + +TEST(StatusOr, TestAssignmentStatusNotOkConverting) { + StatusOr source(Status::CANCELLED); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestStatus) { + StatusOr good(4); + EXPECT_TRUE(good.ok()); + StatusOr bad(Status::CANCELLED); + EXPECT_FALSE(bad.ok()); + EXPECT_EQ(Status::CANCELLED, bad.status()); +} + +TEST(StatusOr, TestValue) { + const int kI = 4; + StatusOr thing(kI); + EXPECT_EQ(kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestValueConst) { + const int kI = 4; + const StatusOr thing(kI); + EXPECT_EQ(kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestPointerDefaultCtor) { + StatusOr thing; + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::UNKNOWN, thing.status()); +} + +TEST(StatusOr, TestPointerStatusCtor) { + StatusOr thing(Status::CANCELLED); + EXPECT_FALSE(thing.ok()); + EXPECT_EQ(Status::CANCELLED, thing.status()); +} + +TEST(StatusOr, TestPointerValueCtor) { + const int kI = 4; + StatusOr thing(&kI); + EXPECT_TRUE(thing.ok()); + EXPECT_EQ(&kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusOk) { + const int kI = 0; + StatusOr original(&kI); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(original.ValueOrDie(), copy.ValueOrDie()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusNotOk) { + StatusOr original(Status::CANCELLED); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) { + Derived derived; + StatusOr original(&derived); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); + EXPECT_EQ(static_cast(original.ValueOrDie()), + copy.ValueOrDie()); +} + +TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) { + StatusOr original(Status::CANCELLED); + StatusOr copy(original); + EXPECT_EQ(original.status(), copy.status()); +} + +TEST(StatusOr, TestPointerAssignmentStatusOk) { + const int kI = 0; + StatusOr source(&kI); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_EQ(source.ValueOrDie(), target.ValueOrDie()); +} + +TEST(StatusOr, TestPointerAssignmentStatusNotOk) { + StatusOr source(Status::CANCELLED); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestPointerAssignmentStatusOKConverting) { + Derived derived; + StatusOr source(&derived); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); + EXPECT_EQ(static_cast(source.ValueOrDie()), + target.ValueOrDie()); +} + +TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) { + StatusOr source(Status::CANCELLED); + StatusOr target; + target = source; + EXPECT_EQ(source.status(), target.status()); +} + +TEST(StatusOr, TestPointerStatus) { + const int kI = 0; + StatusOr good(&kI); + EXPECT_TRUE(good.ok()); + StatusOr bad(Status::CANCELLED); + EXPECT_EQ(Status::CANCELLED, bad.status()); +} + +TEST(StatusOr, TestPointerValue) { + const int kI = 0; + StatusOr thing(&kI); + EXPECT_EQ(&kI, thing.ValueOrDie()); +} + +TEST(StatusOr, TestPointerValueConst) { + const int kI = 0; + const StatusOr thing(&kI); + EXPECT_EQ(&kI, thing.ValueOrDie()); +} + +} // namespace +} // namespace util +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stl_util.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stl_util.h similarity index 100% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stl_util.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stl_util.h diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringpiece.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringpiece.cc new file mode 100644 index 000000000..989474b74 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringpiece.cc @@ -0,0 +1,268 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +std::ostream& operator<<(std::ostream& o, StringPiece piece) { + o.write(piece.data(), piece.size()); + return o; +} + +// Out-of-line error path. +void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) { + GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details; +} + +StringPiece::StringPiece(StringPiece x, stringpiece_ssize_type pos) + : ptr_(x.ptr_ + pos), length_(x.length_ - pos) { + GOOGLE_DCHECK_LE(0, pos); + GOOGLE_DCHECK_LE(pos, x.length_); +} + +StringPiece::StringPiece(StringPiece x, + stringpiece_ssize_type pos, + stringpiece_ssize_type len) + : ptr_(x.ptr_ + pos), length_(std::min(len, x.length_ - pos)) { + GOOGLE_DCHECK_LE(0, pos); + GOOGLE_DCHECK_LE(pos, x.length_); + GOOGLE_DCHECK_GE(len, 0); +} + +void StringPiece::CopyToString(string* target) const { + target->assign(ptr_, length_); +} + +void StringPiece::AppendToString(string* target) const { + target->append(ptr_, length_); +} + +bool StringPiece::Consume(StringPiece x) { + if (starts_with(x)) { + ptr_ += x.length_; + length_ -= x.length_; + return true; + } + return false; +} + +bool StringPiece::ConsumeFromEnd(StringPiece x) { + if (ends_with(x)) { + length_ -= x.length_; + return true; + } + return false; +} + +stringpiece_ssize_type StringPiece::copy(char* buf, + size_type n, + size_type pos) const { + stringpiece_ssize_type ret = std::min(length_ - pos, n); + memcpy(buf, ptr_ + pos, ret); + return ret; +} + +bool StringPiece::contains(StringPiece s) const { + return find(s, 0) != npos; +} + +stringpiece_ssize_type StringPiece::find(StringPiece s, size_type pos) const { + if (length_ <= 0 || pos > static_cast(length_)) { + if (length_ == 0 && pos == 0 && s.length_ == 0) return 0; + return npos; + } + const char *result = std::search(ptr_ + pos, ptr_ + length_, + s.ptr_, s.ptr_ + s.length_); + return result == ptr_ + length_ ? npos : result - ptr_; +} + +stringpiece_ssize_type StringPiece::find(char c, size_type pos) const { + if (length_ <= 0 || pos >= static_cast(length_)) { + return npos; + } + const char* result = static_cast( + memchr(ptr_ + pos, c, length_ - pos)); + return result != NULL ? result - ptr_ : npos; +} + +stringpiece_ssize_type StringPiece::rfind(StringPiece s, size_type pos) const { + if (length_ < s.length_) return npos; + const size_t ulen = length_; + if (s.length_ == 0) return std::min(ulen, pos); + + const char* last = ptr_ + std::min(ulen - s.length_, pos) + s.length_; + const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_); + return result != last ? result - ptr_ : npos; +} + +// Search range is [0..pos] inclusive. If pos == npos, search everything. +stringpiece_ssize_type StringPiece::rfind(char c, size_type pos) const { + // Note: memrchr() is not available on Windows. + if (length_ <= 0) return npos; + for (stringpiece_ssize_type i = + std::min(pos, static_cast(length_ - 1)); + i >= 0; --i) { + if (ptr_[i] == c) { + return i; + } + } + return npos; +} + +// For each character in characters_wanted, sets the index corresponding +// to the ASCII code of that character to 1 in table. This is used by +// the find_.*_of methods below to tell whether or not a character is in +// the lookup table in constant time. +// The argument `table' must be an array that is large enough to hold all +// the possible values of an unsigned char. Thus it should be be declared +// as follows: +// bool table[UCHAR_MAX + 1] +static inline void BuildLookupTable(StringPiece characters_wanted, + bool* table) { + const stringpiece_ssize_type length = characters_wanted.length(); + const char* const data = characters_wanted.data(); + for (stringpiece_ssize_type i = 0; i < length; ++i) { + table[static_cast(data[i])] = true; + } +} + +stringpiece_ssize_type StringPiece::find_first_of(StringPiece s, + size_type pos) const { + if (length_ <= 0 || s.length_ <= 0) { + return npos; + } + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_first_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (stringpiece_ssize_type i = pos; i < length_; ++i) { + if (lookup[static_cast(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_first_not_of(StringPiece s, + size_type pos) const { + if (length_ <= 0) return npos; + if (s.length_ <= 0) return 0; + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_first_not_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (stringpiece_ssize_type i = pos; i < length_; ++i) { + if (!lookup[static_cast(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_first_not_of(char c, + size_type pos) const { + if (length_ <= 0) return npos; + + for (; pos < static_cast(length_); ++pos) { + if (ptr_[pos] != c) { + return pos; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_last_of(StringPiece s, + size_type pos) const { + if (length_ <= 0 || s.length_ <= 0) return npos; + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_last_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (stringpiece_ssize_type i = + std::min(pos, static_cast(length_ - 1)); i >= 0; --i) { + if (lookup[static_cast(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_last_not_of(StringPiece s, + size_type pos) const { + if (length_ <= 0) return npos; + + stringpiece_ssize_type i = std::min(pos, static_cast(length_ - 1)); + if (s.length_ <= 0) return i; + + // Avoid the cost of BuildLookupTable() for a single-character search. + if (s.length_ == 1) return find_last_not_of(s.ptr_[0], pos); + + bool lookup[UCHAR_MAX + 1] = { false }; + BuildLookupTable(s, lookup); + for (; i >= 0; --i) { + if (!lookup[static_cast(ptr_[i])]) { + return i; + } + } + return npos; +} + +stringpiece_ssize_type StringPiece::find_last_not_of(char c, + size_type pos) const { + if (length_ <= 0) return npos; + + for (stringpiece_ssize_type i = + std::min(pos, static_cast(length_ - 1)); i >= 0; --i) { + if (ptr_[i] != c) { + return i; + } + } + return npos; +} + +StringPiece StringPiece::substr(size_type pos, size_type n) const { + if (pos > length_) pos = length_; + if (n > length_ - pos) n = length_ - pos; + return StringPiece(ptr_ + pos, n); +} + +const StringPiece::size_type StringPiece::npos = size_type(-1); + +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringpiece.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringpiece.h new file mode 100644 index 000000000..563ff75dc --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringpiece.h @@ -0,0 +1,487 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// A StringPiece points to part or all of a string, Cord, double-quoted string +// literal, or other string-like object. A StringPiece does *not* own the +// string to which it points. A StringPiece is not null-terminated. +// +// You can use StringPiece as a function or method parameter. A StringPiece +// parameter can receive a double-quoted string literal argument, a "const +// char*" argument, a string argument, or a StringPiece argument with no data +// copying. Systematic use of StringPiece for arguments reduces data +// copies and strlen() calls. +// +// Prefer passing StringPieces by value: +// void MyFunction(StringPiece arg); +// If circumstances require, you may also pass by const reference: +// void MyFunction(const StringPiece& arg); // not preferred +// Both of these have the same lifetime semantics. Passing by value +// generates slightly smaller code. For more discussion, see the thread +// go/stringpiecebyvalue on c-users. +// +// StringPiece is also suitable for local variables if you know that +// the lifetime of the underlying object is longer than the lifetime +// of your StringPiece variable. +// +// Beware of binding a StringPiece to a temporary: +// StringPiece sp = obj.MethodReturningString(); // BAD: lifetime problem +// +// This code is okay: +// string str = obj.MethodReturningString(); // str owns its contents +// StringPiece sp(str); // GOOD, because str outlives sp +// +// StringPiece is sometimes a poor choice for a return value and usually a poor +// choice for a data member. If you do use a StringPiece this way, it is your +// responsibility to ensure that the object pointed to by the StringPiece +// outlives the StringPiece. +// +// A StringPiece may represent just part of a string; thus the name "Piece". +// For example, when splitting a string, vector is a natural data +// type for the output. For another example, a Cord is a non-contiguous, +// potentially very long string-like object. The Cord class has an interface +// that iteratively provides StringPiece objects that point to the +// successive pieces of a Cord object. +// +// A StringPiece is not null-terminated. If you write code that scans a +// StringPiece, you must check its length before reading any characters. +// Common idioms that work on null-terminated strings do not work on +// StringPiece objects. +// +// There are several ways to create a null StringPiece: +// StringPiece() +// StringPiece(NULL) +// StringPiece(NULL, 0) +// For all of the above, sp.data() == NULL, sp.length() == 0, +// and sp.empty() == true. Also, if you create a StringPiece with +// a non-NULL pointer then sp.data() != NULL. Once created, +// sp.data() will stay either NULL or not-NULL, except if you call +// sp.clear() or sp.set(). +// +// Thus, you can use StringPiece(NULL) to signal an out-of-band value +// that is different from other StringPiece values. This is similar +// to the way that const char* p1 = NULL; is different from +// const char* p2 = "";. +// +// There are many ways to create an empty StringPiece: +// StringPiece() +// StringPiece(NULL) +// StringPiece(NULL, 0) +// StringPiece("") +// StringPiece("", 0) +// StringPiece("abcdef", 0) +// StringPiece("abcdef"+6, 0) +// For all of the above, sp.length() will be 0 and sp.empty() will be true. +// For some empty StringPiece values, sp.data() will be NULL. +// For some empty StringPiece values, sp.data() will not be NULL. +// +// Be careful not to confuse: null StringPiece and empty StringPiece. +// The set of empty StringPieces properly includes the set of null StringPieces. +// That is, every null StringPiece is an empty StringPiece, +// but some non-null StringPieces are empty Stringpieces too. +// +// All empty StringPiece values compare equal to each other. +// Even a null StringPieces compares equal to a non-null empty StringPiece: +// StringPiece() == StringPiece("", 0) +// StringPiece(NULL) == StringPiece("abc", 0) +// StringPiece(NULL, 0) == StringPiece("abcdef"+6, 0) +// +// Look carefully at this example: +// StringPiece("") == NULL +// True or false? TRUE, because StringPiece::operator== converts +// the right-hand side from NULL to StringPiece(NULL), +// and then compares two zero-length spans of characters. +// However, we are working to make this example produce a compile error. +// +// Suppose you want to write: +// bool TestWhat?(StringPiece sp) { return sp == NULL; } // BAD +// Do not do that. Write one of these instead: +// bool TestNull(StringPiece sp) { return sp.data() == NULL; } +// bool TestEmpty(StringPiece sp) { return sp.empty(); } +// The intent of TestWhat? is unclear. Did you mean TestNull or TestEmpty? +// Right now, TestWhat? behaves likes TestEmpty. +// We are working to make TestWhat? produce a compile error. +// TestNull is good to test for an out-of-band signal. +// TestEmpty is good to test for an empty StringPiece. +// +// Caveats (again): +// (1) The lifetime of the pointed-to string (or piece of a string) +// must be longer than the lifetime of the StringPiece. +// (2) There may or may not be a '\0' character after the end of +// StringPiece data. +// (3) A null StringPiece is empty. +// An empty StringPiece may or may not be a null StringPiece. + +#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ +#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace google { +namespace protobuf { +// StringPiece has *two* size types. +// StringPiece::size_type +// is unsigned +// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64 +// no future changes intended +// stringpiece_ssize_type +// is signed +// is 32 bits in LP32, 64 bits in LP64, 64 bits in LLP64 +// future changes intended: http://go/64BitStringPiece +// +typedef string::difference_type stringpiece_ssize_type; + +// STRINGPIECE_CHECK_SIZE protects us from 32-bit overflows. +// TODO(mec): delete this after stringpiece_ssize_type goes 64 bit. +#if !defined(NDEBUG) +#define STRINGPIECE_CHECK_SIZE 1 +#elif defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 +#define STRINGPIECE_CHECK_SIZE 1 +#else +#define STRINGPIECE_CHECK_SIZE 0 +#endif + +class LIBPROTOBUF_EXPORT StringPiece { + private: + const char* ptr_; + stringpiece_ssize_type length_; + + // Prevent overflow in debug mode or fortified mode. + // sizeof(stringpiece_ssize_type) may be smaller than sizeof(size_t). + static stringpiece_ssize_type CheckedSsizeTFromSizeT(size_t size) { +#if STRINGPIECE_CHECK_SIZE > 0 +#ifdef max +#undef max +#endif + if (size > static_cast( + std::numeric_limits::max())) { + // Some people grep for this message in logs + // so take care if you ever change it. + LogFatalSizeTooBig(size, "size_t to int conversion"); + } +#endif + return static_cast(size); + } + + // Out-of-line error path. + static void LogFatalSizeTooBig(size_t size, const char* details); + + public: + // We provide non-explicit singleton constructors so users can pass + // in a "const char*" or a "string" wherever a "StringPiece" is + // expected. + // + // Style guide exception granted: + // http://goto/style-guide-exception-20978288 + StringPiece() : ptr_(NULL), length_(0) {} + + StringPiece(const char* str) // NOLINT(runtime/explicit) + : ptr_(str), length_(0) { + if (str != NULL) { + length_ = CheckedSsizeTFromSizeT(strlen(str)); + } + } + + template + StringPiece( // NOLINT(runtime/explicit) + const std::basic_string, Allocator>& str) + : ptr_(str.data()), length_(0) { + length_ = CheckedSsizeTFromSizeT(str.size()); + } + + StringPiece(const char* offset, stringpiece_ssize_type len) + : ptr_(offset), length_(len) { + assert(len >= 0); + } + + // Substring of another StringPiece. + // pos must be non-negative and <= x.length(). + StringPiece(StringPiece x, stringpiece_ssize_type pos); + // Substring of another StringPiece. + // pos must be non-negative and <= x.length(). + // len must be non-negative and will be pinned to at most x.length() - pos. + StringPiece(StringPiece x, + stringpiece_ssize_type pos, + stringpiece_ssize_type len); + + // data() may return a pointer to a buffer with embedded NULs, and the + // returned buffer may or may not be null terminated. Therefore it is + // typically a mistake to pass data() to a routine that expects a NUL + // terminated string. + const char* data() const { return ptr_; } + stringpiece_ssize_type size() const { return length_; } + stringpiece_ssize_type length() const { return length_; } + bool empty() const { return length_ == 0; } + + void clear() { + ptr_ = NULL; + length_ = 0; + } + + void set(const char* data, stringpiece_ssize_type len) { + assert(len >= 0); + ptr_ = data; + length_ = len; + } + + void set(const char* str) { + ptr_ = str; + if (str != NULL) + length_ = CheckedSsizeTFromSizeT(strlen(str)); + else + length_ = 0; + } + + void set(const void* data, stringpiece_ssize_type len) { + ptr_ = reinterpret_cast(data); + length_ = len; + } + + char operator[](stringpiece_ssize_type i) const { + assert(0 <= i); + assert(i < length_); + return ptr_[i]; + } + + void remove_prefix(stringpiece_ssize_type n) { + assert(length_ >= n); + ptr_ += n; + length_ -= n; + } + + void remove_suffix(stringpiece_ssize_type n) { + assert(length_ >= n); + length_ -= n; + } + + // returns {-1, 0, 1} + int compare(StringPiece x) const { + const stringpiece_ssize_type min_size = + length_ < x.length_ ? length_ : x.length_; + int r = memcmp(ptr_, x.ptr_, static_cast(min_size)); + if (r < 0) return -1; + if (r > 0) return 1; + if (length_ < x.length_) return -1; + if (length_ > x.length_) return 1; + return 0; + } + + string as_string() const { + return ToString(); + } + // We also define ToString() here, since many other string-like + // interfaces name the routine that converts to a C++ string + // "ToString", and it's confusing to have the method that does that + // for a StringPiece be called "as_string()". We also leave the + // "as_string()" method defined here for existing code. + string ToString() const { + if (ptr_ == NULL) return string(); + return string(data(), static_cast(size())); + } + + operator string() const { + return ToString(); + } + + void CopyToString(string* target) const; + void AppendToString(string* target) const; + + bool starts_with(StringPiece x) const { + return (length_ >= x.length_) && + (memcmp(ptr_, x.ptr_, static_cast(x.length_)) == 0); + } + + bool ends_with(StringPiece x) const { + return ((length_ >= x.length_) && + (memcmp(ptr_ + (length_-x.length_), x.ptr_, + static_cast(x.length_)) == 0)); + } + + // Checks whether StringPiece starts with x and if so advances the beginning + // of it to past the match. It's basically a shortcut for starts_with + // followed by remove_prefix. + bool Consume(StringPiece x); + // Like above but for the end of the string. + bool ConsumeFromEnd(StringPiece x); + + // standard STL container boilerplate + typedef char value_type; + typedef const char* pointer; + typedef const char& reference; + typedef const char& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + static const size_type npos; + typedef const char* const_iterator; + typedef const char* iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + iterator begin() const { return ptr_; } + iterator end() const { return ptr_ + length_; } + const_reverse_iterator rbegin() const { + return const_reverse_iterator(ptr_ + length_); + } + const_reverse_iterator rend() const { + return const_reverse_iterator(ptr_); + } + stringpiece_ssize_type max_size() const { return length_; } + stringpiece_ssize_type capacity() const { return length_; } + + // cpplint.py emits a false positive [build/include_what_you_use] + stringpiece_ssize_type copy(char* buf, size_type n, size_type pos = 0) const; // NOLINT + + bool contains(StringPiece s) const; + + stringpiece_ssize_type find(StringPiece s, size_type pos = 0) const; + stringpiece_ssize_type find(char c, size_type pos = 0) const; + stringpiece_ssize_type rfind(StringPiece s, size_type pos = npos) const; + stringpiece_ssize_type rfind(char c, size_type pos = npos) const; + + stringpiece_ssize_type find_first_of(StringPiece s, size_type pos = 0) const; + stringpiece_ssize_type find_first_of(char c, size_type pos = 0) const { + return find(c, pos); + } + stringpiece_ssize_type find_first_not_of(StringPiece s, + size_type pos = 0) const; + stringpiece_ssize_type find_first_not_of(char c, size_type pos = 0) const; + stringpiece_ssize_type find_last_of(StringPiece s, + size_type pos = npos) const; + stringpiece_ssize_type find_last_of(char c, size_type pos = npos) const { + return rfind(c, pos); + } + stringpiece_ssize_type find_last_not_of(StringPiece s, + size_type pos = npos) const; + stringpiece_ssize_type find_last_not_of(char c, size_type pos = npos) const; + + StringPiece substr(size_type pos, size_type n = npos) const; +}; + +// This large function is defined inline so that in a fairly common case where +// one of the arguments is a literal, the compiler can elide a lot of the +// following comparisons. +inline bool operator==(StringPiece x, StringPiece y) { + stringpiece_ssize_type len = x.size(); + if (len != y.size()) { + return false; + } + + return x.data() == y.data() || len <= 0 || + memcmp(x.data(), y.data(), static_cast(len)) == 0; +} + +inline bool operator!=(StringPiece x, StringPiece y) { + return !(x == y); +} + +inline bool operator<(StringPiece x, StringPiece y) { + const stringpiece_ssize_type min_size = + x.size() < y.size() ? x.size() : y.size(); + const int r = memcmp(x.data(), y.data(), static_cast(min_size)); + return (r < 0) || (r == 0 && x.size() < y.size()); +} + +inline bool operator>(StringPiece x, StringPiece y) { + return y < x; +} + +inline bool operator<=(StringPiece x, StringPiece y) { + return !(x > y); +} + +inline bool operator>=(StringPiece x, StringPiece y) { + return !(x < y); +} + +// allow StringPiece to be logged +extern std::ostream& operator<<(std::ostream& o, StringPiece piece); + +namespace internal { +// StringPiece is not a POD and can not be used in an union (pre C++11). We +// need a POD version of it. +struct StringPiecePod { + // Create from a StringPiece. + static StringPiecePod CreateFromStringPiece(StringPiece str) { + StringPiecePod pod; + pod.data_ = str.data(); + pod.size_ = str.size(); + return pod; + } + + // Cast to StringPiece. + operator StringPiece() const { return StringPiece(data_, size_); } + + bool operator==(const char* value) const { + return StringPiece(data_, size_) == StringPiece(value); + } + + char operator[](stringpiece_ssize_type i) const { + assert(0 <= i); + assert(i < size_); + return data_[i]; + } + + const char* data() const { return data_; } + + stringpiece_ssize_type size() const { + return size_; + } + + std::string ToString() const { + return std::string(data_, static_cast(size_)); + } + private: + const char* data_; + stringpiece_ssize_type size_; +}; + +} // namespace internal +} // namespace protobuf +} // namespace google + +GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START +template<> struct hash { + size_t operator()(const StringPiece& s) const { + size_t result = 0; + for (const char *str = s.data(), *end = str + s.size(); str < end; str++) { + result = 5 * result + static_cast(*str); + } + return result; + } +}; +GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END + +#endif // STRINGS_STRINGPIECE_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringpiece_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringpiece_unittest.cc new file mode 100644 index 000000000..a6a875954 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringpiece_unittest.cc @@ -0,0 +1,796 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace google { +namespace protobuf { +namespace { +TEST(StringPiece, Ctor) { + { + // Null. + StringPiece s10; + EXPECT_TRUE(s10.data() == NULL); + EXPECT_EQ(0, s10.length()); + } + + { + // const char* without length. + const char* hello = "hello"; + StringPiece s20(hello); + EXPECT_TRUE(s20.data() == hello); + EXPECT_EQ(5, s20.length()); + + // const char* with length. + StringPiece s21(hello, 4); + EXPECT_TRUE(s21.data() == hello); + EXPECT_EQ(4, s21.length()); + + // Not recommended, but valid C++ + StringPiece s22(hello, 6); + EXPECT_TRUE(s22.data() == hello); + EXPECT_EQ(6, s22.length()); + } + + { + // std::string. + std::string hola = "hola"; + StringPiece s30(hola); + EXPECT_TRUE(s30.data() == hola.data()); + EXPECT_EQ(4, s30.length()); + + // std::string with embedded '\0'. + hola.push_back('\0'); + hola.append("h2"); + hola.push_back('\0'); + StringPiece s31(hola); + EXPECT_TRUE(s31.data() == hola.data()); + EXPECT_EQ(8, s31.length()); + } + +#if defined(HAS_GLOBAL_STRING) + { + // ::string + string bonjour = "bonjour"; + StringPiece s40(bonjour); + EXPECT_TRUE(s40.data() == bonjour.data()); + EXPECT_EQ(7, s40.length()); + } +#endif + + // TODO(mec): StringPiece(StringPiece x, int pos); + // TODO(mec): StringPiece(StringPiece x, int pos, int len); + // TODO(mec): StringPiece(const StringPiece&); +} + +TEST(StringPiece, STLComparator) { + string s1("foo"); + string s2("bar"); + string s3("baz"); + + StringPiece p1(s1); + StringPiece p2(s2); + StringPiece p3(s3); + + typedef std::map TestMap; + TestMap map; + + map.insert(std::make_pair(p1, 0)); + map.insert(std::make_pair(p2, 1)); + map.insert(std::make_pair(p3, 2)); + EXPECT_EQ(map.size(), 3); + + TestMap::const_iterator iter = map.begin(); + EXPECT_EQ(iter->second, 1); + ++iter; + EXPECT_EQ(iter->second, 2); + ++iter; + EXPECT_EQ(iter->second, 0); + ++iter; + EXPECT_TRUE(iter == map.end()); + + TestMap::iterator new_iter = map.find("zot"); + EXPECT_TRUE(new_iter == map.end()); + + new_iter = map.find("bar"); + EXPECT_TRUE(new_iter != map.end()); + + map.erase(new_iter); + EXPECT_EQ(map.size(), 2); + + iter = map.begin(); + EXPECT_EQ(iter->second, 2); + ++iter; + EXPECT_EQ(iter->second, 0); + ++iter; + EXPECT_TRUE(iter == map.end()); +} + +TEST(StringPiece, ComparisonOperators) { +#define COMPARE(result, op, x, y) \ + EXPECT_EQ(result, StringPiece((x)) op StringPiece((y))); \ + EXPECT_EQ(result, StringPiece((x)).compare(StringPiece((y))) op 0) + + COMPARE(true, ==, "", ""); + COMPARE(true, ==, "", NULL); + COMPARE(true, ==, NULL, ""); + COMPARE(true, ==, "a", "a"); + COMPARE(true, ==, "aa", "aa"); + COMPARE(false, ==, "a", ""); + COMPARE(false, ==, "", "a"); + COMPARE(false, ==, "a", "b"); + COMPARE(false, ==, "a", "aa"); + COMPARE(false, ==, "aa", "a"); + + COMPARE(false, !=, "", ""); + COMPARE(false, !=, "a", "a"); + COMPARE(false, !=, "aa", "aa"); + COMPARE(true, !=, "a", ""); + COMPARE(true, !=, "", "a"); + COMPARE(true, !=, "a", "b"); + COMPARE(true, !=, "a", "aa"); + COMPARE(true, !=, "aa", "a"); + + COMPARE(true, <, "a", "b"); + COMPARE(true, <, "a", "aa"); + COMPARE(true, <, "aa", "b"); + COMPARE(true, <, "aa", "bb"); + COMPARE(false, <, "a", "a"); + COMPARE(false, <, "b", "a"); + COMPARE(false, <, "aa", "a"); + COMPARE(false, <, "b", "aa"); + COMPARE(false, <, "bb", "aa"); + + COMPARE(true, <=, "a", "a"); + COMPARE(true, <=, "a", "b"); + COMPARE(true, <=, "a", "aa"); + COMPARE(true, <=, "aa", "b"); + COMPARE(true, <=, "aa", "bb"); + COMPARE(false, <=, "b", "a"); + COMPARE(false, <=, "aa", "a"); + COMPARE(false, <=, "b", "aa"); + COMPARE(false, <=, "bb", "aa"); + + COMPARE(false, >=, "a", "b"); + COMPARE(false, >=, "a", "aa"); + COMPARE(false, >=, "aa", "b"); + COMPARE(false, >=, "aa", "bb"); + COMPARE(true, >=, "a", "a"); + COMPARE(true, >=, "b", "a"); + COMPARE(true, >=, "aa", "a"); + COMPARE(true, >=, "b", "aa"); + COMPARE(true, >=, "bb", "aa"); + + COMPARE(false, >, "a", "a"); + COMPARE(false, >, "a", "b"); + COMPARE(false, >, "a", "aa"); + COMPARE(false, >, "aa", "b"); + COMPARE(false, >, "aa", "bb"); + COMPARE(true, >, "b", "a"); + COMPARE(true, >, "aa", "a"); + COMPARE(true, >, "b", "aa"); + COMPARE(true, >, "bb", "aa"); + + string x; + for (int i = 0; i < 256; i++) { + x += 'a'; + string y = x; + COMPARE(true, ==, x, y); + for (int j = 0; j < i; j++) { + string z = x; + z[j] = 'b'; // Differs in position 'j' + COMPARE(false, ==, x, z); + COMPARE(true, <, x, z); + COMPARE(true, >, z, x); + if (j + 1 < i) { + z[j + 1] = 'A'; // Differs in position 'j+1' as well + COMPARE(false, ==, x, z); + COMPARE(true, <, x, z); + COMPARE(true, >, z, x); + z[j + 1] = 'z'; // Differs in position 'j+1' as well + COMPARE(false, ==, x, z); + COMPARE(true, <, x, z); + COMPARE(true, >, z, x); + } + } + } + +#undef COMPARE +} + +TEST(StringPiece, STL1) { + const StringPiece a("abcdefghijklmnopqrstuvwxyz"); + const StringPiece b("abc"); + const StringPiece c("xyz"); + const StringPiece d("foobar"); + const StringPiece e; + string temp("123"); + temp += '\0'; + temp += "456"; + const StringPiece f(temp); + + EXPECT_EQ(a[6], 'g'); + EXPECT_EQ(b[0], 'a'); + EXPECT_EQ(c[2], 'z'); + EXPECT_EQ(f[3], '\0'); + EXPECT_EQ(f[5], '5'); + + EXPECT_EQ(*d.data(), 'f'); + EXPECT_EQ(d.data()[5], 'r'); + EXPECT_TRUE(e.data() == NULL); + + EXPECT_EQ(*a.begin(), 'a'); + EXPECT_EQ(*(b.begin() + 2), 'c'); + EXPECT_EQ(*(c.end() - 1), 'z'); + + EXPECT_EQ(*a.rbegin(), 'z'); + EXPECT_EQ(*(b.rbegin() + 2), 'a'); + EXPECT_EQ(*(c.rend() - 1), 'x'); + EXPECT_TRUE(a.rbegin() + 26 == a.rend()); + + EXPECT_EQ(a.size(), 26); + EXPECT_EQ(b.size(), 3); + EXPECT_EQ(c.size(), 3); + EXPECT_EQ(d.size(), 6); + EXPECT_EQ(e.size(), 0); + EXPECT_EQ(f.size(), 7); + + EXPECT_TRUE(!d.empty()); + EXPECT_TRUE(d.begin() != d.end()); + EXPECT_TRUE(d.begin() + 6 == d.end()); + + EXPECT_TRUE(e.empty()); + EXPECT_TRUE(e.begin() == e.end()); + + EXPECT_GE(a.max_size(), a.capacity()); + EXPECT_GE(a.capacity(), a.size()); + + char buf[4] = { '%', '%', '%', '%' }; + EXPECT_EQ(a.copy(buf, 4), 4); + EXPECT_EQ(buf[0], a[0]); + EXPECT_EQ(buf[1], a[1]); + EXPECT_EQ(buf[2], a[2]); + EXPECT_EQ(buf[3], a[3]); + EXPECT_EQ(a.copy(buf, 3, 7), 3); + EXPECT_EQ(buf[0], a[7]); + EXPECT_EQ(buf[1], a[8]); + EXPECT_EQ(buf[2], a[9]); + EXPECT_EQ(buf[3], a[3]); + EXPECT_EQ(c.copy(buf, 99), 3); + EXPECT_EQ(buf[0], c[0]); + EXPECT_EQ(buf[1], c[1]); + EXPECT_EQ(buf[2], c[2]); + EXPECT_EQ(buf[3], a[3]); +} + +// Separated from STL1() because some compilers produce an overly +// large stack frame for the combined function. +TEST(StringPiece, STL2) { + const StringPiece a("abcdefghijklmnopqrstuvwxyz"); + const StringPiece b("abc"); + const StringPiece c("xyz"); + StringPiece d("foobar"); + const StringPiece e; + const StringPiece f("123" "\0" "456", 7); + + d.clear(); + EXPECT_EQ(d.size(), 0); + EXPECT_TRUE(d.empty()); + EXPECT_TRUE(d.data() == NULL); + EXPECT_TRUE(d.begin() == d.end()); + + EXPECT_EQ(StringPiece::npos, string::npos); + + EXPECT_EQ(a.find(b), 0); + EXPECT_EQ(a.find(b, 1), StringPiece::npos); + EXPECT_EQ(a.find(c), 23); + EXPECT_EQ(a.find(c, 9), 23); + EXPECT_EQ(a.find(c, StringPiece::npos), StringPiece::npos); + EXPECT_EQ(b.find(c), StringPiece::npos); + EXPECT_EQ(b.find(c, StringPiece::npos), StringPiece::npos); + EXPECT_EQ(a.find(d), 0); + EXPECT_EQ(a.find(e), 0); + EXPECT_EQ(a.find(d, 12), 12); + EXPECT_EQ(a.find(e, 17), 17); + StringPiece g("xx not found bb"); + EXPECT_EQ(a.find(g), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(d.find(b), StringPiece::npos); + EXPECT_EQ(e.find(b), StringPiece::npos); + EXPECT_EQ(d.find(b, 4), StringPiece::npos); + EXPECT_EQ(e.find(b, 7), StringPiece::npos); + + size_t empty_search_pos = string().find(string()); + EXPECT_EQ(d.find(d), empty_search_pos); + EXPECT_EQ(d.find(e), empty_search_pos); + EXPECT_EQ(e.find(d), empty_search_pos); + EXPECT_EQ(e.find(e), empty_search_pos); + EXPECT_EQ(d.find(d, 4), string().find(string(), 4)); + EXPECT_EQ(d.find(e, 4), string().find(string(), 4)); + EXPECT_EQ(e.find(d, 4), string().find(string(), 4)); + EXPECT_EQ(e.find(e, 4), string().find(string(), 4)); + + EXPECT_EQ(a.find('a'), 0); + EXPECT_EQ(a.find('c'), 2); + EXPECT_EQ(a.find('z'), 25); + EXPECT_EQ(a.find('$'), StringPiece::npos); + EXPECT_EQ(a.find('\0'), StringPiece::npos); + EXPECT_EQ(f.find('\0'), 3); + EXPECT_EQ(f.find('3'), 2); + EXPECT_EQ(f.find('5'), 5); + EXPECT_EQ(g.find('o'), 4); + EXPECT_EQ(g.find('o', 4), 4); + EXPECT_EQ(g.find('o', 5), 8); + EXPECT_EQ(a.find('b', 5), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(d.find('\0'), StringPiece::npos); + EXPECT_EQ(e.find('\0'), StringPiece::npos); + EXPECT_EQ(d.find('\0', 4), StringPiece::npos); + EXPECT_EQ(e.find('\0', 7), StringPiece::npos); + EXPECT_EQ(d.find('x'), StringPiece::npos); + EXPECT_EQ(e.find('x'), StringPiece::npos); + EXPECT_EQ(d.find('x', 4), StringPiece::npos); + EXPECT_EQ(e.find('x', 7), StringPiece::npos); + + EXPECT_EQ(a.rfind(b), 0); + EXPECT_EQ(a.rfind(b, 1), 0); + EXPECT_EQ(a.rfind(c), 23); + EXPECT_EQ(a.rfind(c, 22), StringPiece::npos); + EXPECT_EQ(a.rfind(c, 1), StringPiece::npos); + EXPECT_EQ(a.rfind(c, 0), StringPiece::npos); + EXPECT_EQ(b.rfind(c), StringPiece::npos); + EXPECT_EQ(b.rfind(c, 0), StringPiece::npos); + EXPECT_EQ(a.rfind(d), a.as_string().rfind(string())); + EXPECT_EQ(a.rfind(e), a.as_string().rfind(string())); + EXPECT_EQ(a.rfind(d, 12), 12); + EXPECT_EQ(a.rfind(e, 17), 17); + EXPECT_EQ(a.rfind(g), StringPiece::npos); + EXPECT_EQ(d.rfind(b), StringPiece::npos); + EXPECT_EQ(e.rfind(b), StringPiece::npos); + EXPECT_EQ(d.rfind(b, 4), StringPiece::npos); + EXPECT_EQ(e.rfind(b, 7), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(d.rfind(d, 4), string().rfind(string())); + EXPECT_EQ(e.rfind(d, 7), string().rfind(string())); + EXPECT_EQ(d.rfind(e, 4), string().rfind(string())); + EXPECT_EQ(e.rfind(e, 7), string().rfind(string())); + EXPECT_EQ(d.rfind(d), string().rfind(string())); + EXPECT_EQ(e.rfind(d), string().rfind(string())); + EXPECT_EQ(d.rfind(e), string().rfind(string())); + EXPECT_EQ(e.rfind(e), string().rfind(string())); + + EXPECT_EQ(g.rfind('o'), 8); + EXPECT_EQ(g.rfind('q'), StringPiece::npos); + EXPECT_EQ(g.rfind('o', 8), 8); + EXPECT_EQ(g.rfind('o', 7), 4); + EXPECT_EQ(g.rfind('o', 3), StringPiece::npos); + EXPECT_EQ(f.rfind('\0'), 3); + EXPECT_EQ(f.rfind('\0', 12), 3); + EXPECT_EQ(f.rfind('3'), 2); + EXPECT_EQ(f.rfind('5'), 5); + // empty string nonsense + EXPECT_EQ(d.rfind('o'), StringPiece::npos); + EXPECT_EQ(e.rfind('o'), StringPiece::npos); + EXPECT_EQ(d.rfind('o', 4), StringPiece::npos); + EXPECT_EQ(e.rfind('o', 7), StringPiece::npos); + + EXPECT_EQ(a.find_first_of(b), 0); + EXPECT_EQ(a.find_first_of(b, 0), 0); + EXPECT_EQ(a.find_first_of(b, 1), 1); + EXPECT_EQ(a.find_first_of(b, 2), 2); + EXPECT_EQ(a.find_first_of(b, 3), StringPiece::npos); + EXPECT_EQ(a.find_first_of(c), 23); + EXPECT_EQ(a.find_first_of(c, 23), 23); + EXPECT_EQ(a.find_first_of(c, 24), 24); + EXPECT_EQ(a.find_first_of(c, 25), 25); + EXPECT_EQ(a.find_first_of(c, 26), StringPiece::npos); + EXPECT_EQ(g.find_first_of(b), 13); + EXPECT_EQ(g.find_first_of(c), 0); + EXPECT_EQ(a.find_first_of(f), StringPiece::npos); + EXPECT_EQ(f.find_first_of(a), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(a.find_first_of(d), StringPiece::npos); + EXPECT_EQ(a.find_first_of(e), StringPiece::npos); + EXPECT_EQ(d.find_first_of(b), StringPiece::npos); + EXPECT_EQ(e.find_first_of(b), StringPiece::npos); + EXPECT_EQ(d.find_first_of(d), StringPiece::npos); + EXPECT_EQ(e.find_first_of(d), StringPiece::npos); + EXPECT_EQ(d.find_first_of(e), StringPiece::npos); + EXPECT_EQ(e.find_first_of(e), StringPiece::npos); + + EXPECT_EQ(a.find_first_not_of(b), 3); + EXPECT_EQ(a.find_first_not_of(c), 0); + EXPECT_EQ(b.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(c.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(f.find_first_not_of(a), 0); + EXPECT_EQ(a.find_first_not_of(f), 0); + EXPECT_EQ(a.find_first_not_of(d), 0); + EXPECT_EQ(a.find_first_not_of(e), 0); + // empty string nonsense + EXPECT_EQ(d.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of(a), StringPiece::npos); + EXPECT_EQ(d.find_first_not_of(d), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of(d), StringPiece::npos); + EXPECT_EQ(d.find_first_not_of(e), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of(e), StringPiece::npos); + + StringPiece h("===="); + EXPECT_EQ(h.find_first_not_of('='), StringPiece::npos); + EXPECT_EQ(h.find_first_not_of('=', 3), StringPiece::npos); + EXPECT_EQ(h.find_first_not_of('\0'), 0); + EXPECT_EQ(g.find_first_not_of('x'), 2); + EXPECT_EQ(f.find_first_not_of('\0'), 0); + EXPECT_EQ(f.find_first_not_of('\0', 3), 4); + EXPECT_EQ(f.find_first_not_of('\0', 2), 2); + // empty string nonsense + EXPECT_EQ(d.find_first_not_of('x'), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of('x'), StringPiece::npos); + EXPECT_EQ(d.find_first_not_of('\0'), StringPiece::npos); + EXPECT_EQ(e.find_first_not_of('\0'), StringPiece::npos); + + // StringPiece g("xx not found bb"); + StringPiece i("56"); + EXPECT_EQ(h.find_last_of(a), StringPiece::npos); + EXPECT_EQ(g.find_last_of(a), g.size()-1); + EXPECT_EQ(a.find_last_of(b), 2); + EXPECT_EQ(a.find_last_of(c), a.size()-1); + EXPECT_EQ(f.find_last_of(i), 6); + EXPECT_EQ(a.find_last_of('a'), 0); + EXPECT_EQ(a.find_last_of('b'), 1); + EXPECT_EQ(a.find_last_of('z'), 25); + EXPECT_EQ(a.find_last_of('a', 5), 0); + EXPECT_EQ(a.find_last_of('b', 5), 1); + EXPECT_EQ(a.find_last_of('b', 0), StringPiece::npos); + EXPECT_EQ(a.find_last_of('z', 25), 25); + EXPECT_EQ(a.find_last_of('z', 24), StringPiece::npos); + EXPECT_EQ(f.find_last_of(i, 5), 5); + EXPECT_EQ(f.find_last_of(i, 6), 6); + EXPECT_EQ(f.find_last_of(a, 4), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(f.find_last_of(d), StringPiece::npos); + EXPECT_EQ(f.find_last_of(e), StringPiece::npos); + EXPECT_EQ(f.find_last_of(d, 4), StringPiece::npos); + EXPECT_EQ(f.find_last_of(e, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_of(d), StringPiece::npos); + EXPECT_EQ(d.find_last_of(e), StringPiece::npos); + EXPECT_EQ(e.find_last_of(d), StringPiece::npos); + EXPECT_EQ(e.find_last_of(e), StringPiece::npos); + EXPECT_EQ(d.find_last_of(f), StringPiece::npos); + EXPECT_EQ(e.find_last_of(f), StringPiece::npos); + EXPECT_EQ(d.find_last_of(d, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_of(e, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_of(d, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_of(e, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_of(f, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_of(f, 4), StringPiece::npos); + + EXPECT_EQ(a.find_last_not_of(b), a.size()-1); + EXPECT_EQ(a.find_last_not_of(c), 22); + EXPECT_EQ(b.find_last_not_of(a), StringPiece::npos); + EXPECT_EQ(b.find_last_not_of(b), StringPiece::npos); + EXPECT_EQ(f.find_last_not_of(i), 4); + EXPECT_EQ(a.find_last_not_of(c, 24), 22); + EXPECT_EQ(a.find_last_not_of(b, 3), 3); + EXPECT_EQ(a.find_last_not_of(b, 2), StringPiece::npos); + // empty string nonsense + EXPECT_EQ(f.find_last_not_of(d), f.size()-1); + EXPECT_EQ(f.find_last_not_of(e), f.size()-1); + EXPECT_EQ(f.find_last_not_of(d, 4), 4); + EXPECT_EQ(f.find_last_not_of(e, 4), 4); + EXPECT_EQ(d.find_last_not_of(d), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(e), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(d), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(e), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(f), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(f), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(d, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(e, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(d, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(e, 4), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of(f, 4), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of(f, 4), StringPiece::npos); + + EXPECT_EQ(h.find_last_not_of('x'), h.size() - 1); + EXPECT_EQ(h.find_last_not_of('='), StringPiece::npos); + EXPECT_EQ(b.find_last_not_of('c'), 1); + EXPECT_EQ(h.find_last_not_of('x', 2), 2); + EXPECT_EQ(h.find_last_not_of('=', 2), StringPiece::npos); + EXPECT_EQ(b.find_last_not_of('b', 1), 0); + // empty string nonsense + EXPECT_EQ(d.find_last_not_of('x'), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of('x'), StringPiece::npos); + EXPECT_EQ(d.find_last_not_of('\0'), StringPiece::npos); + EXPECT_EQ(e.find_last_not_of('\0'), StringPiece::npos); + + EXPECT_EQ(a.substr(0, 3), b); + EXPECT_EQ(a.substr(23), c); + EXPECT_EQ(a.substr(23, 3), c); + EXPECT_EQ(a.substr(23, 99), c); + EXPECT_EQ(a.substr(0), a); + EXPECT_EQ(a.substr(3, 2), "de"); + // empty string nonsense + EXPECT_EQ(a.substr(99, 2), e); + EXPECT_EQ(d.substr(99), e); + EXPECT_EQ(d.substr(0, 99), e); + EXPECT_EQ(d.substr(99, 99), e); + // use of npos + EXPECT_EQ(a.substr(0, StringPiece::npos), a); + EXPECT_EQ(a.substr(23, StringPiece::npos), c); + EXPECT_EQ(a.substr(StringPiece::npos, 0), e); + EXPECT_EQ(a.substr(StringPiece::npos, 1), e); + EXPECT_EQ(a.substr(StringPiece::npos, StringPiece::npos), e); + + // Substring constructors. + EXPECT_EQ(StringPiece(a, 0, 3), b); + EXPECT_EQ(StringPiece(a, 23), c); + EXPECT_EQ(StringPiece(a, 23, 3), c); + EXPECT_EQ(StringPiece(a, 23, 99), c); + EXPECT_EQ(StringPiece(a, 0), a); + EXPECT_EQ(StringPiece(a, 3, 2), "de"); + // empty string nonsense + EXPECT_EQ(StringPiece(d, 0, 99), e); + // Verify that they work taking an actual string, not just a StringPiece. + string a2 = a.as_string(); + EXPECT_EQ(StringPiece(a2, 0, 3), b); + EXPECT_EQ(StringPiece(a2, 23), c); + EXPECT_EQ(StringPiece(a2, 23, 3), c); + EXPECT_EQ(StringPiece(a2, 23, 99), c); + EXPECT_EQ(StringPiece(a2, 0), a); + EXPECT_EQ(StringPiece(a2, 3, 2), "de"); +} + +TEST(StringPiece, Custom) { + StringPiece a("foobar"); + string s1("123"); + s1 += '\0'; + s1 += "456"; + StringPiece b(s1); + StringPiece e; + string s2; + + // CopyToString + a.CopyToString(&s2); + EXPECT_EQ(s2.size(), 6); + EXPECT_EQ(s2, "foobar"); + b.CopyToString(&s2); + EXPECT_EQ(s2.size(), 7); + EXPECT_EQ(s1, s2); + e.CopyToString(&s2); + EXPECT_TRUE(s2.empty()); + + // AppendToString + s2.erase(); + a.AppendToString(&s2); + EXPECT_EQ(s2.size(), 6); + EXPECT_EQ(s2, "foobar"); + a.AppendToString(&s2); + EXPECT_EQ(s2.size(), 12); + EXPECT_EQ(s2, "foobarfoobar"); + + // starts_with + EXPECT_TRUE(a.starts_with(a)); + EXPECT_TRUE(a.starts_with("foo")); + EXPECT_TRUE(a.starts_with(e)); + EXPECT_TRUE(b.starts_with(s1)); + EXPECT_TRUE(b.starts_with(b)); + EXPECT_TRUE(b.starts_with(e)); + EXPECT_TRUE(e.starts_with("")); + EXPECT_TRUE(!a.starts_with(b)); + EXPECT_TRUE(!b.starts_with(a)); + EXPECT_TRUE(!e.starts_with(a)); + + // ends with + EXPECT_TRUE(a.ends_with(a)); + EXPECT_TRUE(a.ends_with("bar")); + EXPECT_TRUE(a.ends_with(e)); + EXPECT_TRUE(b.ends_with(s1)); + EXPECT_TRUE(b.ends_with(b)); + EXPECT_TRUE(b.ends_with(e)); + EXPECT_TRUE(e.ends_with("")); + EXPECT_TRUE(!a.ends_with(b)); + EXPECT_TRUE(!b.ends_with(a)); + EXPECT_TRUE(!e.ends_with(a)); + + // remove_prefix + StringPiece c(a); + c.remove_prefix(3); + EXPECT_EQ(c, "bar"); + c = a; + c.remove_prefix(0); + EXPECT_EQ(c, a); + c.remove_prefix(c.size()); + EXPECT_EQ(c, e); + + // remove_suffix + c = a; + c.remove_suffix(3); + EXPECT_EQ(c, "foo"); + c = a; + c.remove_suffix(0); + EXPECT_EQ(c, a); + c.remove_suffix(c.size()); + EXPECT_EQ(c, e); + + // set + c.set("foobar", 6); + EXPECT_EQ(c, a); + c.set("foobar", 0); + EXPECT_EQ(c, e); + c.set("foobar", 7); + EXPECT_NE(c, a); + + c.set("foobar"); + EXPECT_EQ(c, a); + + c.set(static_cast("foobar"), 6); + EXPECT_EQ(c, a); + c.set(static_cast("foobar"), 0); + EXPECT_EQ(c, e); + c.set(static_cast("foobar"), 7); + EXPECT_NE(c, a); + + // as_string + string s3(a.as_string().c_str(), 7); + EXPECT_EQ(c, s3); + string s4(e.as_string()); + EXPECT_TRUE(s4.empty()); + + // ToString + { + string s5(a.ToString().c_str(), 7); + EXPECT_EQ(c, s5); + string s6(e.ToString()); + EXPECT_TRUE(s6.empty()); + } + + // Consume + a.set("foobar"); + EXPECT_TRUE(a.Consume("foo")); + EXPECT_EQ(a, "bar"); + EXPECT_FALSE(a.Consume("foo")); + EXPECT_FALSE(a.Consume("barbar")); + EXPECT_FALSE(a.Consume("ar")); + EXPECT_EQ(a, "bar"); + + a.set("foobar"); + EXPECT_TRUE(a.ConsumeFromEnd("bar")); + EXPECT_EQ(a, "foo"); + EXPECT_FALSE(a.ConsumeFromEnd("bar")); + EXPECT_FALSE(a.ConsumeFromEnd("foofoo")); + EXPECT_FALSE(a.ConsumeFromEnd("fo")); + EXPECT_EQ(a, "foo"); +} + +TEST(StringPiece, Contains) { + StringPiece a("abcdefg"); + StringPiece b("abcd"); + StringPiece c("efg"); + StringPiece d("gh"); + EXPECT_TRUE(a.contains(b)); + EXPECT_TRUE(a.contains(c)); + EXPECT_TRUE(!a.contains(d)); +} + +TEST(StringPiece, NULLInput) { + // we used to crash here, but now we don't. + StringPiece s(NULL); + EXPECT_EQ(s.data(), (const char*)NULL); + EXPECT_EQ(s.size(), 0); + + s.set(NULL); + EXPECT_EQ(s.data(), (const char*)NULL); + EXPECT_EQ(s.size(), 0); + + // .ToString() on a StringPiece with NULL should produce the empty string. + EXPECT_EQ("", s.ToString()); + EXPECT_EQ("", s.as_string()); +} + +TEST(StringPiece, Comparisons2) { + StringPiece abc("abcdefghijklmnopqrstuvwxyz"); + + // check comparison operations on strings longer than 4 bytes. + EXPECT_EQ(abc, StringPiece("abcdefghijklmnopqrstuvwxyz")); + EXPECT_EQ(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyz")), 0); + + EXPECT_LT(abc, StringPiece("abcdefghijklmnopqrstuvwxzz")); + EXPECT_LT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxzz")), 0); + + EXPECT_GT(abc, StringPiece("abcdefghijklmnopqrstuvwxyy")); + EXPECT_GT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyy")), 0); + + // starts_with + EXPECT_TRUE(abc.starts_with(abc)); + EXPECT_TRUE(abc.starts_with("abcdefghijklm")); + EXPECT_TRUE(!abc.starts_with("abcdefguvwxyz")); + + // ends_with + EXPECT_TRUE(abc.ends_with(abc)); + EXPECT_TRUE(!abc.ends_with("abcdefguvwxyz")); + EXPECT_TRUE(abc.ends_with("nopqrstuvwxyz")); +} + +TEST(ComparisonOpsTest, StringCompareNotAmbiguous) { + EXPECT_EQ("hello", string("hello")); + EXPECT_LT("hello", string("world")); +} + +TEST(ComparisonOpsTest, HeterogenousStringPieceEquals) { + EXPECT_EQ(StringPiece("hello"), string("hello")); + EXPECT_EQ("hello", StringPiece("hello")); +} + +TEST(FindOneCharTest, EdgeCases) { + StringPiece a("xxyyyxx"); + + // Set a = "xyyyx". + a.remove_prefix(1); + a.remove_suffix(1); + + EXPECT_EQ(0, a.find('x')); + EXPECT_EQ(0, a.find('x', 0)); + EXPECT_EQ(4, a.find('x', 1)); + EXPECT_EQ(4, a.find('x', 4)); + EXPECT_EQ(StringPiece::npos, a.find('x', 5)); + + EXPECT_EQ(4, a.rfind('x')); + EXPECT_EQ(4, a.rfind('x', 5)); + EXPECT_EQ(4, a.rfind('x', 4)); + EXPECT_EQ(0, a.rfind('x', 3)); + EXPECT_EQ(0, a.rfind('x', 0)); + + // Set a = "yyy". + a.remove_prefix(1); + a.remove_suffix(1); + + EXPECT_EQ(StringPiece::npos, a.find('x')); + EXPECT_EQ(StringPiece::npos, a.rfind('x')); +} + +#ifdef PROTOBUF_HAS_DEATH_TEST +#ifndef NDEBUG +TEST(NonNegativeLenTest, NonNegativeLen) { + EXPECT_DEATH(StringPiece("xyz", -1), "len >= 0"); +} +#endif // ndef DEBUG +#endif // PROTOBUF_HAS_DEATH_TEST + +} // namespace +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stringprintf.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringprintf.cc similarity index 98% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stringprintf.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringprintf.cc index 3272d8e38..d98b9b874 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stringprintf.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringprintf.cc @@ -37,7 +37,6 @@ #include // MSVC requires this for _vsnprintf #include #include -#include namespace google { namespace protobuf { @@ -138,7 +137,7 @@ const int kStringPrintfVectorMaxArgs = 32; // and we can fix the problem or protect against an attack. static const char string_printf_empty_block[256] = { '\0' }; -string StringPrintfVector(const char* format, const vector& v) { +string StringPrintfVector(const char* format, const std::vector& v) { GOOGLE_CHECK_LE(v.size(), kStringPrintfVectorMaxArgs) << "StringPrintfVector currently only supports up to " << kStringPrintfVectorMaxArgs << " arguments. " diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stringprintf.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringprintf.h similarity index 98% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stringprintf.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringprintf.h index ab1ab5583..7183ec6a0 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stringprintf.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringprintf.h @@ -68,7 +68,7 @@ LIBPROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs; // You can use this version when all your arguments are strings, but // you don't know how many arguments you'll have at compile time. // StringPrintfVector will LOG(FATAL) if v.size() > kStringPrintfVectorMaxArgs -LIBPROTOBUF_EXPORT extern string StringPrintfVector(const char* format, const vector& v); +LIBPROTOBUF_EXPORT extern string StringPrintfVector(const char* format, const std::vector& v); } // namespace protobuf } // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stringprintf_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringprintf_unittest.cc similarity index 100% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/stringprintf_unittest.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/stringprintf_unittest.cc diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/structurally_valid.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/structurally_valid.cc similarity index 86% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/structurally_valid.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/structurally_valid.cc index 0f6afe6dc..b22396829 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/structurally_valid.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/structurally_valid.cc @@ -1,8 +1,39 @@ -// Copyright 2005-2008 Google Inc. All Rights Reserved. +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + // Author: jrm@google.com (Jim Meehan) #include +#include + namespace google { namespace protobuf { namespace internal { @@ -531,6 +562,56 @@ bool IsStructurallyValidUTF8(const char* buf, int len) { return (bytes_consumed == len); } +int UTF8SpnStructurallyValid(const StringPiece& str) { + if (!module_initialized_) return str.size(); + + int bytes_consumed = 0; + UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj, + str.data(), str.size(), &bytes_consumed); + return bytes_consumed; +} + +// Coerce UTF-8 byte string in src_str to be +// a structurally-valid equal-length string by selectively +// overwriting illegal bytes with replace_char (typically blank). +// replace_char must be legal printable 7-bit Ascii 0x20..0x7e. +// src_str is read-only. If any overwriting is needed, a modified byte string +// is created in idst, length isrclen. +// +// Returns pointer to output buffer, isrc if no changes were made, +// or idst if some bytes were changed. +// +// Fast case: all is structurally valid and no byte copying is done. +// +char* UTF8CoerceToStructurallyValid(const StringPiece& src_str, + char* idst, + const char replace_char) { + const char* isrc = src_str.data(); + const int len = src_str.length(); + int n = UTF8SpnStructurallyValid(src_str); + if (n == len) { // Normal case -- all is cool, return + return const_cast(isrc); + } else { // Unusual case -- copy w/o bad bytes + const char* src = isrc; + const char* srclimit = isrc + len; + char* dst = idst; + memmove(dst, src, n); // Copy initial good chunk + src += n; + dst += n; + while (src < srclimit) { // src points to bogus byte or is off the end + dst[0] = replace_char; // replace one bad byte + src++; + dst++; + StringPiece str2(src, srclimit - src); + n = UTF8SpnStructurallyValid(str2); // scan the remainder + memmove(dst, src, n); // copy next good chunk + src += n; + dst += n; + } + } + return idst; +} + } // namespace internal } // namespace protobuf } // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/structurally_valid_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/structurally_valid_unittest.cc new file mode 100644 index 000000000..eec07a87a --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/structurally_valid_unittest.cc @@ -0,0 +1,70 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Copyright 2008 Google Inc. All Rights Reserved. +// Author: xpeng@google.com (Peter Peng) + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +namespace { + +TEST(StructurallyValidTest, ValidUTF8String) { + // On GCC, this string can be written as: + // "abcd 1234 - \u2014\u2013\u2212" + // MSVC seems to interpret \u differently. + string valid_str("abcd 1234 - \342\200\224\342\200\223\342\210\222 - xyz789"); + EXPECT_TRUE(IsStructurallyValidUTF8(valid_str.data(), + valid_str.size())); + // Additional check for pointer alignment + for (int i = 1; i < 8; ++i) { + EXPECT_TRUE(IsStructurallyValidUTF8(valid_str.data() + i, + valid_str.size() - i)); + } +} + +TEST(StructurallyValidTest, InvalidUTF8String) { + const string invalid_str("abcd\xA0\xB0\xA0\xB0\xA0\xB0 - xyz789"); + EXPECT_FALSE(IsStructurallyValidUTF8(invalid_str.data(), + invalid_str.size())); + // Additional check for pointer alignment + for (int i = 1; i < 8; ++i) { + EXPECT_FALSE(IsStructurallyValidUTF8(invalid_str.data() + i, + invalid_str.size() - i)); + } +} + +} // namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/strutil.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/strutil.cc new file mode 100644 index 000000000..552d416f6 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/strutil.cc @@ -0,0 +1,2304 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// from google3/strings/strutil.cc + +#include +#include + +#include +#include // FLT_DIG and DBL_DIG +#include +#include +#include +#include + +#include + +#ifdef _WIN32 +// MSVC has only _snprintf, not snprintf. +// +// MinGW has both snprintf and _snprintf, but they appear to be different +// functions. The former is buggy. When invoked like so: +// char buffer[32]; +// snprintf(buffer, 32, "%.*g\n", FLT_DIG, 1.23e10f); +// it prints "1.23000e+10". This is plainly wrong: %g should never print +// trailing zeros after the decimal point. For some reason this bug only +// occurs with some input values, not all. In any case, _snprintf does the +// right thing, so we use it. +#define snprintf _snprintf +#endif + +namespace google { +namespace protobuf { + +// These are defined as macros on some platforms. #undef them so that we can +// redefine them. +#undef isxdigit +#undef isprint + +// The definitions of these in ctype.h change based on locale. Since our +// string manipulation is all in relation to the protocol buffer and C++ +// languages, we always want to use the C locale. So, we re-define these +// exactly as we want them. +inline bool isxdigit(char c) { + return ('0' <= c && c <= '9') || + ('a' <= c && c <= 'f') || + ('A' <= c && c <= 'F'); +} + +inline bool isprint(char c) { + return c >= 0x20 && c <= 0x7E; +} + +// ---------------------------------------------------------------------- +// StripString +// Replaces any occurrence of the character 'remove' (or the characters +// in 'remove') with the character 'replacewith'. +// ---------------------------------------------------------------------- +void StripString(string* s, const char* remove, char replacewith) { + const char * str_start = s->c_str(); + const char * str = str_start; + for (str = strpbrk(str, remove); + str != NULL; + str = strpbrk(str + 1, remove)) { + (*s)[str - str_start] = replacewith; + } +} + +// ---------------------------------------------------------------------- +// ReplaceCharacters +// Replaces any occurrence of the character 'remove' (or the characters +// in 'remove') with the character 'replacewith'. +// ---------------------------------------------------------------------- +void ReplaceCharacters(string *s, const char *remove, char replacewith) { + const char *str_start = s->c_str(); + const char *str = str_start; + for (str = strpbrk(str, remove); + str != NULL; + str = strpbrk(str + 1, remove)) { + (*s)[str - str_start] = replacewith; + } +} + +void StripWhitespace(string* str) { + int str_length = str->length(); + + // Strip off leading whitespace. + int first = 0; + while (first < str_length && ascii_isspace(str->at(first))) { + ++first; + } + // If entire string is white space. + if (first == str_length) { + str->clear(); + return; + } + if (first > 0) { + str->erase(0, first); + str_length -= first; + } + + // Strip off trailing whitespace. + int last = str_length - 1; + while (last >= 0 && ascii_isspace(str->at(last))) { + --last; + } + if (last != (str_length - 1) && last >= 0) { + str->erase(last + 1, string::npos); + } +} + +// ---------------------------------------------------------------------- +// StringReplace() +// Replace the "old" pattern with the "new" pattern in a string, +// and append the result to "res". If replace_all is false, +// it only replaces the first instance of "old." +// ---------------------------------------------------------------------- + +void StringReplace(const string& s, const string& oldsub, + const string& newsub, bool replace_all, + string* res) { + if (oldsub.empty()) { + res->append(s); // if empty, append the given string. + return; + } + + string::size_type start_pos = 0; + string::size_type pos; + do { + pos = s.find(oldsub, start_pos); + if (pos == string::npos) { + break; + } + res->append(s, start_pos, pos - start_pos); + res->append(newsub); + start_pos = pos + oldsub.size(); // start searching again after the "old" + } while (replace_all); + res->append(s, start_pos, s.length() - start_pos); +} + +// ---------------------------------------------------------------------- +// StringReplace() +// Give me a string and two patterns "old" and "new", and I replace +// the first instance of "old" in the string with "new", if it +// exists. If "global" is true; call this repeatedly until it +// fails. RETURN a new string, regardless of whether the replacement +// happened or not. +// ---------------------------------------------------------------------- + +string StringReplace(const string& s, const string& oldsub, + const string& newsub, bool replace_all) { + string ret; + StringReplace(s, oldsub, newsub, replace_all, &ret); + return ret; +} + +// ---------------------------------------------------------------------- +// SplitStringUsing() +// Split a string using a character delimiter. Append the components +// to 'result'. +// +// Note: For multi-character delimiters, this routine will split on *ANY* of +// the characters in the string, not the entire string as a single delimiter. +// ---------------------------------------------------------------------- +template +static inline +void SplitStringToIteratorUsing(const string& full, + const char* delim, + ITR& result) { + // Optimize the common case where delim is a single character. + if (delim[0] != '\0' && delim[1] == '\0') { + char c = delim[0]; + const char* p = full.data(); + const char* end = p + full.size(); + while (p != end) { + if (*p == c) { + ++p; + } else { + const char* start = p; + while (++p != end && *p != c); + *result++ = string(start, p - start); + } + } + return; + } + + string::size_type begin_index, end_index; + begin_index = full.find_first_not_of(delim); + while (begin_index != string::npos) { + end_index = full.find_first_of(delim, begin_index); + if (end_index == string::npos) { + *result++ = full.substr(begin_index); + return; + } + *result++ = full.substr(begin_index, (end_index - begin_index)); + begin_index = full.find_first_not_of(delim, end_index); + } +} + +void SplitStringUsing(const string& full, + const char* delim, + std::vector* result) { + std::back_insert_iterator< std::vector > it(*result); + SplitStringToIteratorUsing(full, delim, it); +} + +// Split a string using a character delimiter. Append the components +// to 'result'. If there are consecutive delimiters, this function +// will return corresponding empty strings. The string is split into +// at most the specified number of pieces greedily. This means that the +// last piece may possibly be split further. To split into as many pieces +// as possible, specify 0 as the number of pieces. +// +// If "full" is the empty string, yields an empty string as the only value. +// +// If "pieces" is negative for some reason, it returns the whole string +// ---------------------------------------------------------------------- +template +static inline +void SplitStringToIteratorAllowEmpty(const StringType& full, + const char* delim, + int pieces, + ITR& result) { + string::size_type begin_index, end_index; + begin_index = 0; + + for (int i = 0; (i < pieces-1) || (pieces == 0); i++) { + end_index = full.find_first_of(delim, begin_index); + if (end_index == string::npos) { + *result++ = full.substr(begin_index); + return; + } + *result++ = full.substr(begin_index, (end_index - begin_index)); + begin_index = end_index + 1; + } + *result++ = full.substr(begin_index); +} + +void SplitStringAllowEmpty(const string& full, const char* delim, + std::vector* result) { + std::back_insert_iterator > it(*result); + SplitStringToIteratorAllowEmpty(full, delim, 0, it); +} + +// ---------------------------------------------------------------------- +// JoinStrings() +// This merges a vector of string components with delim inserted +// as separaters between components. +// +// ---------------------------------------------------------------------- +template +static void JoinStringsIterator(const ITERATOR& start, + const ITERATOR& end, + const char* delim, + string* result) { + GOOGLE_CHECK(result != NULL); + result->clear(); + int delim_length = strlen(delim); + + // Precompute resulting length so we can reserve() memory in one shot. + int length = 0; + for (ITERATOR iter = start; iter != end; ++iter) { + if (iter != start) { + length += delim_length; + } + length += iter->size(); + } + result->reserve(length); + + // Now combine everything. + for (ITERATOR iter = start; iter != end; ++iter) { + if (iter != start) { + result->append(delim, delim_length); + } + result->append(iter->data(), iter->size()); + } +} + +void JoinStrings(const std::vector& components, + const char* delim, + string * result) { + JoinStringsIterator(components.begin(), components.end(), delim, result); +} + +// ---------------------------------------------------------------------- +// UnescapeCEscapeSequences() +// This does all the unescaping that C does: \ooo, \r, \n, etc +// Returns length of resulting string. +// The implementation of \x parses any positive number of hex digits, +// but it is an error if the value requires more than 8 bits, and the +// result is truncated to 8 bits. +// +// The second call stores its errors in a supplied string vector. +// If the string vector pointer is NULL, it reports the errors with LOG(). +// ---------------------------------------------------------------------- + +#define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7')) + +// Protocol buffers doesn't ever care about errors, but I don't want to remove +// the code. +#define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false) + +int UnescapeCEscapeSequences(const char* source, char* dest) { + return UnescapeCEscapeSequences(source, dest, NULL); +} + +int UnescapeCEscapeSequences(const char* source, char* dest, + std::vector *errors) { + GOOGLE_DCHECK(errors == NULL) << "Error reporting not implemented."; + + char* d = dest; + const char* p = source; + + // Small optimization for case where source = dest and there's no escaping + while ( p == d && *p != '\0' && *p != '\\' ) + p++, d++; + + while (*p != '\0') { + if (*p != '\\') { + *d++ = *p++; + } else { + switch ( *++p ) { // skip past the '\\' + case '\0': + LOG_STRING(ERROR, errors) << "String cannot end with \\"; + *d = '\0'; + return d - dest; // we're done with p + case 'a': *d++ = '\a'; break; + case 'b': *d++ = '\b'; break; + case 'f': *d++ = '\f'; break; + case 'n': *d++ = '\n'; break; + case 'r': *d++ = '\r'; break; + case 't': *d++ = '\t'; break; + case 'v': *d++ = '\v'; break; + case '\\': *d++ = '\\'; break; + case '?': *d++ = '\?'; break; // \? Who knew? + case '\'': *d++ = '\''; break; + case '"': *d++ = '\"'; break; + case '0': case '1': case '2': case '3': // octal digit: 1 to 3 digits + case '4': case '5': case '6': case '7': { + char ch = *p - '0'; + if ( IS_OCTAL_DIGIT(p[1]) ) + ch = ch * 8 + *++p - '0'; + if ( IS_OCTAL_DIGIT(p[1]) ) // safe (and easy) to do this twice + ch = ch * 8 + *++p - '0'; // now points at last digit + *d++ = ch; + break; + } + case 'x': case 'X': { + if (!isxdigit(p[1])) { + if (p[1] == '\0') { + LOG_STRING(ERROR, errors) << "String cannot end with \\x"; + } else { + LOG_STRING(ERROR, errors) << + "\\x cannot be followed by non-hex digit: \\" << *p << p[1]; + } + break; + } + unsigned int ch = 0; + const char *hex_start = p; + while (isxdigit(p[1])) // arbitrarily many hex digits + ch = (ch << 4) + hex_digit_to_int(*++p); + if (ch > 0xFF) + LOG_STRING(ERROR, errors) << "Value of " << + "\\" << string(hex_start, p+1-hex_start) << " exceeds 8 bits"; + *d++ = ch; + break; + } +#if 0 // TODO(kenton): Support \u and \U? Requires runetochar(). + case 'u': { + // \uhhhh => convert 4 hex digits to UTF-8 + char32 rune = 0; + const char *hex_start = p; + for (int i = 0; i < 4; ++i) { + if (isxdigit(p[1])) { // Look one char ahead. + rune = (rune << 4) + hex_digit_to_int(*++p); // Advance p. + } else { + LOG_STRING(ERROR, errors) + << "\\u must be followed by 4 hex digits: \\" + << string(hex_start, p+1-hex_start); + break; + } + } + d += runetochar(d, &rune); + break; + } + case 'U': { + // \Uhhhhhhhh => convert 8 hex digits to UTF-8 + char32 rune = 0; + const char *hex_start = p; + for (int i = 0; i < 8; ++i) { + if (isxdigit(p[1])) { // Look one char ahead. + // Don't change rune until we're sure this + // is within the Unicode limit, but do advance p. + char32 newrune = (rune << 4) + hex_digit_to_int(*++p); + if (newrune > 0x10FFFF) { + LOG_STRING(ERROR, errors) + << "Value of \\" + << string(hex_start, p + 1 - hex_start) + << " exceeds Unicode limit (0x10FFFF)"; + break; + } else { + rune = newrune; + } + } else { + LOG_STRING(ERROR, errors) + << "\\U must be followed by 8 hex digits: \\" + << string(hex_start, p+1-hex_start); + break; + } + } + d += runetochar(d, &rune); + break; + } +#endif + default: + LOG_STRING(ERROR, errors) << "Unknown escape sequence: \\" << *p; + } + p++; // read past letter we escaped + } + } + *d = '\0'; + return d - dest; +} + +// ---------------------------------------------------------------------- +// UnescapeCEscapeString() +// This does the same thing as UnescapeCEscapeSequences, but creates +// a new string. The caller does not need to worry about allocating +// a dest buffer. This should be used for non performance critical +// tasks such as printing debug messages. It is safe for src and dest +// to be the same. +// +// The second call stores its errors in a supplied string vector. +// If the string vector pointer is NULL, it reports the errors with LOG(). +// +// In the first and second calls, the length of dest is returned. In the +// the third call, the new string is returned. +// ---------------------------------------------------------------------- +int UnescapeCEscapeString(const string& src, string* dest) { + return UnescapeCEscapeString(src, dest, NULL); +} + +int UnescapeCEscapeString(const string& src, string* dest, + std::vector *errors) { + std::unique_ptr unescaped(new char[src.size() + 1]); + int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), errors); + GOOGLE_CHECK(dest); + dest->assign(unescaped.get(), len); + return len; +} + +string UnescapeCEscapeString(const string& src) { + std::unique_ptr unescaped(new char[src.size() + 1]); + int len = UnescapeCEscapeSequences(src.c_str(), unescaped.get(), NULL); + return string(unescaped.get(), len); +} + +// ---------------------------------------------------------------------- +// CEscapeString() +// CHexEscapeString() +// Copies 'src' to 'dest', escaping dangerous characters using +// C-style escape sequences. This is very useful for preparing query +// flags. 'src' and 'dest' should not overlap. The 'Hex' version uses +// hexadecimal rather than octal sequences. +// Returns the number of bytes written to 'dest' (not including the \0) +// or -1 if there was insufficient space. +// +// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped. +// ---------------------------------------------------------------------- +int CEscapeInternal(const char* src, int src_len, char* dest, + int dest_len, bool use_hex, bool utf8_safe) { + const char* src_end = src + src_len; + int used = 0; + bool last_hex_escape = false; // true if last output char was \xNN + + for (; src < src_end; src++) { + if (dest_len - used < 2) // Need space for two letter escape + return -1; + + bool is_hex_escape = false; + switch (*src) { + case '\n': dest[used++] = '\\'; dest[used++] = 'n'; break; + case '\r': dest[used++] = '\\'; dest[used++] = 'r'; break; + case '\t': dest[used++] = '\\'; dest[used++] = 't'; break; + case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break; + case '\'': dest[used++] = '\\'; dest[used++] = '\''; break; + case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break; + default: + // Note that if we emit \xNN and the src character after that is a hex + // digit then that digit must be escaped too to prevent it being + // interpreted as part of the character code by C. + if ((!utf8_safe || static_cast(*src) < 0x80) && + (!isprint(*src) || + (last_hex_escape && isxdigit(*src)))) { + if (dest_len - used < 4) // need space for 4 letter escape + return -1; + sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"), + static_cast(*src)); + is_hex_escape = use_hex; + used += 4; + } else { + dest[used++] = *src; break; + } + } + last_hex_escape = is_hex_escape; + } + + if (dest_len - used < 1) // make sure that there is room for \0 + return -1; + + dest[used] = '\0'; // doesn't count towards return value though + return used; +} + +// Calculates the length of the C-style escaped version of 'src'. +// Assumes that non-printable characters are escaped using octal sequences, and +// that UTF-8 bytes are not handled specially. +static inline size_t CEscapedLength(StringPiece src) { + static char c_escaped_len[256] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4, // \t, \n, \r + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // ", ' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // '0'..'9' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'A'..'O' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, // 'P'..'Z', '\' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 'a'..'o' + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, // 'p'..'z', DEL + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + }; + + size_t escaped_len = 0; + for (int i = 0; i < src.size(); ++i) { + unsigned char c = static_cast(src[i]); + escaped_len += c_escaped_len[c]; + } + return escaped_len; +} + +// ---------------------------------------------------------------------- +// Escapes 'src' using C-style escape sequences, and appends the escaped string +// to 'dest'. This version is faster than calling CEscapeInternal as it computes +// the required space using a lookup table, and also does not do any special +// handling for Hex or UTF-8 characters. +// ---------------------------------------------------------------------- +void CEscapeAndAppend(StringPiece src, string* dest) { + size_t escaped_len = CEscapedLength(src); + if (escaped_len == src.size()) { + dest->append(src.data(), src.size()); + return; + } + + size_t cur_dest_len = dest->size(); + dest->resize(cur_dest_len + escaped_len); + char* append_ptr = &(*dest)[cur_dest_len]; + + for (int i = 0; i < src.size(); ++i) { + unsigned char c = static_cast(src[i]); + switch (c) { + case '\n': *append_ptr++ = '\\'; *append_ptr++ = 'n'; break; + case '\r': *append_ptr++ = '\\'; *append_ptr++ = 'r'; break; + case '\t': *append_ptr++ = '\\'; *append_ptr++ = 't'; break; + case '\"': *append_ptr++ = '\\'; *append_ptr++ = '\"'; break; + case '\'': *append_ptr++ = '\\'; *append_ptr++ = '\''; break; + case '\\': *append_ptr++ = '\\'; *append_ptr++ = '\\'; break; + default: + if (!isprint(c)) { + *append_ptr++ = '\\'; + *append_ptr++ = '0' + c / 64; + *append_ptr++ = '0' + (c % 64) / 8; + *append_ptr++ = '0' + c % 8; + } else { + *append_ptr++ = c; + } + break; + } + } +} + +string CEscape(const string& src) { + string dest; + CEscapeAndAppend(src, &dest); + return dest; +} + +namespace strings { + +string Utf8SafeCEscape(const string& src) { + const int dest_length = src.size() * 4 + 1; // Maximum possible expansion + std::unique_ptr dest(new char[dest_length]); + const int len = CEscapeInternal(src.data(), src.size(), + dest.get(), dest_length, false, true); + GOOGLE_DCHECK_GE(len, 0); + return string(dest.get(), len); +} + +string CHexEscape(const string& src) { + const int dest_length = src.size() * 4 + 1; // Maximum possible expansion + std::unique_ptr dest(new char[dest_length]); + const int len = CEscapeInternal(src.data(), src.size(), + dest.get(), dest_length, true, false); + GOOGLE_DCHECK_GE(len, 0); + return string(dest.get(), len); +} + +} // namespace strings + +// ---------------------------------------------------------------------- +// strto32_adaptor() +// strtou32_adaptor() +// Implementation of strto[u]l replacements that have identical +// overflow and underflow characteristics for both ILP-32 and LP-64 +// platforms, including errno preservation in error-free calls. +// ---------------------------------------------------------------------- + +int32 strto32_adaptor(const char *nptr, char **endptr, int base) { + const int saved_errno = errno; + errno = 0; + const long result = strtol(nptr, endptr, base); + if (errno == ERANGE && result == LONG_MIN) { + return kint32min; + } else if (errno == ERANGE && result == LONG_MAX) { + return kint32max; + } else if (errno == 0 && result < kint32min) { + errno = ERANGE; + return kint32min; + } else if (errno == 0 && result > kint32max) { + errno = ERANGE; + return kint32max; + } + if (errno == 0) + errno = saved_errno; + return static_cast(result); +} + +uint32 strtou32_adaptor(const char *nptr, char **endptr, int base) { + const int saved_errno = errno; + errno = 0; + const unsigned long result = strtoul(nptr, endptr, base); + if (errno == ERANGE && result == ULONG_MAX) { + return kuint32max; + } else if (errno == 0 && result > kuint32max) { + errno = ERANGE; + return kuint32max; + } + if (errno == 0) + errno = saved_errno; + return static_cast(result); +} + +inline bool safe_parse_sign(string* text /*inout*/, + bool* negative_ptr /*output*/) { + const char* start = text->data(); + const char* end = start + text->size(); + + // Consume whitespace. + while (start < end && (start[0] == ' ')) { + ++start; + } + while (start < end && (end[-1] == ' ')) { + --end; + } + if (start >= end) { + return false; + } + + // Consume sign. + *negative_ptr = (start[0] == '-'); + if (*negative_ptr || start[0] == '+') { + ++start; + if (start >= end) { + return false; + } + } + *text = text->substr(start - text->data(), end - start); + return true; +} + +template +bool safe_parse_positive_int( + string text, IntType* value_p) { + int base = 10; + IntType value = 0; + const IntType vmax = std::numeric_limits::max(); + assert(vmax > 0); + assert(vmax >= base); + const IntType vmax_over_base = vmax / base; + const char* start = text.data(); + const char* end = start + text.size(); + // loop over digits + for (; start < end; ++start) { + unsigned char c = static_cast(start[0]); + int digit = c - '0'; + if (digit >= base || digit < 0) { + *value_p = value; + return false; + } + if (value > vmax_over_base) { + *value_p = vmax; + return false; + } + value *= base; + if (value > vmax - digit) { + *value_p = vmax; + return false; + } + value += digit; + } + *value_p = value; + return true; +} + +template +bool safe_parse_negative_int( + const string& text, IntType* value_p) { + int base = 10; + IntType value = 0; + const IntType vmin = std::numeric_limits::min(); + assert(vmin < 0); + assert(vmin <= 0 - base); + IntType vmin_over_base = vmin / base; + // 2003 c++ standard [expr.mul] + // "... the sign of the remainder is implementation-defined." + // Although (vmin/base)*base + vmin%base is always vmin. + // 2011 c++ standard tightens the spec but we cannot rely on it. + if (vmin % base > 0) { + vmin_over_base += 1; + } + const char* start = text.data(); + const char* end = start + text.size(); + // loop over digits + for (; start < end; ++start) { + unsigned char c = static_cast(start[0]); + int digit = c - '0'; + if (digit >= base || digit < 0) { + *value_p = value; + return false; + } + if (value < vmin_over_base) { + *value_p = vmin; + return false; + } + value *= base; + if (value < vmin + digit) { + *value_p = vmin; + return false; + } + value -= digit; + } + *value_p = value; + return true; +} + +template +bool safe_int_internal(string text, IntType* value_p) { + *value_p = 0; + bool negative; + if (!safe_parse_sign(&text, &negative)) { + return false; + } + if (!negative) { + return safe_parse_positive_int(text, value_p); + } else { + return safe_parse_negative_int(text, value_p); + } +} + +template +bool safe_uint_internal(string text, IntType* value_p) { + *value_p = 0; + bool negative; + if (!safe_parse_sign(&text, &negative) || negative) { + return false; + } + return safe_parse_positive_int(text, value_p); +} + +// ---------------------------------------------------------------------- +// FastIntToBuffer() +// FastInt64ToBuffer() +// FastHexToBuffer() +// FastHex64ToBuffer() +// FastHex32ToBuffer() +// ---------------------------------------------------------------------- + +// Offset into buffer where FastInt64ToBuffer places the end of string +// null character. Also used by FastInt64ToBufferLeft. +static const int kFastInt64ToBufferOffset = 21; + +char *FastInt64ToBuffer(int64 i, char* buffer) { + // We could collapse the positive and negative sections, but that + // would be slightly slower for positive numbers... + // 22 bytes is enough to store -2**64, -18446744073709551616. + char* p = buffer + kFastInt64ToBufferOffset; + *p-- = '\0'; + if (i >= 0) { + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + return p + 1; + } else { + // On different platforms, % and / have different behaviors for + // negative numbers, so we need to jump through hoops to make sure + // we don't divide negative numbers. + if (i > -10) { + i = -i; + *p-- = '0' + i; + *p = '-'; + return p; + } else { + // Make sure we aren't at MIN_INT, in which case we can't say i = -i + i = i + 10; + i = -i; + *p-- = '0' + i % 10; + // Undo what we did a moment ago + i = i / 10 + 1; + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + *p = '-'; + return p; + } + } +} + +// Offset into buffer where FastInt32ToBuffer places the end of string +// null character. Also used by FastInt32ToBufferLeft +static const int kFastInt32ToBufferOffset = 11; + +// Yes, this is a duplicate of FastInt64ToBuffer. But, we need this for the +// compiler to generate 32 bit arithmetic instructions. It's much faster, at +// least with 32 bit binaries. +char *FastInt32ToBuffer(int32 i, char* buffer) { + // We could collapse the positive and negative sections, but that + // would be slightly slower for positive numbers... + // 12 bytes is enough to store -2**32, -4294967296. + char* p = buffer + kFastInt32ToBufferOffset; + *p-- = '\0'; + if (i >= 0) { + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + return p + 1; + } else { + // On different platforms, % and / have different behaviors for + // negative numbers, so we need to jump through hoops to make sure + // we don't divide negative numbers. + if (i > -10) { + i = -i; + *p-- = '0' + i; + *p = '-'; + return p; + } else { + // Make sure we aren't at MIN_INT, in which case we can't say i = -i + i = i + 10; + i = -i; + *p-- = '0' + i % 10; + // Undo what we did a moment ago + i = i / 10 + 1; + do { + *p-- = '0' + i % 10; + i /= 10; + } while (i > 0); + *p = '-'; + return p; + } + } +} + +char *FastHexToBuffer(int i, char* buffer) { + GOOGLE_CHECK(i >= 0) << "FastHexToBuffer() wants non-negative integers, not " << i; + + static const char *hexdigits = "0123456789abcdef"; + char *p = buffer + 21; + *p-- = '\0'; + do { + *p-- = hexdigits[i & 15]; // mod by 16 + i >>= 4; // divide by 16 + } while (i > 0); + return p + 1; +} + +char *InternalFastHexToBuffer(uint64 value, char* buffer, int num_byte) { + static const char *hexdigits = "0123456789abcdef"; + buffer[num_byte] = '\0'; + for (int i = num_byte - 1; i >= 0; i--) { +#ifdef _M_X64 + // MSVC x64 platform has a bug optimizing the uint32(value) in the #else + // block. Given that the uint32 cast was to improve performance on 32-bit + // platforms, we use 64-bit '&' directly. + buffer[i] = hexdigits[value & 0xf]; +#else + buffer[i] = hexdigits[uint32(value) & 0xf]; +#endif + value >>= 4; + } + return buffer; +} + +char *FastHex64ToBuffer(uint64 value, char* buffer) { + return InternalFastHexToBuffer(value, buffer, 16); +} + +char *FastHex32ToBuffer(uint32 value, char* buffer) { + return InternalFastHexToBuffer(value, buffer, 8); +} + +// ---------------------------------------------------------------------- +// FastInt32ToBufferLeft() +// FastUInt32ToBufferLeft() +// FastInt64ToBufferLeft() +// FastUInt64ToBufferLeft() +// +// Like the Fast*ToBuffer() functions above, these are intended for speed. +// Unlike the Fast*ToBuffer() functions, however, these functions write +// their output to the beginning of the buffer (hence the name, as the +// output is left-aligned). The caller is responsible for ensuring that +// the buffer has enough space to hold the output. +// +// Returns a pointer to the end of the string (i.e. the null character +// terminating the string). +// ---------------------------------------------------------------------- + +static const char two_ASCII_digits[100][2] = { + {'0','0'}, {'0','1'}, {'0','2'}, {'0','3'}, {'0','4'}, + {'0','5'}, {'0','6'}, {'0','7'}, {'0','8'}, {'0','9'}, + {'1','0'}, {'1','1'}, {'1','2'}, {'1','3'}, {'1','4'}, + {'1','5'}, {'1','6'}, {'1','7'}, {'1','8'}, {'1','9'}, + {'2','0'}, {'2','1'}, {'2','2'}, {'2','3'}, {'2','4'}, + {'2','5'}, {'2','6'}, {'2','7'}, {'2','8'}, {'2','9'}, + {'3','0'}, {'3','1'}, {'3','2'}, {'3','3'}, {'3','4'}, + {'3','5'}, {'3','6'}, {'3','7'}, {'3','8'}, {'3','9'}, + {'4','0'}, {'4','1'}, {'4','2'}, {'4','3'}, {'4','4'}, + {'4','5'}, {'4','6'}, {'4','7'}, {'4','8'}, {'4','9'}, + {'5','0'}, {'5','1'}, {'5','2'}, {'5','3'}, {'5','4'}, + {'5','5'}, {'5','6'}, {'5','7'}, {'5','8'}, {'5','9'}, + {'6','0'}, {'6','1'}, {'6','2'}, {'6','3'}, {'6','4'}, + {'6','5'}, {'6','6'}, {'6','7'}, {'6','8'}, {'6','9'}, + {'7','0'}, {'7','1'}, {'7','2'}, {'7','3'}, {'7','4'}, + {'7','5'}, {'7','6'}, {'7','7'}, {'7','8'}, {'7','9'}, + {'8','0'}, {'8','1'}, {'8','2'}, {'8','3'}, {'8','4'}, + {'8','5'}, {'8','6'}, {'8','7'}, {'8','8'}, {'8','9'}, + {'9','0'}, {'9','1'}, {'9','2'}, {'9','3'}, {'9','4'}, + {'9','5'}, {'9','6'}, {'9','7'}, {'9','8'}, {'9','9'} +}; + +char* FastUInt32ToBufferLeft(uint32 u, char* buffer) { + uint32 digits; + const char *ASCII_digits = NULL; + // The idea of this implementation is to trim the number of divides to as few + // as possible by using multiplication and subtraction rather than mod (%), + // and by outputting two digits at a time rather than one. + // The huge-number case is first, in the hopes that the compiler will output + // that case in one branch-free block of code, and only output conditional + // branches into it from below. + if (u >= 1000000000) { // >= 1,000,000,000 + digits = u / 100000000; // 100,000,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +sublt100_000_000: + u -= digits * 100000000; // 100,000,000 +lt100_000_000: + digits = u / 1000000; // 1,000,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +sublt1_000_000: + u -= digits * 1000000; // 1,000,000 +lt1_000_000: + digits = u / 10000; // 10,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +sublt10_000: + u -= digits * 10000; // 10,000 +lt10_000: + digits = u / 100; + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +sublt100: + u -= digits * 100; +lt100: + digits = u; + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; +done: + *buffer = 0; + return buffer; + } + + if (u < 100) { + digits = u; + if (u >= 10) goto lt100; + *buffer++ = '0' + digits; + goto done; + } + if (u < 10000) { // 10,000 + if (u >= 1000) goto lt10_000; + digits = u / 100; + *buffer++ = '0' + digits; + goto sublt100; + } + if (u < 1000000) { // 1,000,000 + if (u >= 100000) goto lt1_000_000; + digits = u / 10000; // 10,000 + *buffer++ = '0' + digits; + goto sublt10_000; + } + if (u < 100000000) { // 100,000,000 + if (u >= 10000000) goto lt100_000_000; + digits = u / 1000000; // 1,000,000 + *buffer++ = '0' + digits; + goto sublt1_000_000; + } + // we already know that u < 1,000,000,000 + digits = u / 100000000; // 100,000,000 + *buffer++ = '0' + digits; + goto sublt100_000_000; +} + +char* FastInt32ToBufferLeft(int32 i, char* buffer) { + uint32 u = i; + if (i < 0) { + *buffer++ = '-'; + u = -i; + } + return FastUInt32ToBufferLeft(u, buffer); +} + +char* FastUInt64ToBufferLeft(uint64 u64, char* buffer) { + int digits; + const char *ASCII_digits = NULL; + + uint32 u = static_cast(u64); + if (u == u64) return FastUInt32ToBufferLeft(u, buffer); + + uint64 top_11_digits = u64 / 1000000000; + buffer = FastUInt64ToBufferLeft(top_11_digits, buffer); + u = u64 - (top_11_digits * 1000000000); + + digits = u / 10000000; // 10,000,000 + GOOGLE_DCHECK_LT(digits, 100); + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; + u -= digits * 10000000; // 10,000,000 + digits = u / 100000; // 100,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; + u -= digits * 100000; // 100,000 + digits = u / 1000; // 1,000 + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; + u -= digits * 1000; // 1,000 + digits = u / 10; + ASCII_digits = two_ASCII_digits[digits]; + buffer[0] = ASCII_digits[0]; + buffer[1] = ASCII_digits[1]; + buffer += 2; + u -= digits * 10; + digits = u; + *buffer++ = '0' + digits; + *buffer = 0; + return buffer; +} + +char* FastInt64ToBufferLeft(int64 i, char* buffer) { + uint64 u = i; + if (i < 0) { + *buffer++ = '-'; + u = -i; + } + return FastUInt64ToBufferLeft(u, buffer); +} + +// ---------------------------------------------------------------------- +// SimpleItoa() +// Description: converts an integer to a string. +// +// Return value: string +// ---------------------------------------------------------------------- + +string SimpleItoa(int i) { + char buffer[kFastToBufferSize]; + return (sizeof(i) == 4) ? + FastInt32ToBuffer(i, buffer) : + FastInt64ToBuffer(i, buffer); +} + +string SimpleItoa(unsigned int i) { + char buffer[kFastToBufferSize]; + return string(buffer, (sizeof(i) == 4) ? + FastUInt32ToBufferLeft(i, buffer) : + FastUInt64ToBufferLeft(i, buffer)); +} + +string SimpleItoa(long i) { + char buffer[kFastToBufferSize]; + return (sizeof(i) == 4) ? + FastInt32ToBuffer(i, buffer) : + FastInt64ToBuffer(i, buffer); +} + +string SimpleItoa(unsigned long i) { + char buffer[kFastToBufferSize]; + return string(buffer, (sizeof(i) == 4) ? + FastUInt32ToBufferLeft(i, buffer) : + FastUInt64ToBufferLeft(i, buffer)); +} + +string SimpleItoa(long long i) { + char buffer[kFastToBufferSize]; + return (sizeof(i) == 4) ? + FastInt32ToBuffer(i, buffer) : + FastInt64ToBuffer(i, buffer); +} + +string SimpleItoa(unsigned long long i) { + char buffer[kFastToBufferSize]; + return string(buffer, (sizeof(i) == 4) ? + FastUInt32ToBufferLeft(i, buffer) : + FastUInt64ToBufferLeft(i, buffer)); +} + +// ---------------------------------------------------------------------- +// SimpleDtoa() +// SimpleFtoa() +// DoubleToBuffer() +// FloatToBuffer() +// We want to print the value without losing precision, but we also do +// not want to print more digits than necessary. This turns out to be +// trickier than it sounds. Numbers like 0.2 cannot be represented +// exactly in binary. If we print 0.2 with a very large precision, +// e.g. "%.50g", we get "0.2000000000000000111022302462515654042363167". +// On the other hand, if we set the precision too low, we lose +// significant digits when printing numbers that actually need them. +// It turns out there is no precision value that does the right thing +// for all numbers. +// +// Our strategy is to first try printing with a precision that is never +// over-precise, then parse the result with strtod() to see if it +// matches. If not, we print again with a precision that will always +// give a precise result, but may use more digits than necessary. +// +// An arguably better strategy would be to use the algorithm described +// in "How to Print Floating-Point Numbers Accurately" by Steele & +// White, e.g. as implemented by David M. Gay's dtoa(). It turns out, +// however, that the following implementation is about as fast as +// DMG's code. Furthermore, DMG's code locks mutexes, which means it +// will not scale well on multi-core machines. DMG's code is slightly +// more accurate (in that it will never use more digits than +// necessary), but this is probably irrelevant for most users. +// +// Rob Pike and Ken Thompson also have an implementation of dtoa() in +// third_party/fmt/fltfmt.cc. Their implementation is similar to this +// one in that it makes guesses and then uses strtod() to check them. +// Their implementation is faster because they use their own code to +// generate the digits in the first place rather than use snprintf(), +// thus avoiding format string parsing overhead. However, this makes +// it considerably more complicated than the following implementation, +// and it is embedded in a larger library. If speed turns out to be +// an issue, we could re-implement this in terms of their +// implementation. +// ---------------------------------------------------------------------- + +string SimpleDtoa(double value) { + char buffer[kDoubleToBufferSize]; + return DoubleToBuffer(value, buffer); +} + +string SimpleFtoa(float value) { + char buffer[kFloatToBufferSize]; + return FloatToBuffer(value, buffer); +} + +static inline bool IsValidFloatChar(char c) { + return ('0' <= c && c <= '9') || + c == 'e' || c == 'E' || + c == '+' || c == '-'; +} + +void DelocalizeRadix(char* buffer) { + // Fast check: if the buffer has a normal decimal point, assume no + // translation is needed. + if (strchr(buffer, '.') != NULL) return; + + // Find the first unknown character. + while (IsValidFloatChar(*buffer)) ++buffer; + + if (*buffer == '\0') { + // No radix character found. + return; + } + + // We are now pointing at the locale-specific radix character. Replace it + // with '.'. + *buffer = '.'; + ++buffer; + + if (!IsValidFloatChar(*buffer) && *buffer != '\0') { + // It appears the radix was a multi-byte character. We need to remove the + // extra bytes. + char* target = buffer; + do { ++buffer; } while (!IsValidFloatChar(*buffer) && *buffer != '\0'); + memmove(target, buffer, strlen(buffer) + 1); + } +} + +char* DoubleToBuffer(double value, char* buffer) { + // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all + // platforms these days. Just in case some system exists where DBL_DIG + // is significantly larger -- and risks overflowing our buffer -- we have + // this assert. + GOOGLE_COMPILE_ASSERT(DBL_DIG < 20, DBL_DIG_is_too_big); + + if (value == std::numeric_limits::infinity()) { + strcpy(buffer, "inf"); + return buffer; + } else if (value == -std::numeric_limits::infinity()) { + strcpy(buffer, "-inf"); + return buffer; + } else if (MathLimits::IsNaN(value)) { + strcpy(buffer, "nan"); + return buffer; + } + + int snprintf_result = + snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG, value); + + // The snprintf should never overflow because the buffer is significantly + // larger than the precision we asked for. + GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize); + + // We need to make parsed_value volatile in order to force the compiler to + // write it out to the stack. Otherwise, it may keep the value in a + // register, and if it does that, it may keep it as a long double instead + // of a double. This long double may have extra bits that make it compare + // unequal to "value" even though it would be exactly equal if it were + // truncated to a double. + volatile double parsed_value = strtod(buffer, NULL); + if (parsed_value != value) { + int snprintf_result = + snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG+2, value); + + // Should never overflow; see above. + GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize); + } + + DelocalizeRadix(buffer); + return buffer; +} + +static int memcasecmp(const char *s1, const char *s2, size_t len) { + const unsigned char *us1 = reinterpret_cast(s1); + const unsigned char *us2 = reinterpret_cast(s2); + + for ( int i = 0; i < len; i++ ) { + const int diff = + static_cast(static_cast(ascii_tolower(us1[i]))) - + static_cast(static_cast(ascii_tolower(us2[i]))); + if (diff != 0) return diff; + } + return 0; +} + +inline bool CaseEqual(StringPiece s1, StringPiece s2) { + if (s1.size() != s2.size()) return false; + return memcasecmp(s1.data(), s2.data(), s1.size()) == 0; +} + +bool safe_strtob(StringPiece str, bool* value) { + GOOGLE_CHECK(value != NULL) << "NULL output boolean given."; + if (CaseEqual(str, "true") || CaseEqual(str, "t") || + CaseEqual(str, "yes") || CaseEqual(str, "y") || + CaseEqual(str, "1")) { + *value = true; + return true; + } + if (CaseEqual(str, "false") || CaseEqual(str, "f") || + CaseEqual(str, "no") || CaseEqual(str, "n") || + CaseEqual(str, "0")) { + *value = false; + return true; + } + return false; +} + +bool safe_strtof(const char* str, float* value) { + char* endptr; + errno = 0; // errno only gets set on errors +#if defined(_WIN32) || defined (__hpux) // has no strtof() + *value = strtod(str, &endptr); +#else + *value = strtof(str, &endptr); +#endif + return *str != 0 && *endptr == 0 && errno == 0; +} + +bool safe_strtod(const char* str, double* value) { + char* endptr; + *value = strtod(str, &endptr); + if (endptr != str) { + while (ascii_isspace(*endptr)) ++endptr; + } + // Ignore range errors from strtod. The values it + // returns on underflow and overflow are the right + // fallback in a robust setting. + return *str != '\0' && *endptr == '\0'; +} + +bool safe_strto32(const string& str, int32* value) { + return safe_int_internal(str, value); +} + +bool safe_strtou32(const string& str, uint32* value) { + return safe_uint_internal(str, value); +} + +bool safe_strto64(const string& str, int64* value) { + return safe_int_internal(str, value); +} + +bool safe_strtou64(const string& str, uint64* value) { + return safe_uint_internal(str, value); +} + +char* FloatToBuffer(float value, char* buffer) { + // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all + // platforms these days. Just in case some system exists where FLT_DIG + // is significantly larger -- and risks overflowing our buffer -- we have + // this assert. + GOOGLE_COMPILE_ASSERT(FLT_DIG < 10, FLT_DIG_is_too_big); + + if (value == std::numeric_limits::infinity()) { + strcpy(buffer, "inf"); + return buffer; + } else if (value == -std::numeric_limits::infinity()) { + strcpy(buffer, "-inf"); + return buffer; + } else if (MathLimits::IsNaN(value)) { + strcpy(buffer, "nan"); + return buffer; + } + + int snprintf_result = + snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG, value); + + // The snprintf should never overflow because the buffer is significantly + // larger than the precision we asked for. + GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize); + + float parsed_value; + if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) { + int snprintf_result = + snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG+3, value); + + // Should never overflow; see above. + GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize); + } + + DelocalizeRadix(buffer); + return buffer; +} + +namespace strings { + +AlphaNum::AlphaNum(strings::Hex hex) { + char *const end = &digits[kFastToBufferSize]; + char *writer = end; + uint64 value = hex.value; + uint64 width = hex.spec; + // We accomplish minimum width by OR'ing in 0x10000 to the user's value, + // where 0x10000 is the smallest hex number that is as wide as the user + // asked for. + uint64 mask = ((static_cast(1) << (width - 1) * 4)) | value; + static const char hexdigits[] = "0123456789abcdef"; + do { + *--writer = hexdigits[value & 0xF]; + value >>= 4; + mask >>= 4; + } while (mask != 0); + piece_data_ = writer; + piece_size_ = end - writer; +} + +} // namespace strings + +// ---------------------------------------------------------------------- +// StrCat() +// This merges the given strings or integers, with no delimiter. This +// is designed to be the fastest possible way to construct a string out +// of a mix of raw C strings, C++ strings, and integer values. +// ---------------------------------------------------------------------- + +// Append is merely a version of memcpy that returns the address of the byte +// after the area just overwritten. It comes in multiple flavors to minimize +// call overhead. +static char *Append1(char *out, const AlphaNum &x) { + memcpy(out, x.data(), x.size()); + return out + x.size(); +} + +static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + + memcpy(out, x2.data(), x2.size()); + return out + x2.size(); +} + +static char *Append4(char *out, + const AlphaNum &x1, const AlphaNum &x2, + const AlphaNum &x3, const AlphaNum &x4) { + memcpy(out, x1.data(), x1.size()); + out += x1.size(); + + memcpy(out, x2.data(), x2.size()); + out += x2.size(); + + memcpy(out, x3.data(), x3.size()); + out += x3.size(); + + memcpy(out, x4.data(), x4.size()); + return out + x4.size(); +} + +string StrCat(const AlphaNum &a, const AlphaNum &b) { + string result; + result.resize(a.size() + b.size()); + char *const begin = &*result.begin(); + char *out = Append2(begin, a, b); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { + string result; + result.resize(a.size() + b.size() + c.size()); + char *const begin = &*result.begin(); + char *out = Append2(begin, a, b); + out = Append1(out, c); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append1(out, e); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append2(out, e, f); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append2(out, e, f); + out = Append1(out, g); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size() + h.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append4(out, e, f, g, h); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +string StrCat(const AlphaNum &a, const AlphaNum &b, const AlphaNum &c, + const AlphaNum &d, const AlphaNum &e, const AlphaNum &f, + const AlphaNum &g, const AlphaNum &h, const AlphaNum &i) { + string result; + result.resize(a.size() + b.size() + c.size() + d.size() + e.size() + + f.size() + g.size() + h.size() + i.size()); + char *const begin = &*result.begin(); + char *out = Append4(begin, a, b, c, d); + out = Append4(out, e, f, g, h); + out = Append1(out, i); + GOOGLE_DCHECK_EQ(out, begin + result.size()); + return result; +} + +// It's possible to call StrAppend with a char * pointer that is partway into +// the string we're appending to. However the results of this are random. +// Therefore, check for this in debug mode. Use unsigned math so we only have +// to do one comparison. +#define GOOGLE_DCHECK_NO_OVERLAP(dest, src) \ + GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \ + uintptr_t((dest).size())) + +void StrAppend(string *result, const AlphaNum &a) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + result->append(a.data(), a.size()); +} + +void StrAppend(string *result, const AlphaNum &a, const AlphaNum &b) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size()); + char *const begin = &*result->begin(); + char *out = Append2(begin + old_size, a, b); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +void StrAppend(string *result, + const AlphaNum &a, const AlphaNum &b, const AlphaNum &c) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + GOOGLE_DCHECK_NO_OVERLAP(*result, c); + string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size() + c.size()); + char *const begin = &*result->begin(); + char *out = Append2(begin + old_size, a, b); + out = Append1(out, c); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +void StrAppend(string *result, + const AlphaNum &a, const AlphaNum &b, + const AlphaNum &c, const AlphaNum &d) { + GOOGLE_DCHECK_NO_OVERLAP(*result, a); + GOOGLE_DCHECK_NO_OVERLAP(*result, b); + GOOGLE_DCHECK_NO_OVERLAP(*result, c); + GOOGLE_DCHECK_NO_OVERLAP(*result, d); + string::size_type old_size = result->size(); + result->resize(old_size + a.size() + b.size() + c.size() + d.size()); + char *const begin = &*result->begin(); + char *out = Append4(begin + old_size, a, b, c, d); + GOOGLE_DCHECK_EQ(out, begin + result->size()); +} + +int GlobalReplaceSubstring(const string& substring, + const string& replacement, + string* s) { + GOOGLE_CHECK(s != NULL); + if (s->empty() || substring.empty()) + return 0; + string tmp; + int num_replacements = 0; + int pos = 0; + for (int match_pos = s->find(substring.data(), pos, substring.length()); + match_pos != string::npos; + pos = match_pos + substring.length(), + match_pos = s->find(substring.data(), pos, substring.length())) { + ++num_replacements; + // Append the original content before the match. + tmp.append(*s, pos, match_pos - pos); + // Append the replacement for the match. + tmp.append(replacement.begin(), replacement.end()); + } + // Append the content after the last match. If no replacements were made, the + // original string is left untouched. + if (num_replacements > 0) { + tmp.append(*s, pos, s->length() - pos); + s->swap(tmp); + } + return num_replacements; +} + +int CalculateBase64EscapedLen(int input_len, bool do_padding) { + // Base64 encodes three bytes of input at a time. If the input is not + // divisible by three, we pad as appropriate. + // + // (from http://tools.ietf.org/html/rfc3548) + // Special processing is performed if fewer than 24 bits are available + // at the end of the data being encoded. A full encoding quantum is + // always completed at the end of a quantity. When fewer than 24 input + // bits are available in an input group, zero bits are added (on the + // right) to form an integral number of 6-bit groups. Padding at the + // end of the data is performed using the '=' character. Since all base + // 64 input is an integral number of octets, only the following cases + // can arise: + + + // Base64 encodes each three bytes of input into four bytes of output. + int len = (input_len / 3) * 4; + + if (input_len % 3 == 0) { + // (from http://tools.ietf.org/html/rfc3548) + // (1) the final quantum of encoding input is an integral multiple of 24 + // bits; here, the final unit of encoded output will be an integral + // multiple of 4 characters with no "=" padding, + } else if (input_len % 3 == 1) { + // (from http://tools.ietf.org/html/rfc3548) + // (2) the final quantum of encoding input is exactly 8 bits; here, the + // final unit of encoded output will be two characters followed by two + // "=" padding characters, or + len += 2; + if (do_padding) { + len += 2; + } + } else { // (input_len % 3 == 2) + // (from http://tools.ietf.org/html/rfc3548) + // (3) the final quantum of encoding input is exactly 16 bits; here, the + // final unit of encoded output will be three characters followed by one + // "=" padding character. + len += 3; + if (do_padding) { + len += 1; + } + } + + assert(len >= input_len); // make sure we didn't overflow + return len; +} + +// Base64Escape does padding, so this calculation includes padding. +int CalculateBase64EscapedLen(int input_len) { + return CalculateBase64EscapedLen(input_len, true); +} + +// ---------------------------------------------------------------------- +// int Base64Unescape() - base64 decoder +// int Base64Escape() - base64 encoder +// int WebSafeBase64Unescape() - Google's variation of base64 decoder +// int WebSafeBase64Escape() - Google's variation of base64 encoder +// +// Check out +// http://tools.ietf.org/html/rfc2045 for formal description, but what we +// care about is that... +// Take the encoded stuff in groups of 4 characters and turn each +// character into a code 0 to 63 thus: +// A-Z map to 0 to 25 +// a-z map to 26 to 51 +// 0-9 map to 52 to 61 +// +(- for WebSafe) maps to 62 +// /(_ for WebSafe) maps to 63 +// There will be four numbers, all less than 64 which can be represented +// by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively). +// Arrange the 6 digit binary numbers into three bytes as such: +// aaaaaabb bbbbcccc ccdddddd +// Equals signs (one or two) are used at the end of the encoded block to +// indicate that the text was not an integer multiple of three bytes long. +// ---------------------------------------------------------------------- + +int Base64UnescapeInternal(const char *src_param, int szsrc, + char *dest, int szdest, + const signed char* unbase64) { + static const char kPad64Equals = '='; + static const char kPad64Dot = '.'; + + int decode = 0; + int destidx = 0; + int state = 0; + unsigned int ch = 0; + unsigned int temp = 0; + + // If "char" is signed by default, using *src as an array index results in + // accessing negative array elements. Treat the input as a pointer to + // unsigned char to avoid this. + const unsigned char *src = reinterpret_cast(src_param); + + // The GET_INPUT macro gets the next input character, skipping + // over any whitespace, and stopping when we reach the end of the + // string or when we read any non-data character. The arguments are + // an arbitrary identifier (used as a label for goto) and the number + // of data bytes that must remain in the input to avoid aborting the + // loop. +#define GET_INPUT(label, remain) \ + label: \ + --szsrc; \ + ch = *src++; \ + decode = unbase64[ch]; \ + if (decode < 0) { \ + if (ascii_isspace(ch) && szsrc >= remain) \ + goto label; \ + state = 4 - remain; \ + break; \ + } + + // if dest is null, we're just checking to see if it's legal input + // rather than producing output. (I suspect this could just be done + // with a regexp...). We duplicate the loop so this test can be + // outside it instead of in every iteration. + + if (dest) { + // This loop consumes 4 input bytes and produces 3 output bytes + // per iteration. We can't know at the start that there is enough + // data left in the string for a full iteration, so the loop may + // break out in the middle; if so 'state' will be set to the + // number of input bytes read. + + while (szsrc >= 4) { + // We'll start by optimistically assuming that the next four + // bytes of the string (src[0..3]) are four good data bytes + // (that is, no nulls, whitespace, padding chars, or illegal + // chars). We need to test src[0..2] for nulls individually + // before constructing temp to preserve the property that we + // never read past a null in the string (no matter how long + // szsrc claims the string is). + + if (!src[0] || !src[1] || !src[2] || + (temp = ((unsigned(unbase64[src[0]]) << 18) | + (unsigned(unbase64[src[1]]) << 12) | + (unsigned(unbase64[src[2]]) << 6) | + (unsigned(unbase64[src[3]])))) & 0x80000000) { + // Iff any of those four characters was bad (null, illegal, + // whitespace, padding), then temp's high bit will be set + // (because unbase64[] is -1 for all bad characters). + // + // We'll back up and resort to the slower decoder, which knows + // how to handle those cases. + + GET_INPUT(first, 4); + temp = decode; + GET_INPUT(second, 3); + temp = (temp << 6) | decode; + GET_INPUT(third, 2); + temp = (temp << 6) | decode; + GET_INPUT(fourth, 1); + temp = (temp << 6) | decode; + } else { + // We really did have four good data bytes, so advance four + // characters in the string. + + szsrc -= 4; + src += 4; + decode = -1; + ch = '\0'; + } + + // temp has 24 bits of input, so write that out as three bytes. + + if (destidx+3 > szdest) return -1; + dest[destidx+2] = temp; + temp >>= 8; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + destidx += 3; + } + } else { + while (szsrc >= 4) { + if (!src[0] || !src[1] || !src[2] || + (temp = ((unsigned(unbase64[src[0]]) << 18) | + (unsigned(unbase64[src[1]]) << 12) | + (unsigned(unbase64[src[2]]) << 6) | + (unsigned(unbase64[src[3]])))) & 0x80000000) { + GET_INPUT(first_no_dest, 4); + GET_INPUT(second_no_dest, 3); + GET_INPUT(third_no_dest, 2); + GET_INPUT(fourth_no_dest, 1); + } else { + szsrc -= 4; + src += 4; + decode = -1; + ch = '\0'; + } + destidx += 3; + } + } + +#undef GET_INPUT + + // if the loop terminated because we read a bad character, return + // now. + if (decode < 0 && ch != '\0' && + ch != kPad64Equals && ch != kPad64Dot && !ascii_isspace(ch)) + return -1; + + if (ch == kPad64Equals || ch == kPad64Dot) { + // if we stopped by hitting an '=' or '.', un-read that character -- we'll + // look at it again when we count to check for the proper number of + // equals signs at the end. + ++szsrc; + --src; + } else { + // This loop consumes 1 input byte per iteration. It's used to + // clean up the 0-3 input bytes remaining when the first, faster + // loop finishes. 'temp' contains the data from 'state' input + // characters read by the first loop. + while (szsrc > 0) { + --szsrc; + ch = *src++; + decode = unbase64[ch]; + if (decode < 0) { + if (ascii_isspace(ch)) { + continue; + } else if (ch == '\0') { + break; + } else if (ch == kPad64Equals || ch == kPad64Dot) { + // back up one character; we'll read it again when we check + // for the correct number of pad characters at the end. + ++szsrc; + --src; + break; + } else { + return -1; + } + } + + // Each input character gives us six bits of output. + temp = (temp << 6) | decode; + ++state; + if (state == 4) { + // If we've accumulated 24 bits of output, write that out as + // three bytes. + if (dest) { + if (destidx+3 > szdest) return -1; + dest[destidx+2] = temp; + temp >>= 8; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + } + destidx += 3; + state = 0; + temp = 0; + } + } + } + + // Process the leftover data contained in 'temp' at the end of the input. + int expected_equals = 0; + switch (state) { + case 0: + // Nothing left over; output is a multiple of 3 bytes. + break; + + case 1: + // Bad input; we have 6 bits left over. + return -1; + + case 2: + // Produce one more output byte from the 12 input bits we have left. + if (dest) { + if (destidx+1 > szdest) return -1; + temp >>= 4; + dest[destidx] = temp; + } + ++destidx; + expected_equals = 2; + break; + + case 3: + // Produce two more output bytes from the 18 input bits we have left. + if (dest) { + if (destidx+2 > szdest) return -1; + temp >>= 2; + dest[destidx+1] = temp; + temp >>= 8; + dest[destidx] = temp; + } + destidx += 2; + expected_equals = 1; + break; + + default: + // state should have no other values at this point. + GOOGLE_LOG(FATAL) << "This can't happen; base64 decoder state = " << state; + } + + // The remainder of the string should be all whitespace, mixed with + // exactly 0 equals signs, or exactly 'expected_equals' equals + // signs. (Always accepting 0 equals signs is a google extension + // not covered in the RFC, as is accepting dot as the pad character.) + + int equals = 0; + while (szsrc > 0 && *src) { + if (*src == kPad64Equals || *src == kPad64Dot) + ++equals; + else if (!ascii_isspace(*src)) + return -1; + --szsrc; + ++src; + } + + return (equals == 0 || equals == expected_equals) ? destidx : -1; +} + +// The arrays below were generated by the following code +// #include +// #include +// #include +// main() +// { +// static const char Base64[] = +// "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +// char *pos; +// int idx, i, j; +// printf(" "); +// for (i = 0; i < 255; i += 8) { +// for (j = i; j < i + 8; j++) { +// pos = strchr(Base64, j); +// if ((pos == NULL) || (j == 0)) +// idx = -1; +// else +// idx = pos - Base64; +// if (idx == -1) +// printf(" %2d, ", idx); +// else +// printf(" %2d/*%c*/,", idx, j); +// } +// printf("\n "); +// } +// } +// +// where the value of "Base64[]" was replaced by one of the base-64 conversion +// tables from the functions below. +static const signed char kUnBase64[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 62/*+*/, -1, -1, -1, 63/*/ */, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, + -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, -1, + -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; +static const signed char kUnWebSafeBase64[] = { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 62/*-*/, -1, -1, + 52/*0*/, 53/*1*/, 54/*2*/, 55/*3*/, 56/*4*/, 57/*5*/, 58/*6*/, 59/*7*/, + 60/*8*/, 61/*9*/, -1, -1, -1, -1, -1, -1, + -1, 0/*A*/, 1/*B*/, 2/*C*/, 3/*D*/, 4/*E*/, 5/*F*/, 6/*G*/, + 07/*H*/, 8/*I*/, 9/*J*/, 10/*K*/, 11/*L*/, 12/*M*/, 13/*N*/, 14/*O*/, + 15/*P*/, 16/*Q*/, 17/*R*/, 18/*S*/, 19/*T*/, 20/*U*/, 21/*V*/, 22/*W*/, + 23/*X*/, 24/*Y*/, 25/*Z*/, -1, -1, -1, -1, 63/*_*/, + -1, 26/*a*/, 27/*b*/, 28/*c*/, 29/*d*/, 30/*e*/, 31/*f*/, 32/*g*/, + 33/*h*/, 34/*i*/, 35/*j*/, 36/*k*/, 37/*l*/, 38/*m*/, 39/*n*/, 40/*o*/, + 41/*p*/, 42/*q*/, 43/*r*/, 44/*s*/, 45/*t*/, 46/*u*/, 47/*v*/, 48/*w*/, + 49/*x*/, 50/*y*/, 51/*z*/, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1 +}; + +int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) { + return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64); +} + +static bool Base64UnescapeInternal(const char* src, int slen, string* dest, + const signed char* unbase64) { + // Determine the size of the output string. Base64 encodes every 3 bytes into + // 4 characters. any leftover chars are added directly for good measure. + // This is documented in the base64 RFC: http://tools.ietf.org/html/rfc3548 + const int dest_len = 3 * (slen / 4) + (slen % 4); + + dest->resize(dest_len); + + // We are getting the destination buffer by getting the beginning of the + // string and converting it into a char *. + const int len = Base64UnescapeInternal(src, slen, string_as_array(dest), + dest_len, unbase64); + if (len < 0) { + dest->clear(); + return false; + } + + // could be shorter if there was padding + GOOGLE_DCHECK_LE(len, dest_len); + dest->erase(len); + + return true; +} + +bool Base64Unescape(StringPiece src, string* dest) { + return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64); +} + +bool WebSafeBase64Unescape(StringPiece src, string* dest) { + return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64); +} + +int Base64EscapeInternal(const unsigned char *src, int szsrc, + char *dest, int szdest, const char *base64, + bool do_padding) { + static const char kPad64 = '='; + + if (szsrc <= 0) return 0; + + if (szsrc * 4 > szdest * 3) return 0; + + char *cur_dest = dest; + const unsigned char *cur_src = src; + + char *limit_dest = dest + szdest; + const unsigned char *limit_src = src + szsrc; + + // Three bytes of data encodes to four characters of cyphertext. + // So we can pump through three-byte chunks atomically. + while (cur_src < limit_src - 3) { // keep going as long as we have >= 32 bits + uint32 in = BigEndian::Load32(cur_src) >> 8; + + cur_dest[0] = base64[in >> 18]; + in &= 0x3FFFF; + cur_dest[1] = base64[in >> 12]; + in &= 0xFFF; + cur_dest[2] = base64[in >> 6]; + in &= 0x3F; + cur_dest[3] = base64[in]; + + cur_dest += 4; + cur_src += 3; + } + // To save time, we didn't update szdest or szsrc in the loop. So do it now. + szdest = limit_dest - cur_dest; + szsrc = limit_src - cur_src; + + /* now deal with the tail (<=3 bytes) */ + switch (szsrc) { + case 0: + // Nothing left; nothing more to do. + break; + case 1: { + // One byte left: this encodes to two characters, and (optionally) + // two pad characters to round out the four-character cypherblock. + if ((szdest -= 2) < 0) return 0; + uint32 in = cur_src[0]; + cur_dest[0] = base64[in >> 2]; + in &= 0x3; + cur_dest[1] = base64[in << 4]; + cur_dest += 2; + if (do_padding) { + if ((szdest -= 2) < 0) return 0; + cur_dest[0] = kPad64; + cur_dest[1] = kPad64; + cur_dest += 2; + } + break; + } + case 2: { + // Two bytes left: this encodes to three characters, and (optionally) + // one pad character to round out the four-character cypherblock. + if ((szdest -= 3) < 0) return 0; + uint32 in = BigEndian::Load16(cur_src); + cur_dest[0] = base64[in >> 10]; + in &= 0x3FF; + cur_dest[1] = base64[in >> 4]; + in &= 0x00F; + cur_dest[2] = base64[in << 2]; + cur_dest += 3; + if (do_padding) { + if ((szdest -= 1) < 0) return 0; + cur_dest[0] = kPad64; + cur_dest += 1; + } + break; + } + case 3: { + // Three bytes left: same as in the big loop above. We can't do this in + // the loop because the loop above always reads 4 bytes, and the fourth + // byte is past the end of the input. + if ((szdest -= 4) < 0) return 0; + uint32 in = (cur_src[0] << 16) + BigEndian::Load16(cur_src + 1); + cur_dest[0] = base64[in >> 18]; + in &= 0x3FFFF; + cur_dest[1] = base64[in >> 12]; + in &= 0xFFF; + cur_dest[2] = base64[in >> 6]; + in &= 0x3F; + cur_dest[3] = base64[in]; + cur_dest += 4; + break; + } + default: + // Should not be reached: blocks of 4 bytes are handled + // in the while loop before this switch statement. + GOOGLE_LOG(FATAL) << "Logic problem? szsrc = " << szsrc; + break; + } + return (cur_dest - dest); +} + +static const char kBase64Chars[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static const char kWebSafeBase64Chars[] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + +int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) { + return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true); +} +int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest, + int szdest, bool do_padding) { + return Base64EscapeInternal(src, szsrc, dest, szdest, + kWebSafeBase64Chars, do_padding); +} + +void Base64EscapeInternal(const unsigned char* src, int szsrc, + string* dest, bool do_padding, + const char* base64_chars) { + const int calc_escaped_size = + CalculateBase64EscapedLen(szsrc, do_padding); + dest->resize(calc_escaped_size); + const int escaped_len = Base64EscapeInternal(src, szsrc, + string_as_array(dest), + dest->size(), + base64_chars, + do_padding); + GOOGLE_DCHECK_EQ(calc_escaped_size, escaped_len); + dest->erase(escaped_len); +} + +void Base64Escape(const unsigned char *src, int szsrc, + string* dest, bool do_padding) { + Base64EscapeInternal(src, szsrc, dest, do_padding, kBase64Chars); +} + +void WebSafeBase64Escape(const unsigned char *src, int szsrc, + string *dest, bool do_padding) { + Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars); +} + +void Base64Escape(StringPiece src, string* dest) { + Base64Escape(reinterpret_cast(src.data()), + src.size(), dest, true); +} + +void WebSafeBase64Escape(StringPiece src, string* dest) { + WebSafeBase64Escape(reinterpret_cast(src.data()), + src.size(), dest, false); +} + +void WebSafeBase64EscapeWithPadding(StringPiece src, string* dest) { + WebSafeBase64Escape(reinterpret_cast(src.data()), + src.size(), dest, true); +} + +// Helper to append a Unicode code point to a string as UTF8, without bringing +// in any external dependencies. +int EncodeAsUTF8Char(uint32 code_point, char* output) { + uint32 tmp = 0; + int len = 0; + if (code_point <= 0x7f) { + tmp = code_point; + len = 1; + } else if (code_point <= 0x07ff) { + tmp = 0x0000c080 | + ((code_point & 0x07c0) << 2) | + (code_point & 0x003f); + len = 2; + } else if (code_point <= 0xffff) { + tmp = 0x00e08080 | + ((code_point & 0xf000) << 4) | + ((code_point & 0x0fc0) << 2) | + (code_point & 0x003f); + len = 3; + } else { + // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is + // normally only defined up to there as well. + tmp = 0xf0808080 | + ((code_point & 0x1c0000) << 6) | + ((code_point & 0x03f000) << 4) | + ((code_point & 0x000fc0) << 2) | + (code_point & 0x003f); + len = 4; + } + tmp = ghtonl(tmp); + memcpy(output, reinterpret_cast(&tmp) + sizeof(tmp) - len, len); + return len; +} + +// Table of UTF-8 character lengths, based on first byte +static const unsigned char kUTF8LenTbl[256] = { + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1, + 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2, + 3,3,3,3,3,3,3,3, 3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4, 4,4,4,4,4,4,4,4 +}; + +// Return length of a single UTF-8 source character +int UTF8FirstLetterNumBytes(const char* src, int len) { + if (len == 0) { + return 0; + } + return kUTF8LenTbl[*reinterpret_cast(src)]; +} + +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/strutil.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/strutil.h similarity index 57% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/strutil.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/strutil.h index 4178ac9ff..a839b8b3e 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/strutil.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/strutil.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace google { namespace protobuf { @@ -57,6 +58,8 @@ namespace protobuf { // strings, so locale should not be taken into account. // ascii_isdigit() // Like above, but only accepts digits. +// ascii_isspace() +// Check if the character is a space character. // ---------------------------------------------------------------------- inline bool ascii_isalnum(char c) { @@ -69,6 +72,36 @@ inline bool ascii_isdigit(char c) { return ('0' <= c && c <= '9'); } +inline bool ascii_isspace(char c) { + return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || + c == '\r'; +} + +inline bool ascii_isupper(char c) { + return c >= 'A' && c <= 'Z'; +} + +inline bool ascii_islower(char c) { + return c >= 'a' && c <= 'z'; +} + +inline char ascii_toupper(char c) { + return ascii_islower(c) ? c - ('a' - 'A') : c; +} + +inline char ascii_tolower(char c) { + return ascii_isupper(c) ? c + ('a' - 'A') : c; +} + +inline int hex_digit_to_int(char c) { + /* Assume ASCII. */ + int x = static_cast(c); + if (x > '9') { + x += 9; + } + return x & 0xf; +} + // ---------------------------------------------------------------------- // HasPrefixString() // Check if a string begins with a given prefix. @@ -114,15 +147,22 @@ inline string StripSuffixString(const string& str, const string& suffix) { } // ---------------------------------------------------------------------- -// StripString +// ReplaceCharacters // Replaces any occurrence of the character 'remove' (or the characters // in 'remove') with the character 'replacewith'. // Good for keeping html characters or protocol characters (\t) out // of places where they might cause a problem. +// StripWhitespace +// Removes whitespaces from both ends of the given string. // ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT void ReplaceCharacters(string* s, const char* remove, + char replacewith); LIBPROTOBUF_EXPORT void StripString(string* s, const char* remove, char replacewith); +LIBPROTOBUF_EXPORT void StripWhitespace(string* s); + + // ---------------------------------------------------------------------- // LowerString() // UpperString() @@ -173,7 +213,7 @@ LIBPROTOBUF_EXPORT string StringReplace(const string& s, const string& oldsub, // over all of them. // ---------------------------------------------------------------------- LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim, - vector* res); + std::vector* res); // Split a string using one or more byte delimiters, presented // as a nul-terminated c string. Append the components to 'result'. @@ -185,15 +225,15 @@ LIBPROTOBUF_EXPORT void SplitStringUsing(const string& full, const char* delim, // ---------------------------------------------------------------------- LIBPROTOBUF_EXPORT void SplitStringAllowEmpty(const string& full, const char* delim, - vector* result); + std::vector* result); // ---------------------------------------------------------------------- // Split() // Split a string using a character delimiter. // ---------------------------------------------------------------------- -inline vector Split( +inline std::vector Split( const string& full, const char* delim, bool skip_empty = true) { - vector result; + std::vector result; if (skip_empty) { SplitStringUsing(full, delim, &result); } else { @@ -210,10 +250,10 @@ inline vector Split( // another takes a pointer to the target string. In the latter case the // target string is cleared and overwritten. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT void JoinStrings(const vector& components, +LIBPROTOBUF_EXPORT void JoinStrings(const std::vector& components, const char* delim, string* result); -inline string JoinStrings(const vector& components, +inline string JoinStrings(const std::vector& components, const char* delim) { string result; JoinStrings(components, delim, &result); @@ -245,15 +285,15 @@ inline string JoinStrings(const vector& components, // // Errors: In the first form of the call, errors are reported with // LOG(ERROR). The same is true for the second form of the call if -// the pointer to the string vector is NULL; otherwise, error -// messages are stored in the vector. In either case, the effect on +// the pointer to the string std::vector is NULL; otherwise, error +// messages are stored in the std::vector. In either case, the effect on // the dest array is not defined, but rest of the source will be // processed. // ---------------------------------------------------------------------- LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest); LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest, - vector *errors); + std::vector *errors); // ---------------------------------------------------------------------- // UnescapeCEscapeString() @@ -272,30 +312,24 @@ LIBPROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest, LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest); LIBPROTOBUF_EXPORT int UnescapeCEscapeString(const string& src, string* dest, - vector *errors); + std::vector *errors); LIBPROTOBUF_EXPORT string UnescapeCEscapeString(const string& src); // ---------------------------------------------------------------------- -// CEscapeString() -// Copies 'src' to 'dest', escaping dangerous characters using -// C-style escape sequences. This is very useful for preparing query -// flags. 'src' and 'dest' should not overlap. -// Returns the number of bytes written to 'dest' (not including the \0) -// or -1 if there was insufficient space. +// CEscape() +// Escapes 'src' using C-style escape sequences and returns the resulting +// string. // -// Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped. +// Escaped chars: \n, \r, \t, ", ', \, and !isprint(). // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT int CEscapeString(const char* src, int src_len, - char* dest, int dest_len); +LIBPROTOBUF_EXPORT string CEscape(const string& src); // ---------------------------------------------------------------------- -// CEscape() -// More convenient form of CEscapeString: returns result as a "string". -// This version is slower than CEscapeString() because it does more -// allocation. However, it is much more convenient to use in -// non-speed-critical code like logging messages etc. +// CEscapeAndAppend() +// Escapes 'src' using C-style escape sequences, and appends the escaped +// string to 'dest'. // ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT string CEscape(const string& src); +LIBPROTOBUF_EXPORT void CEscapeAndAppend(StringPiece src, string* dest); namespace strings { // Like CEscape() but does not escape bytes with the upper bit set. @@ -349,12 +383,59 @@ inline uint64 strtou64(const char *nptr, char **endptr, int base) { } // ---------------------------------------------------------------------- +// safe_strtob() // safe_strto32() -// ---------------------------------------------------------------------- -LIBPROTOBUF_EXPORT bool safe_int(string text, int32* value_p); +// safe_strtou32() +// safe_strto64() +// safe_strtou64() +// safe_strtof() +// safe_strtod() +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value); + +LIBPROTOBUF_EXPORT bool safe_strto32(const string& str, int32* value); +LIBPROTOBUF_EXPORT bool safe_strtou32(const string& str, uint32* value); +inline bool safe_strto32(const char* str, int32* value) { + return safe_strto32(string(str), value); +} +inline bool safe_strto32(StringPiece str, int32* value) { + return safe_strto32(str.ToString(), value); +} +inline bool safe_strtou32(const char* str, uint32* value) { + return safe_strtou32(string(str), value); +} +inline bool safe_strtou32(StringPiece str, uint32* value) { + return safe_strtou32(str.ToString(), value); +} + +LIBPROTOBUF_EXPORT bool safe_strto64(const string& str, int64* value); +LIBPROTOBUF_EXPORT bool safe_strtou64(const string& str, uint64* value); +inline bool safe_strto64(const char* str, int64* value) { + return safe_strto64(string(str), value); +} +inline bool safe_strto64(StringPiece str, int64* value) { + return safe_strto64(str.ToString(), value); +} +inline bool safe_strtou64(const char* str, uint64* value) { + return safe_strtou64(string(str), value); +} +inline bool safe_strtou64(StringPiece str, uint64* value) { + return safe_strtou64(str.ToString(), value); +} -inline bool safe_strto32(string text, int32* value) { - return safe_int(text, value); +LIBPROTOBUF_EXPORT bool safe_strtof(const char* str, float* value); +LIBPROTOBUF_EXPORT bool safe_strtod(const char* str, double* value); +inline bool safe_strtof(const string& str, float* value) { + return safe_strtof(str.c_str(), value); +} +inline bool safe_strtod(const string& str, double* value) { + return safe_strtod(str.c_str(), value); +} +inline bool safe_strtof(StringPiece str, float* value) { + return safe_strtof(str.ToString(), value); +} +inline bool safe_strtod(StringPiece str, double* value) { + return safe_strtod(str.ToString(), value); } // ---------------------------------------------------------------------- @@ -440,6 +521,10 @@ inline char* FastUInt64ToBuffer(uint64 i, char* buffer) { return buffer; } +inline string SimpleBtoa(bool value) { + return value ? "true" : "false"; +} + // ---------------------------------------------------------------------- // SimpleItoa() // Description: converts an integer to a string. @@ -484,47 +569,185 @@ LIBPROTOBUF_EXPORT char* FloatToBuffer(float i, char* buffer); static const int kDoubleToBufferSize = 32; static const int kFloatToBufferSize = 24; -// ---------------------------------------------------------------------- -// ToString() are internal help methods used in StrCat() and Join() -// ---------------------------------------------------------------------- -namespace internal { -inline string ToString(int i) { - return SimpleItoa(i); -} +namespace strings { -inline string ToString(string a) { - return a; -} -} // namespace internal +enum PadSpec { + NO_PAD = 1, + ZERO_PAD_2, + ZERO_PAD_3, + ZERO_PAD_4, + ZERO_PAD_5, + ZERO_PAD_6, + ZERO_PAD_7, + ZERO_PAD_8, + ZERO_PAD_9, + ZERO_PAD_10, + ZERO_PAD_11, + ZERO_PAD_12, + ZERO_PAD_13, + ZERO_PAD_14, + ZERO_PAD_15, + ZERO_PAD_16, +}; + +struct Hex { + uint64 value; + enum PadSpec spec; + template + explicit Hex(Int v, PadSpec s = NO_PAD) + : spec(s) { + // Prevent sign-extension by casting integers to + // their unsigned counterparts. +#ifdef LANG_CXX11 + static_assert( + sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8, + "Unknown integer type"); +#endif + value = sizeof(v) == 1 ? static_cast(v) + : sizeof(v) == 2 ? static_cast(v) + : sizeof(v) == 4 ? static_cast(v) + : static_cast(v); + } +}; + +struct LIBPROTOBUF_EXPORT AlphaNum { + const char *piece_data_; // move these to string_ref eventually + size_t piece_size_; // move these to string_ref eventually + + char digits[kFastToBufferSize]; + + // No bool ctor -- bools convert to an integral type. + // A bool ctor would also convert incoming pointers (bletch). + + AlphaNum(int32 i32) + : piece_data_(digits), + piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {} + AlphaNum(uint32 u32) + : piece_data_(digits), + piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {} + AlphaNum(int64 i64) + : piece_data_(digits), + piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {} + AlphaNum(uint64 u64) + : piece_data_(digits), + piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {} + + AlphaNum(float f) + : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {} + AlphaNum(double f) + : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {} + + AlphaNum(Hex hex); + + AlphaNum(const char* c_str) + : piece_data_(c_str), piece_size_(strlen(c_str)) {} + // TODO: Add a string_ref constructor, eventually + // AlphaNum(const StringPiece &pc) : piece(pc) {} + + AlphaNum(const string& str) + : piece_data_(str.data()), piece_size_(str.size()) {} + + AlphaNum(StringPiece str) + : piece_data_(str.data()), piece_size_(str.size()) {} + + AlphaNum(internal::StringPiecePod str) + : piece_data_(str.data()), piece_size_(str.size()) {} + + size_t size() const { return piece_size_; } + const char *data() const { return piece_data_; } + + private: + // Use ":" not ':' + AlphaNum(char c); // NOLINT(runtime/explicit) + + // Disallow copy and assign. + AlphaNum(const AlphaNum&); + void operator=(const AlphaNum&); +}; + +} // namespace strings + +using strings::AlphaNum; // ---------------------------------------------------------------------- // StrCat() -// These methods join some strings together. +// This merges the given strings or numbers, with no delimiter. This +// is designed to be the fastest possible way to construct a string out +// of a mix of raw C strings, strings, bool values, +// and numeric values. +// +// Don't use this for user-visible strings. The localization process +// works poorly on strings built up out of fragments. +// +// For clarity and performance, don't use StrCat when appending to a +// string. In particular, avoid using any of these (anti-)patterns: +// str.append(StrCat(...) +// str += StrCat(...) +// str = StrCat(str, ...) +// where the last is the worse, with the potential to change a loop +// from a linear time operation with O(1) dynamic allocations into a +// quadratic time operation with O(n) dynamic allocations. StrAppend +// is a better choice than any of the above, subject to the restriction +// of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may +// be a reference into str. +// ---------------------------------------------------------------------- + +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h); +LIBPROTOBUF_EXPORT string StrCat(const AlphaNum& a, const AlphaNum& b, + const AlphaNum& c, const AlphaNum& d, + const AlphaNum& e, const AlphaNum& f, + const AlphaNum& g, const AlphaNum& h, + const AlphaNum& i); + +inline string StrCat(const AlphaNum& a) { return string(a.data(), a.size()); } + +// ---------------------------------------------------------------------- +// StrAppend() +// Same as above, but adds the output to the given string. +// WARNING: For speed, StrAppend does not try to check each of its input +// arguments to be sure that they are not a subset of the string being +// appended to. That is, while this will work: +// +// string s = "foo"; +// s += s; +// +// This will not (necessarily) work: +// +// string s = "foo"; +// StrAppend(&s, s); +// +// Note: while StrCat supports appending up to 9 arguments, StrAppend +// is currently limited to 4. That's rarely an issue except when +// automatically transforming StrCat to StrAppend, and can easily be +// worked around as consecutive calls to StrAppend are quite efficient. // ---------------------------------------------------------------------- -template -string StrCat( - const T1& a, const T2& b, const T3& c, const T4& d, const T5& e) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c) + internal::ToString(d) + internal::ToString(e); -} -template -string StrCat( - const T1& a, const T2& b, const T3& c, const T4& d) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c) + internal::ToString(d); -} - -template -string StrCat(const T1& a, const T2& b, const T3& c) { - return internal::ToString(a) + internal::ToString(b) + - internal::ToString(c); -} - -template -string StrCat(const T1& a, const T2& b) { - return internal::ToString(a) + internal::ToString(b); -} +LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a); +LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, + const AlphaNum& b); +LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c); +LIBPROTOBUF_EXPORT void StrAppend(string* dest, const AlphaNum& a, + const AlphaNum& b, const AlphaNum& c, + const AlphaNum& d); // ---------------------------------------------------------------------- // Join() @@ -538,7 +761,7 @@ void Join(Iterator start, Iterator end, if (it != start) { result->append(delim); } - result->append(internal::ToString(*it)); + StrAppend(result, *it); } } @@ -556,6 +779,99 @@ string Join(const Range& components, // ---------------------------------------------------------------------- LIBPROTOBUF_EXPORT string ToHex(uint64 num); +// ---------------------------------------------------------------------- +// GlobalReplaceSubstring() +// Replaces all instances of a substring in a string. Does nothing +// if 'substring' is empty. Returns the number of replacements. +// +// NOTE: The string pieces must not overlap s. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT int GlobalReplaceSubstring(const string& substring, + const string& replacement, + string* s); + +// ---------------------------------------------------------------------- +// Base64Unescape() +// Converts "src" which is encoded in Base64 to its binary equivalent and +// writes it to "dest". If src contains invalid characters, dest is cleared +// and the function returns false. Returns true on success. +// ---------------------------------------------------------------------- +LIBPROTOBUF_EXPORT bool Base64Unescape(StringPiece src, string* dest); + +// ---------------------------------------------------------------------- +// WebSafeBase64Unescape() +// This is a variation of Base64Unescape which uses '-' instead of '+', and +// '_' instead of '/'. src is not null terminated, instead specify len. I +// recommend that slen + +#include + +#include +#include +#include + +#ifdef _WIN32 +#define snprintf _snprintf +#endif + +namespace google { +namespace protobuf { +namespace { + +// TODO(kenton): Copy strutil tests from google3? + +TEST(StringUtilityTest, ImmuneToLocales) { + // Remember the old locale. + char* old_locale_cstr = setlocale(LC_NUMERIC, NULL); + ASSERT_TRUE(old_locale_cstr != NULL); + string old_locale = old_locale_cstr; + + // Set the locale to "C". + ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != NULL); + + EXPECT_EQ("1.5", SimpleDtoa(1.5)); + EXPECT_EQ("1.5", SimpleFtoa(1.5)); + + if (setlocale(LC_NUMERIC, "es_ES") == NULL && + setlocale(LC_NUMERIC, "es_ES.utf8") == NULL) { + // Some systems may not have the desired locale available. + GOOGLE_LOG(WARNING) + << "Couldn't set locale to es_ES. Skipping this test."; + } else { + EXPECT_EQ("1.5", SimpleDtoa(1.5)); + EXPECT_EQ("1.5", SimpleFtoa(1.5)); + } + + // Return to original locale. + setlocale(LC_NUMERIC, old_locale.c_str()); +} + +#define EXPECT_EQ_ARRAY(len, x, y, msg) \ + for (int j = 0; j < len; ++j) { \ + EXPECT_EQ(x[j], y[j]) << "" # x << " != " # y \ + << " byte " << j << ": " << msg; \ + } + +static struct { + int plain_length; + const char* plaintext; + const char* cyphertext; +} base64_tests[] = { + // Empty string. + { 0, "", ""}, + + // Basic bit patterns; + // values obtained with "echo -n '...' | uuencode -m test" + + { 1, "\000", "AA==" }, + { 1, "\001", "AQ==" }, + { 1, "\002", "Ag==" }, + { 1, "\004", "BA==" }, + { 1, "\010", "CA==" }, + { 1, "\020", "EA==" }, + { 1, "\040", "IA==" }, + { 1, "\100", "QA==" }, + { 1, "\200", "gA==" }, + + { 1, "\377", "/w==" }, + { 1, "\376", "/g==" }, + { 1, "\375", "/Q==" }, + { 1, "\373", "+w==" }, + { 1, "\367", "9w==" }, + { 1, "\357", "7w==" }, + { 1, "\337", "3w==" }, + { 1, "\277", "vw==" }, + { 1, "\177", "fw==" }, + { 2, "\000\000", "AAA=" }, + { 2, "\000\001", "AAE=" }, + { 2, "\000\002", "AAI=" }, + { 2, "\000\004", "AAQ=" }, + { 2, "\000\010", "AAg=" }, + { 2, "\000\020", "ABA=" }, + { 2, "\000\040", "ACA=" }, + { 2, "\000\100", "AEA=" }, + { 2, "\000\200", "AIA=" }, + { 2, "\001\000", "AQA=" }, + { 2, "\002\000", "AgA=" }, + { 2, "\004\000", "BAA=" }, + { 2, "\010\000", "CAA=" }, + { 2, "\020\000", "EAA=" }, + { 2, "\040\000", "IAA=" }, + { 2, "\100\000", "QAA=" }, + { 2, "\200\000", "gAA=" }, + + { 2, "\377\377", "//8=" }, + { 2, "\377\376", "//4=" }, + { 2, "\377\375", "//0=" }, + { 2, "\377\373", "//s=" }, + { 2, "\377\367", "//c=" }, + { 2, "\377\357", "/+8=" }, + { 2, "\377\337", "/98=" }, + { 2, "\377\277", "/78=" }, + { 2, "\377\177", "/38=" }, + { 2, "\376\377", "/v8=" }, + { 2, "\375\377", "/f8=" }, + { 2, "\373\377", "+/8=" }, + { 2, "\367\377", "9/8=" }, + { 2, "\357\377", "7/8=" }, + { 2, "\337\377", "3/8=" }, + { 2, "\277\377", "v/8=" }, + { 2, "\177\377", "f/8=" }, + + { 3, "\000\000\000", "AAAA" }, + { 3, "\000\000\001", "AAAB" }, + { 3, "\000\000\002", "AAAC" }, + { 3, "\000\000\004", "AAAE" }, + { 3, "\000\000\010", "AAAI" }, + { 3, "\000\000\020", "AAAQ" }, + { 3, "\000\000\040", "AAAg" }, + { 3, "\000\000\100", "AABA" }, + { 3, "\000\000\200", "AACA" }, + { 3, "\000\001\000", "AAEA" }, + { 3, "\000\002\000", "AAIA" }, + { 3, "\000\004\000", "AAQA" }, + { 3, "\000\010\000", "AAgA" }, + { 3, "\000\020\000", "ABAA" }, + { 3, "\000\040\000", "ACAA" }, + { 3, "\000\100\000", "AEAA" }, + { 3, "\000\200\000", "AIAA" }, + { 3, "\001\000\000", "AQAA" }, + { 3, "\002\000\000", "AgAA" }, + { 3, "\004\000\000", "BAAA" }, + { 3, "\010\000\000", "CAAA" }, + { 3, "\020\000\000", "EAAA" }, + { 3, "\040\000\000", "IAAA" }, + { 3, "\100\000\000", "QAAA" }, + { 3, "\200\000\000", "gAAA" }, + + { 3, "\377\377\377", "////" }, + { 3, "\377\377\376", "///+" }, + { 3, "\377\377\375", "///9" }, + { 3, "\377\377\373", "///7" }, + { 3, "\377\377\367", "///3" }, + { 3, "\377\377\357", "///v" }, + { 3, "\377\377\337", "///f" }, + { 3, "\377\377\277", "//+/" }, + { 3, "\377\377\177", "//9/" }, + { 3, "\377\376\377", "//7/" }, + { 3, "\377\375\377", "//3/" }, + { 3, "\377\373\377", "//v/" }, + { 3, "\377\367\377", "//f/" }, + { 3, "\377\357\377", "/+//" }, + { 3, "\377\337\377", "/9//" }, + { 3, "\377\277\377", "/7//" }, + { 3, "\377\177\377", "/3//" }, + { 3, "\376\377\377", "/v//" }, + { 3, "\375\377\377", "/f//" }, + { 3, "\373\377\377", "+///" }, + { 3, "\367\377\377", "9///" }, + { 3, "\357\377\377", "7///" }, + { 3, "\337\377\377", "3///" }, + { 3, "\277\377\377", "v///" }, + { 3, "\177\377\377", "f///" }, + + // Random numbers: values obtained with + // + // #! /bin/bash + // dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random + // od -N $1 -t o1 /tmp/bar.random + // uuencode -m test < /tmp/bar.random + // + // where $1 is the number of bytes (2, 3) + + { 2, "\243\361", "o/E=" }, + { 2, "\024\167", "FHc=" }, + { 2, "\313\252", "y6o=" }, + { 2, "\046\041", "JiE=" }, + { 2, "\145\236", "ZZ4=" }, + { 2, "\254\325", "rNU=" }, + { 2, "\061\330", "Mdg=" }, + { 2, "\245\032", "pRo=" }, + { 2, "\006\000", "BgA=" }, + { 2, "\375\131", "/Vk=" }, + { 2, "\303\210", "w4g=" }, + { 2, "\040\037", "IB8=" }, + { 2, "\261\372", "sfo=" }, + { 2, "\335\014", "3Qw=" }, + { 2, "\233\217", "m48=" }, + { 2, "\373\056", "+y4=" }, + { 2, "\247\232", "p5o=" }, + { 2, "\107\053", "Rys=" }, + { 2, "\204\077", "hD8=" }, + { 2, "\276\211", "vok=" }, + { 2, "\313\110", "y0g=" }, + { 2, "\363\376", "8/4=" }, + { 2, "\251\234", "qZw=" }, + { 2, "\103\262", "Q7I=" }, + { 2, "\142\312", "Yso=" }, + { 2, "\067\211", "N4k=" }, + { 2, "\220\001", "kAE=" }, + { 2, "\152\240", "aqA=" }, + { 2, "\367\061", "9zE=" }, + { 2, "\133\255", "W60=" }, + { 2, "\176\035", "fh0=" }, + { 2, "\032\231", "Gpk=" }, + + { 3, "\013\007\144", "Cwdk" }, + { 3, "\030\112\106", "GEpG" }, + { 3, "\047\325\046", "J9Um" }, + { 3, "\310\160\022", "yHAS" }, + { 3, "\131\100\237", "WUCf" }, + { 3, "\064\342\134", "NOJc" }, + { 3, "\010\177\004", "CH8E" }, + { 3, "\345\147\205", "5WeF" }, + { 3, "\300\343\360", "wOPw" }, + { 3, "\061\240\201", "MaCB" }, + { 3, "\225\333\044", "ldsk" }, + { 3, "\215\137\352", "jV/q" }, + { 3, "\371\147\160", "+Wdw" }, + { 3, "\030\320\051", "GNAp" }, + { 3, "\044\174\241", "JHyh" }, + { 3, "\260\127\037", "sFcf" }, + { 3, "\111\045\033", "SSUb" }, + { 3, "\202\114\107", "gkxH" }, + { 3, "\057\371\042", "L/ki" }, + { 3, "\223\247\244", "k6ek" }, + { 3, "\047\216\144", "J45k" }, + { 3, "\203\070\327", "gzjX" }, + { 3, "\247\140\072", "p2A6" }, + { 3, "\124\115\116", "VE1O" }, + { 3, "\157\162\050", "b3Io" }, + { 3, "\357\223\004", "75ME" }, + { 3, "\052\117\156", "Kk9u" }, + { 3, "\347\154\000", "52wA" }, + { 3, "\303\012\142", "wwpi" }, + { 3, "\060\035\362", "MB3y" }, + { 3, "\130\226\361", "WJbx" }, + { 3, "\173\013\071", "ews5" }, + { 3, "\336\004\027", "3gQX" }, + { 3, "\357\366\234", "7/ac" }, + { 3, "\353\304\111", "68RJ" }, + { 3, "\024\264\131", "FLRZ" }, + { 3, "\075\114\251", "PUyp" }, + { 3, "\315\031\225", "zRmV" }, + { 3, "\154\201\276", "bIG+" }, + { 3, "\200\066\072", "gDY6" }, + { 3, "\142\350\267", "Yui3" }, + { 3, "\033\000\166", "GwB2" }, + { 3, "\210\055\077", "iC0/" }, + { 3, "\341\037\124", "4R9U" }, + { 3, "\161\103\152", "cUNq" }, + { 3, "\270\142\131", "uGJZ" }, + { 3, "\337\076\074", "3z48" }, + { 3, "\375\106\362", "/Uby" }, + { 3, "\227\301\127", "l8FX" }, + { 3, "\340\002\234", "4AKc" }, + { 3, "\121\064\033", "UTQb" }, + { 3, "\157\134\143", "b1xj" }, + { 3, "\247\055\327", "py3X" }, + { 3, "\340\142\005", "4GIF" }, + { 3, "\060\260\143", "MLBj" }, + { 3, "\075\203\170", "PYN4" }, + { 3, "\143\160\016", "Y3AO" }, + { 3, "\313\013\063", "ywsz" }, + { 3, "\174\236\135", "fJ5d" }, + { 3, "\103\047\026", "QycW" }, + { 3, "\365\005\343", "9QXj" }, + { 3, "\271\160\223", "uXCT" }, + { 3, "\362\255\172", "8q16" }, + { 3, "\113\012\015", "SwoN" }, + + // various lengths, generated by this python script: + // + // from string import lowercase as lc + // for i in range(27): + // print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i), + // lc[:i].encode('base64').strip()) + + { 0, "", "" }, + { 1, "a", "YQ==" }, + { 2, "ab", "YWI=" }, + { 3, "abc", "YWJj" }, + { 4, "abcd", "YWJjZA==" }, + { 5, "abcde", "YWJjZGU=" }, + { 6, "abcdef", "YWJjZGVm" }, + { 7, "abcdefg", "YWJjZGVmZw==" }, + { 8, "abcdefgh", "YWJjZGVmZ2g=" }, + { 9, "abcdefghi", "YWJjZGVmZ2hp" }, + { 10, "abcdefghij", "YWJjZGVmZ2hpag==" }, + { 11, "abcdefghijk", "YWJjZGVmZ2hpams=" }, + { 12, "abcdefghijkl", "YWJjZGVmZ2hpamts" }, + { 13, "abcdefghijklm", "YWJjZGVmZ2hpamtsbQ==" }, + { 14, "abcdefghijklmn", "YWJjZGVmZ2hpamtsbW4=" }, + { 15, "abcdefghijklmno", "YWJjZGVmZ2hpamtsbW5v" }, + { 16, "abcdefghijklmnop", "YWJjZGVmZ2hpamtsbW5vcA==" }, + { 17, "abcdefghijklmnopq", "YWJjZGVmZ2hpamtsbW5vcHE=" }, + { 18, "abcdefghijklmnopqr", "YWJjZGVmZ2hpamtsbW5vcHFy" }, + { 19, "abcdefghijklmnopqrs", "YWJjZGVmZ2hpamtsbW5vcHFycw==" }, + { 20, "abcdefghijklmnopqrst", "YWJjZGVmZ2hpamtsbW5vcHFyc3Q=" }, + { 21, "abcdefghijklmnopqrstu", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1" }, + { 22, "abcdefghijklmnopqrstuv", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg==" }, + { 23, "abcdefghijklmnopqrstuvw", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc=" }, + { 24, "abcdefghijklmnopqrstuvwx", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4" }, + { 25, "abcdefghijklmnopqrstuvwxy", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ==" }, + { 26, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=" }, +}; + +static struct { + const char* plaintext; + const char* cyphertext; +} base64_strings[] = { + // Some google quotes + // Cyphertext created with "uuencode (GNU sharutils) 4.6.3" + // (Note that we're testing the websafe encoding, though, so if + // you add messages, be sure to run "tr -- '+/' '-_'" on the output) + { "I was always good at math and science, and I never realized " + "that was unusual or somehow undesirable. So one of the things " + "I care a lot about is helping to remove that stigma, " + "to show girls that you can be feminine, you can like the things " + "that girls like, but you can also be really good at technology. " + "You can be really good at building things." + " - Marissa Meyer, Newsweek, 2010-12-22" "\n", + + "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg" + "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu" + "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg" + "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo" + "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp" + "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs" + "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy" + "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll" + "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK" }, + + { "Typical first year for a new cluster: " + "~0.5 overheating " + "~1 PDU failure " + "~1 rack-move " + "~1 network rewiring " + "~20 rack failures " + "~5 racks go wonky " + "~8 network maintenances " + "~12 router reloads " + "~3 router failures " + "~dozens of minor 30-second blips for dns " + "~1000 individual machine failures " + "~thousands of hard drive failures " + "slow disks, bad memory, misconfigured machines, flaky machines, etc." + " - Jeff Dean, The Joys of Real Hardware" "\n", + + "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92" + "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3" + "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv" + "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk" + "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv" + "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp" + "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg" + "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs" + "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS" + "ZWFsIEhhcmR3YXJlCg" }, + + { "I'm the head of the webspam team at Google. " + "That means that if you type your name into Google and get porn back, " + "it's my fault. Unless you're a porn star, in which case porn is a " + "completely reasonable response." + " - Matt Cutts, Google Plus" "\n", + + "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg" + "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv" + "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz" + "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg" + "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs" + "IEdvb2dsZSBQbHVzCg" }, + + { "It will still be a long time before machines approach human intelligence. " + "But luckily, machines don't actually have to be intelligent; " + "they just have to fake it. Access to a wealth of information, " + "combined with a rudimentary decision-making capacity, " + "can often be almost as useful. Of course, the results are better yet " + "when coupled with intelligence. A reference librarian with access to " + "a good search engine is a formidable tool." + " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004" "\n", + + "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg" + "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj" + "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg" + "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo" + "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg" + "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0" + "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy" + "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl" + "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu" + "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp" + "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw" + "NAo" }, + + // Degenerate edge case + { "", + "" }, +}; + +TEST(Base64, EscapeAndUnescape) { + // Check the short strings; this tests the math (and boundaries) + for (int i = 0; i < sizeof(base64_tests) / sizeof(base64_tests[0]); ++i) { + char encode_buffer[100]; + int encode_length; + char decode_buffer[100]; + int decode_length; + int cypher_length; + string decode_str; + + const unsigned char* unsigned_plaintext = + reinterpret_cast(base64_tests[i].plaintext); + + StringPiece plaintext(base64_tests[i].plaintext, + base64_tests[i].plain_length); + + cypher_length = strlen(base64_tests[i].cyphertext); + + // The basic escape function: + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = Base64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + sizeof(encode_buffer)); + // Is it of the expected length? + EXPECT_EQ(encode_length, cypher_length); + // Would it have been okay to allocate only CalculateBase64EscapeLen()? + EXPECT_EQ(CalculateBase64EscapedLen(base64_tests[i].plain_length), + encode_length); + + // Is it the expected encoded value? + ASSERT_STREQ(encode_buffer, base64_tests[i].cyphertext); + + // If we encode it into a buffer of exactly the right length... + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = Base64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + cypher_length); + // Is it still of the expected length? + EXPECT_EQ(encode_length, cypher_length); + + // And is the value still correct? (i.e., not losing the last byte) + EXPECT_STREQ(encode_buffer, base64_tests[i].cyphertext); + + // If we decode it back: + decode_str.clear(); + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, cypher_length), &decode_str)); + + // Is it of the expected length? + EXPECT_EQ(base64_tests[i].plain_length, decode_str.length()); + + // Is it the expected decoded value? + EXPECT_EQ(plaintext, decode_str); + + // Let's try with a pre-populated string. + string encoded("this junk should be ignored"); + Base64Escape(string(base64_tests[i].plaintext, + base64_tests[i].plain_length), + &encoded); + EXPECT_EQ(encoded, string(encode_buffer, cypher_length)); + + string decoded("this junk should be ignored"); + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, cypher_length), &decoded)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Our decoder treats the padding '=' characters at the end as + // optional (but if there are any, there must be the correct + // number of them.) If encode_buffer has any, run some additional + // tests that fiddle with them. + char* first_equals = strchr(encode_buffer, '='); + if (first_equals) { + // How many equals signs does the string start with? + int equals = (*(first_equals+1) == '=') ? 2 : 1; + + // Try chopping off the equals sign(s) entirely. The decoder + // should still be okay with this. + string decoded2("this junk should also be ignored"); + *first_equals = '\0'; + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, first_equals - encode_buffer), &decoded2)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Now test chopping off the equals sign(s) and adding + // whitespace. Our decoder should still accept this. + decoded2.assign("this junk should be ignored"); + *first_equals = ' '; + *(first_equals+1) = '\0'; + EXPECT_TRUE(Base64Unescape( + StringPiece(encode_buffer, first_equals - encode_buffer + 1), + &decoded2)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Now stick a bad character at the end of the string. The decoder + // should refuse this string. + decoded2.assign("this junk should be ignored"); + *first_equals = '?'; + *(first_equals+1) = '\0'; + EXPECT_TRUE( + !Base64Unescape( + StringPiece(encode_buffer, first_equals - encode_buffer + 1), + &decoded2)); + + int len; + + // Test whitespace mixed with the padding. (eg "AA = = ") The + // decoder should accept this. + if (equals == 2) { + snprintf(first_equals, 6, " = = "); + len = first_equals - encode_buffer + 5; + } else { + snprintf(first_equals, 6, " = "); + len = first_equals - encode_buffer + 3; + } + decoded2.assign("this junk should be ignored"); + EXPECT_TRUE( + Base64Unescape(StringPiece(encode_buffer, len), &decoded2)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Test whitespace mixed with the padding, but with the wrong + // number of equals signs (eg "AA = "). The decoder should + // refuse these strings. + if (equals == 1) { + snprintf(first_equals, 6, " = = "); + len = first_equals - encode_buffer + 5; + } else { + snprintf(first_equals, 6, " = "); + len = first_equals - encode_buffer + 3; + } + EXPECT_TRUE( + !Base64Unescape(StringPiece(encode_buffer, len), &decoded2)); + } + + // Cool! the basic Base64 encoder/decoder works. + // Let's try the alternate alphabet: tr -- '+/' '-_' + + char websafe[100]; + memset(websafe, 0, sizeof(websafe)); + strncpy(websafe, base64_tests[i].cyphertext, cypher_length); + for (int c = 0; c < sizeof(websafe); ++c) { + if ('+' == websafe[c]) { websafe[c] = '-'; } + if ('/' == websafe[c]) { websafe[c] = '_'; } + } + + // The websafe escape function: + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + sizeof(encode_buffer), + true); + // Is it of the expected length? + EXPECT_EQ(encode_length, cypher_length); + EXPECT_EQ( + CalculateBase64EscapedLen(base64_tests[i].plain_length, true), + encode_length); + + // Is it the expected encoded value? + EXPECT_STREQ(encode_buffer, websafe); + + // If we encode it into a buffer of exactly the right length... + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + cypher_length, + true); + // Is it still of the expected length? + EXPECT_EQ(encode_length, cypher_length); + + // And is the value still correct? (i.e., not losing the last byte) + EXPECT_STREQ(encode_buffer, websafe); + + // Let's try the string version of the encoder + encoded = "this junk should be ignored"; + WebSafeBase64Escape( + unsigned_plaintext, base64_tests[i].plain_length, + &encoded, true); + EXPECT_EQ(encoded.size(), cypher_length); + EXPECT_STREQ(encoded.c_str(), websafe); + + // If we decode it back: + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + sizeof(decode_buffer)); + + // Is it of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // Is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // If we decode it into a buffer of exactly the right length... + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + decode_length); + + // Is it still of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // And is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // Try using '.' for the pad character. + for (int c = cypher_length - 1; c >= 0 && '=' == encode_buffer[c]; --c) { + encode_buffer[c] = '.'; + } + + // If we decode it back: + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + sizeof(decode_buffer)); + + // Is it of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // Is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // If we decode it into a buffer of exactly the right length... + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + decode_length); + + // Is it still of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // And is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // Let's try the string version of the decoder + decoded = "this junk should be ignored"; + EXPECT_TRUE(WebSafeBase64Unescape( + StringPiece(encode_buffer, cypher_length), &decoded)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // Okay! the websafe Base64 encoder/decoder works. + // Let's try the unpadded version + + for (int c = 0; c < sizeof(websafe); ++c) { + if ('=' == websafe[c]) { + websafe[c] = '\0'; + cypher_length = c; + break; + } + } + + // The websafe escape function: + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + sizeof(encode_buffer), + false); + // Is it of the expected length? + EXPECT_EQ(encode_length, cypher_length); + EXPECT_EQ( + CalculateBase64EscapedLen(base64_tests[i].plain_length, false), + encode_length); + + // Is it the expected encoded value? + EXPECT_STREQ(encode_buffer, websafe); + + // If we encode it into a buffer of exactly the right length... + memset(encode_buffer, 0, sizeof(encode_buffer)); + encode_length = WebSafeBase64Escape(unsigned_plaintext, + base64_tests[i].plain_length, + encode_buffer, + cypher_length, + false); + // Is it still of the expected length? + EXPECT_EQ(encode_length, cypher_length); + + // And is the value still correct? (i.e., not losing the last byte) + EXPECT_STREQ(encode_buffer, websafe); + + // Let's try the (other) string version of the encoder + string plain(base64_tests[i].plaintext, base64_tests[i].plain_length); + encoded = "this junk should be ignored"; + WebSafeBase64Escape(plain, &encoded); + EXPECT_EQ(encoded.size(), cypher_length); + EXPECT_STREQ(encoded.c_str(), websafe); + + // If we decode it back: + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + sizeof(decode_buffer)); + + // Is it of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // Is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + // If we decode it into a buffer of exactly the right length... + memset(decode_buffer, 0, sizeof(decode_buffer)); + decode_length = WebSafeBase64Unescape(encode_buffer, + cypher_length, + decode_buffer, + decode_length); + + // Is it still of the expected length? + EXPECT_EQ(decode_length, base64_tests[i].plain_length); + + // And is it the expected decoded value? + EXPECT_EQ(0, + memcmp(decode_buffer, base64_tests[i].plaintext, decode_length)); + + + // Let's try the string version of the decoder + decoded = "this junk should be ignored"; + EXPECT_TRUE(WebSafeBase64Unescape( + StringPiece(encode_buffer, cypher_length), &decoded)); + EXPECT_EQ(decoded.size(), base64_tests[i].plain_length); + EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i); + + // This value works. Try the next. + } + + // Now try the long strings, this tests the streaming + for (int i = 0; i < sizeof(base64_strings) / sizeof(base64_strings[0]); + ++i) { + const unsigned char* unsigned_plaintext = + reinterpret_cast(base64_strings[i].plaintext); + int plain_length = strlen(base64_strings[i].plaintext); + int cypher_length = strlen(base64_strings[i].cyphertext); + std::vector buffer(cypher_length+1); + int encode_length = WebSafeBase64Escape(unsigned_plaintext, + plain_length, + &buffer[0], + buffer.size(), + false); + EXPECT_EQ(cypher_length, encode_length); + EXPECT_EQ( + CalculateBase64EscapedLen(plain_length, false), encode_length); + buffer[ encode_length ] = '\0'; + EXPECT_STREQ(base64_strings[i].cyphertext, &buffer[0]); + } + + // Verify the behavior when decoding bad data + { + const char* bad_data = "ab-/"; + string buf; + EXPECT_FALSE(Base64Unescape(StringPiece(bad_data), &buf)); + EXPECT_TRUE(!WebSafeBase64Unescape(bad_data, &buf)); + EXPECT_TRUE(buf.empty()); + } +} + +} // anonymous namespace +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/substitute.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/substitute.cc similarity index 97% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/substitute.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/substitute.cc index c9d95899f..7194a5b17 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/substitute.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/substitute.cc @@ -113,7 +113,9 @@ void SubstituteAndAppend( for (int i = 0; format[i] != '\0'; i++) { if (format[i] == '$') { if (ascii_isdigit(format[i+1])) { - const SubstituteArg* src = args_array[format[i+1] - '0']; + unsigned int index = format[i+1] - '0'; + assert(index < 10); + const SubstituteArg* src = args_array[index]; memcpy(target, src->data(), src->size()); target += src->size(); ++i; // Skip next char. diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/substitute.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/substitute.h similarity index 100% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/substitute.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/substitute.h diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/template_util.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/template_util.h similarity index 98% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/template_util.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/template_util.h index 4f30ffa3b..feef904be 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/template_util.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/template_util.h @@ -37,7 +37,7 @@ // any changes here, make sure that you're not breaking any platforms. // // -// The names choosen here reflect those used in tr1 and the boost::mpl +// The names chosen here reflect those used in tr1 and the boost::mpl // library, there are similar operations used in the Loki library as // well. I prefer the boost names for 2 reasons: // 1. I think that portions of the Boost libraries are more likely to diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/template_util_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/template_util_unittest.cc similarity index 100% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/stubs/template_util_unittest.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/template_util_unittest.cc diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/time.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/time.cc new file mode 100644 index 000000000..6def637ee --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/time.cc @@ -0,0 +1,365 @@ +#include + +#include + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { + +namespace { +static const int64 kSecondsPerMinute = 60; +static const int64 kSecondsPerHour = 3600; +static const int64 kSecondsPerDay = kSecondsPerHour * 24; +static const int64 kSecondsPer400Years = + kSecondsPerDay * (400 * 365 + 400 / 4 - 3); +// Seconds from 0001-01-01T00:00:00 to 1970-01-01T:00:00:00 +static const int64 kSecondsFromEraToEpoch = 62135596800LL; +// The range of timestamp values we support. +static const int64 kMinTime = -62135596800LL; // 0001-01-01T00:00:00 +static const int64 kMaxTime = 253402300799LL; // 9999-12-31T23:59:59 + +static const int kNanosPerMillisecond = 1000000; +static const int kNanosPerMicrosecond = 1000; + +// Count the seconds from the given year (start at Jan 1, 00:00) to 100 years +// after. +int64 SecondsPer100Years(int year) { + if (year % 400 == 0 || year % 400 > 300) { + return kSecondsPerDay * (100 * 365 + 100 / 4); + } else { + return kSecondsPerDay * (100 * 365 + 100 / 4 - 1); + } +} + +// Count the seconds from the given year (start at Jan 1, 00:00) to 4 years +// after. +int64 SecondsPer4Years(int year) { + if ((year % 100 == 0 || year % 100 > 96) && + !(year % 400 == 0 || year % 400 > 396)) { + // No leap years. + return kSecondsPerDay * (4 * 365); + } else { + // One leap years. + return kSecondsPerDay * (4 * 365 + 1); + } +} + +bool IsLeapYear(int year) { + return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0); +} + +int64 SecondsPerYear(int year) { + return kSecondsPerDay * (IsLeapYear(year) ? 366 : 365); +} + +static const int kDaysInMonth[13] = { + 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +int64 SecondsPerMonth(int month, bool leap) { + if (month == 2 && leap) { + return kSecondsPerDay * (kDaysInMonth[month] + 1); + } + return kSecondsPerDay * kDaysInMonth[month]; +} + +static const int kDaysSinceJan[13] = { + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, +}; + +bool ValidateDateTime(const DateTime& time) { + if (time.year < 1 || time.year > 9999 || + time.month < 1 || time.month > 12 || + time.day < 1 || time.day > 31 || + time.hour < 0 || time.hour > 23 || + time.minute < 0 || time.minute > 59 || + time.second < 0 || time.second > 59) { + return false; + } + if (time.month == 2 && IsLeapYear(time.year)) { + return time.day <= kDaysInMonth[time.month] + 1; + } else { + return time.day <= kDaysInMonth[time.month]; + } +} + +// Count the number of seconds elapsed from 0001-01-01T00:00:00 to the given +// time. +int64 SecondsSinceCommonEra(const DateTime& time) { + int64 result = 0; + // Years should be between 1 and 9999. + assert(time.year >= 1 && time.year <= 9999); + int year = 1; + if ((time.year - year) >= 400) { + int count_400years = (time.year - year) / 400; + result += kSecondsPer400Years * count_400years; + year += count_400years * 400; + } + while ((time.year - year) >= 100) { + result += SecondsPer100Years(year); + year += 100; + } + while ((time.year - year) >= 4) { + result += SecondsPer4Years(year); + year += 4; + } + while (time.year > year) { + result += SecondsPerYear(year); + ++year; + } + // Months should be between 1 and 12. + assert(time.month >= 1 && time.month <= 12); + int month = time.month; + result += kSecondsPerDay * kDaysSinceJan[month]; + if (month > 2 && IsLeapYear(year)) { + result += kSecondsPerDay; + } + assert(time.day >= 1 && + time.day <= (month == 2 && IsLeapYear(year) + ? kDaysInMonth[month] + 1 + : kDaysInMonth[month])); + result += kSecondsPerDay * (time.day - 1); + result += kSecondsPerHour * time.hour + + kSecondsPerMinute * time.minute + + time.second; + return result; +} + +// Format nanoseconds with either 3, 6, or 9 digits depending on the required +// precision to represent the exact value. +string FormatNanos(int32 nanos) { + if (nanos % kNanosPerMillisecond == 0) { + return StringPrintf("%03d", nanos / kNanosPerMillisecond); + } else if (nanos % kNanosPerMicrosecond == 0) { + return StringPrintf("%06d", nanos / kNanosPerMicrosecond); + } else { + return StringPrintf("%09d", nanos); + } +} + +// Parses an integer from a null-terminated char sequence. The method +// consumes at most "width" chars. Returns a pointer after the consumed +// integer, or NULL if the data does not start with an integer or the +// integer value does not fall in the range of [min_value, max_value]. +const char* ParseInt(const char* data, int width, int min_value, + int max_value, int* result) { + if (!ascii_isdigit(*data)) { + return NULL; + } + int value = 0; + for (int i = 0; i < width; ++i, ++data) { + if (ascii_isdigit(*data)) { + value = value * 10 + (*data - '0'); + } else { + break; + } + } + if (value >= min_value && value <= max_value) { + *result = value; + return data; + } else { + return NULL; + } +} + +// Consumes the fractional parts of a second into nanos. For example, +// "010" will be parsed to 10000000 nanos. +const char* ParseNanos(const char* data, int32* nanos) { + if (!ascii_isdigit(*data)) { + return NULL; + } + int value = 0; + int len = 0; + // Consume as many digits as there are but only take the first 9 into + // account. + while (ascii_isdigit(*data)) { + if (len < 9) { + value = value * 10 + *data - '0'; + } + ++len; + ++data; + } + while (len < 9) { + value = value * 10; + ++len; + } + *nanos = value; + return data; +} + +const char* ParseTimezoneOffset(const char* data, int64* offset) { + // Accept format "HH:MM". E.g., "08:00" + int hour; + if ((data = ParseInt(data, 2, 0, 23, &hour)) == NULL) { + return NULL; + } + if (*data++ != ':') { + return NULL; + } + int minute; + if ((data = ParseInt(data, 2, 0, 59, &minute)) == NULL) { + return NULL; + } + *offset = (hour * 60 + minute) * 60; + return data; +} +} // namespace + +bool SecondsToDateTime(int64 seconds, DateTime* time) { + if (seconds < kMinTime || seconds > kMaxTime) { + return false; + } + // It's easier to calcuate the DateTime starting from 0001-01-01T00:00:00 + seconds = seconds + kSecondsFromEraToEpoch; + int year = 1; + if (seconds >= kSecondsPer400Years) { + int count_400years = seconds / kSecondsPer400Years; + year += 400 * count_400years; + seconds %= kSecondsPer400Years; + } + while (seconds >= SecondsPer100Years(year)) { + seconds -= SecondsPer100Years(year); + year += 100; + } + while (seconds >= SecondsPer4Years(year)) { + seconds -= SecondsPer4Years(year); + year += 4; + } + while (seconds >= SecondsPerYear(year)) { + seconds -= SecondsPerYear(year); + year += 1; + } + bool leap = IsLeapYear(year); + int month = 1; + while (seconds >= SecondsPerMonth(month, leap)) { + seconds -= SecondsPerMonth(month, leap); + ++month; + } + int day = 1 + seconds / kSecondsPerDay; + seconds %= kSecondsPerDay; + int hour = seconds / kSecondsPerHour; + seconds %= kSecondsPerHour; + int minute = seconds / kSecondsPerMinute; + seconds %= kSecondsPerMinute; + time->year = year; + time->month = month; + time->day = day; + time->hour = hour; + time->minute = minute; + time->second = static_cast(seconds); + return true; +} + +bool DateTimeToSeconds(const DateTime& time, int64* seconds) { + if (!ValidateDateTime(time)) { + return false; + } + *seconds = SecondsSinceCommonEra(time) - kSecondsFromEraToEpoch; + return true; +} + +void GetCurrentTime(int64* seconds, int32* nanos) { + // TODO(xiaofeng): Improve the accuracy of this implementation (or just + // remove this method from protobuf). + *seconds = time(NULL); + *nanos = 0; +} + +string FormatTime(int64 seconds, int32 nanos) { + DateTime time; + if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) { + return "InvalidTime"; + } + string result = StringPrintf("%04d-%02d-%02dT%02d:%02d:%02d", + time.year, time.month, time.day, + time.hour, time.minute, time.second); + if (nanos != 0) { + result += "." + FormatNanos(nanos); + } + return result + "Z"; +} + +bool ParseTime(const string& value, int64* seconds, int32* nanos) { + DateTime time; + const char* data = value.c_str(); + // We only accept: + // Z-normalized: 2015-05-20T13:29:35.120Z + // With UTC offset: 2015-05-20T13:29:35.120-08:00 + + // Parse year + if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == NULL) { + return false; + } + // Expect '-' + if (*data++ != '-') return false; + // Parse month + if ((data = ParseInt(data, 2, 1, 12, &time.month)) == NULL) { + return false; + } + // Expect '-' + if (*data++ != '-') return false; + // Parse day + if ((data = ParseInt(data, 2, 1, 31, &time.day)) == NULL) { + return false; + } + // Expect 'T' + if (*data++ != 'T') return false; + // Parse hour + if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == NULL) { + return false; + } + // Expect ':' + if (*data++ != ':') return false; + // Parse minute + if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == NULL) { + return false; + } + // Expect ':' + if (*data++ != ':') return false; + // Parse second + if ((data = ParseInt(data, 2, 0, 59, &time.second)) == NULL) { + return false; + } + if (!DateTimeToSeconds(time, seconds)) { + return false; + } + // Parse nanoseconds. + if (*data == '.') { + ++data; + // Parse nanoseconds. + if ((data = ParseNanos(data, nanos)) == NULL) { + return false; + } + } else { + *nanos = 0; + } + // Parse UTC offsets. + if (*data == 'Z') { + ++data; + } else if (*data == '+') { + ++data; + int64 offset; + if ((data = ParseTimezoneOffset(data, &offset)) == NULL) { + return false; + } + *seconds -= offset; + } else if (*data == '-') { + ++data; + int64 offset; + if ((data = ParseTimezoneOffset(data, &offset)) == NULL) { + return false; + } + *seconds += offset; + } else { + return false; + } + // Done with parsing. + return *data == 0; +} + +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/time.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/time.h new file mode 100644 index 000000000..45607ca9b --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/time.h @@ -0,0 +1,75 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. +#ifndef GOOGLE_PROTOBUF_STUBS_TIME_H_ +#define GOOGLE_PROTOBUF_STUBS_TIME_H_ + +#include + +namespace google { +namespace protobuf { +namespace internal { + +struct DateTime { + int year; + int month; + int day; + int hour; + int minute; + int second; +}; + +// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be +// negative to represent time before 1970-01-01) to DateTime. Returns false +// if the timestamp is not in the range between 0001-01-01T00:00:00 and +// 9999-12-31T23:59:59. +bool LIBPROTOBUF_EXPORT SecondsToDateTime(int64 seconds, DateTime* time); +// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00). +// Returns false if the DateTime is not valid or is not in the valid range. +bool LIBPROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64* seconds); + +void LIBPROTOBUF_EXPORT GetCurrentTime(int64* seconds, int32* nanos); + +// Formats a time string in RFC3339 fromat. +// +// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional +// digits will be used depending on how many are required to represent the exact +// value. +// +// Note that "nanos" must in the range of [0, 999999999]. +string LIBPROTOBUF_EXPORT FormatTime(int64 seconds, int32 nanos); +// Parses a time string. This method accepts RFC3339 date/time string with UTC +// offset. For example, "2015-05-20T13:29:35.120-08:00". +bool LIBPROTOBUF_EXPORT ParseTime(const string& value, int64* seconds, int32* nanos); + +} // namespace internal +} // namespace protobuf +} // namespace google + +#endif // GOOGLE_PROTOBUF_STUBS_TIME_H_ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/time_test.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/time_test.cc new file mode 100644 index 000000000..53da94804 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/stubs/time_test.cc @@ -0,0 +1,261 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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 + +#include +#include + +namespace google { +namespace protobuf { +namespace internal { +namespace { +static const int64 kSecondsPerDay = 3600 * 24; + +// For DateTime, tests will mostly focuse on the date part because that's +// the tricky one. +int64 CreateTimestamp(int year, int month, int day) { + DateTime time; + time.year = year; + time.month = month; + time.day = day; + time.hour = time.minute = time.second = 0; + int64 result; + GOOGLE_CHECK(DateTimeToSeconds(time, &result)); + // Check that a roundtrip produces the same result. + GOOGLE_CHECK(SecondsToDateTime(result, &time)); + GOOGLE_CHECK(time.year == year); + GOOGLE_CHECK(time.month == month); + GOOGLE_CHECK(time.day == day); + return result; +} + +TEST(DateTimeTest, SimpleTime) { + DateTime time; + ASSERT_TRUE(SecondsToDateTime(1, &time)); + EXPECT_EQ(1970, time.year); + EXPECT_EQ(1, time.month); + EXPECT_EQ(1, time.day); + EXPECT_EQ(0, time.hour); + EXPECT_EQ(0, time.minute); + EXPECT_EQ(1, time.second); + int64 seconds; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(1, seconds); + + ASSERT_TRUE(SecondsToDateTime(-1, &time)); + EXPECT_EQ(1969, time.year); + EXPECT_EQ(12, time.month); + EXPECT_EQ(31, time.day); + EXPECT_EQ(23, time.hour); + EXPECT_EQ(59, time.minute); + EXPECT_EQ(59, time.second); + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(-1, seconds); + + DateTime start, end; + start.year = 1; + start.month = 1; + start.day = 1; + start.hour = 0; + start.minute = 0; + start.second = 0; + end.year = 9999; + end.month = 12; + end.day = 31; + end.hour = 23; + end.minute = 59; + end.second = 59; + int64 start_time, end_time; + ASSERT_TRUE(DateTimeToSeconds(start, &start_time)); + ASSERT_TRUE(DateTimeToSeconds(end, &end_time)); + EXPECT_EQ(315537897599LL, end_time - start_time); + ASSERT_TRUE(SecondsToDateTime(start_time, &time)); + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(start_time, seconds); + ASSERT_TRUE(SecondsToDateTime(end_time, &time)); + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + EXPECT_EQ(end_time, seconds); +} + +TEST(DateTimeTest, DayInMonths) { + // Check that month boundaries are handled correctly. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 1, 1) - CreateTimestamp(2014, 12, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 2, 1) - CreateTimestamp(2015, 1, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 4, 1) - CreateTimestamp(2015, 3, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 5, 1) - CreateTimestamp(2015, 4, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 6, 1) - CreateTimestamp(2015, 5, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 7, 1) - CreateTimestamp(2015, 6, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 8, 1) - CreateTimestamp(2015, 7, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 9, 1) - CreateTimestamp(2015, 8, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 10, 1) - CreateTimestamp(2015, 9, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 11, 1) - CreateTimestamp(2015, 10, 31)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 12, 1) - CreateTimestamp(2015, 11, 30)); + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2016, 1, 1) - CreateTimestamp(2015, 12, 31)); +} + +TEST(DateTimeTest, LeapYear) { + // Non-leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28)); + // Leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2016, 3, 1) - CreateTimestamp(2016, 2, 29)); + // Non-leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2100, 3, 1) - CreateTimestamp(2100, 2, 28)); + // Leap year. + EXPECT_EQ(kSecondsPerDay, + CreateTimestamp(2400, 3, 1) - CreateTimestamp(2400, 2, 29)); +} + +TEST(DateTimeTest, WrongDays) { + int64 seconds; + DateTime time; + time.hour = 0; + time.minute = 0; + time.second = 0; + time.month = 2; + + // Non-leap year. + time.year = 2015; + time.day = 29; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Leap year. + time.year = 2016; + time.day = 29; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + time.day = 30; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Non-leap year. + time.year = 2100; + time.day = 29; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Leap year. + time.year = 2400; + time.day = 29; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + time.day = 30; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Non-february + time.year = 2015; + time.month = 1; + time.day = 0; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + time.day = 1; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + time.day = 31; + ASSERT_TRUE(DateTimeToSeconds(time, &seconds)); + time.day = 32; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + + // Bad month + time.year = 2015; + time.month = 0; + time.day = 1; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); + time.month = 13; + ASSERT_FALSE(DateTimeToSeconds(time, &seconds)); +} + +TEST(DateTimeTest, StringFormat) { + DateTime start, end; + start.year = 1; + start.month = 1; + start.day = 1; + start.hour = 0; + start.minute = 0; + start.second = 0; + end.year = 9999; + end.month = 12; + end.day = 31; + end.hour = 23; + end.minute = 59; + end.second = 59; + int64 start_time, end_time; + ASSERT_TRUE(DateTimeToSeconds(start, &start_time)); + ASSERT_TRUE(DateTimeToSeconds(end, &end_time)); + + EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(start_time, 0)); + EXPECT_EQ("9999-12-31T23:59:59Z", FormatTime(end_time, 0)); + + // Make sure the nanoseconds part is formated correctly. + EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(0, 10000000)); + EXPECT_EQ("1970-01-01T00:00:00.000010Z", FormatTime(0, 10000)); + EXPECT_EQ("1970-01-01T00:00:00.000000010Z", FormatTime(0, 10)); +} + +TEST(DateTimeTest, ParseString) { + int64 seconds; + int32 nanos; + ASSERT_TRUE(ParseTime("0001-01-01T00:00:00Z", &seconds, &nanos)); + EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("9999-12-31T23:59:59.999999999Z", &seconds, &nanos)); + EXPECT_EQ("9999-12-31T23:59:59.999999999Z", FormatTime(seconds, nanos)); + + // Test time zone offsets. + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00-08:00", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T08:00:00Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00+08:00", &seconds, &nanos)); + EXPECT_EQ("1969-12-31T16:00:00Z", FormatTime(seconds, nanos)); + + // Test nanoseconds. + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.01Z", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00001-08:00", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T08:00:00.000010Z", FormatTime(seconds, nanos)); + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00000001+08:00", &seconds, &nanos)); + EXPECT_EQ("1969-12-31T16:00:00.000000010Z", FormatTime(seconds, nanos)); + // Fractional parts less than 1 nanosecond will be ignored. + ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.0123456789Z", &seconds, &nanos)); + EXPECT_EQ("1970-01-01T00:00:00.012345678Z", FormatTime(seconds, nanos)); +} + +} // namespace +} // namespace internal +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_messages_proto2.proto b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_messages_proto2.proto new file mode 100644 index 000000000..60dbfc753 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_messages_proto2.proto @@ -0,0 +1,216 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. +// +// Test schema for proto2 messages. This test schema is used by: +// +// - conformance tests +// + +syntax = "proto2"; + +package protobuf_test_messages.proto2; +option java_package = "com.google.protobuf_test_messages.proto2"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; + +option cc_enable_arenas = true; + +// This proto includes every type of field in both singular and repeated +// forms. +// +// Also, crucially, all messages and enums in this file are eventually +// submessages of this message. So for example, a fuzz test of TestAllTypes +// could trigger bugs that occur in any message type in this file. We verify +// this stays true in a unit test. +message TestAllTypesProto2 { + message NestedMessage { + optional int32 a = 1; + optional TestAllTypesProto2 corecursive = 2; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + // Singular + optional int32 optional_int32 = 1; + optional int64 optional_int64 = 2; + optional uint32 optional_uint32 = 3; + optional uint64 optional_uint64 = 4; + optional sint32 optional_sint32 = 5; + optional sint64 optional_sint64 = 6; + optional fixed32 optional_fixed32 = 7; + optional fixed64 optional_fixed64 = 8; + optional sfixed32 optional_sfixed32 = 9; + optional sfixed64 optional_sfixed64 = 10; + optional float optional_float = 11; + optional double optional_double = 12; + optional bool optional_bool = 13; + optional string optional_string = 14; + optional bytes optional_bytes = 15; + + optional NestedMessage optional_nested_message = 18; + optional ForeignMessageProto2 optional_foreign_message = 19; + + optional NestedEnum optional_nested_enum = 21; + optional ForeignEnumProto2 optional_foreign_enum = 22; + + optional string optional_string_piece = 24 [ctype=STRING_PIECE]; + optional string optional_cord = 25 [ctype=CORD]; + + optional TestAllTypesProto2 recursive_message = 27; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessageProto2 repeated_foreign_message = 49; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnumProto2 repeated_foreign_enum = 52; + + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; + repeated string repeated_cord = 55 [ctype=CORD]; + + // Map + map < int32, int32> map_int32_int32 = 56; + map < int64, int64> map_int64_int64 = 57; + map < uint32, uint32> map_uint32_uint32 = 58; + map < uint64, uint64> map_uint64_uint64 = 59; + map < sint32, sint32> map_sint32_sint32 = 60; + map < sint64, sint64> map_sint64_sint64 = 61; + map < fixed32, fixed32> map_fixed32_fixed32 = 62; + map < fixed64, fixed64> map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map < int32, float> map_int32_float = 66; + map < int32, double> map_int32_double = 67; + map < bool, bool> map_bool_bool = 68; + map < string, string> map_string_string = 69; + map < string, bytes> map_string_bytes = 70; + map < string, NestedMessage> map_string_nested_message = 71; + map < string, ForeignMessageProto2> map_string_foreign_message = 72; + map < string, NestedEnum> map_string_nested_enum = 73; + map < string, ForeignEnumProto2> map_string_foreign_enum = 74; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + bool oneof_bool = 115; + uint64 oneof_uint64 = 116; + float oneof_float = 117; + double oneof_double = 118; + NestedEnum oneof_enum = 119; + } + + // extensions + extensions 120 to 200; + + // groups + optional group Data = 201 { + optional int32 group_int32 = 202; + optional uint32 group_uint32 = 203; + }; + + // Test field-name-to-JSON-name convention. + // (protobuf says names can be any valid C/C++ identifier.) + optional int32 fieldname1 = 401; + optional int32 field_name2 = 402; + optional int32 _field_name3 = 403; + optional int32 field__name4_ = 404; + optional int32 field0name5 = 405; + optional int32 field_0_name6 = 406; + optional int32 fieldName7 = 407; + optional int32 FieldName8 = 408; + optional int32 field_Name9 = 409; + optional int32 Field_Name10 = 410; + optional int32 FIELD_NAME11 = 411; + optional int32 FIELD_name12 = 412; + optional int32 __field_name13 = 413; + optional int32 __Field_name14 = 414; + optional int32 field__name15 = 415; + optional int32 field__Name16 = 416; + optional int32 field_name17__ = 417; + optional int32 Field_name18__ = 418; + + // message_set test case. + message MessageSetCorrect { + option message_set_wire_format = true; + extensions 4 to max; + } + + message MessageSetCorrectExtension1 { + extend MessageSetCorrect { + optional MessageSetCorrectExtension1 message_set_extension = 1547769; + } + optional string str = 25; + } + + message MessageSetCorrectExtension2 { + extend MessageSetCorrect { + optional MessageSetCorrectExtension2 message_set_extension = 4135312; + } + optional int32 i = 9; + } +} + +message ForeignMessageProto2 { + optional int32 c = 1; +} + +enum ForeignEnumProto2 { + FOREIGN_FOO = 0; + FOREIGN_BAR = 1; + FOREIGN_BAZ = 2; +} + +extend TestAllTypesProto2 { + optional int32 extension_int32 = 120; +} diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_messages_proto3.proto b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_messages_proto3.proto new file mode 100644 index 000000000..4f295aac4 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_messages_proto3.proto @@ -0,0 +1,231 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. +// +// Test schema for proto3 messages. This test schema is used by: +// +// - benchmarks +// - fuzz tests +// - conformance tests +// + +syntax = "proto3"; + +package protobuf_test_messages.proto3; +option java_package = "com.google.protobuf_test_messages.proto3"; +option objc_class_prefix = "Proto3"; + +// This is the default, but we specify it here explicitly. +option optimize_for = SPEED; + +import "google/protobuf/any.proto"; +import "google/protobuf/duration.proto"; +import "google/protobuf/field_mask.proto"; +import "google/protobuf/struct.proto"; +import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; + +option cc_enable_arenas = true; + +// This proto includes every type of field in both singular and repeated +// forms. +// +// Also, crucially, all messages and enums in this file are eventually +// submessages of this message. So for example, a fuzz test of TestAllTypes +// could trigger bugs that occur in any message type in this file. We verify +// this stays true in a unit test. +message TestAllTypesProto3 { + message NestedMessage { + int32 a = 1; + TestAllTypesProto3 corecursive = 2; + } + + enum NestedEnum { + FOO = 0; + BAR = 1; + BAZ = 2; + NEG = -1; // Intentionally negative. + } + + // Singular + int32 optional_int32 = 1; + int64 optional_int64 = 2; + uint32 optional_uint32 = 3; + uint64 optional_uint64 = 4; + sint32 optional_sint32 = 5; + sint64 optional_sint64 = 6; + fixed32 optional_fixed32 = 7; + fixed64 optional_fixed64 = 8; + sfixed32 optional_sfixed32 = 9; + sfixed64 optional_sfixed64 = 10; + float optional_float = 11; + double optional_double = 12; + bool optional_bool = 13; + string optional_string = 14; + bytes optional_bytes = 15; + + NestedMessage optional_nested_message = 18; + ForeignMessage optional_foreign_message = 19; + + NestedEnum optional_nested_enum = 21; + ForeignEnum optional_foreign_enum = 22; + + string optional_string_piece = 24 [ctype=STRING_PIECE]; + string optional_cord = 25 [ctype=CORD]; + + TestAllTypesProto3 recursive_message = 27; + + // Repeated + repeated int32 repeated_int32 = 31; + repeated int64 repeated_int64 = 32; + repeated uint32 repeated_uint32 = 33; + repeated uint64 repeated_uint64 = 34; + repeated sint32 repeated_sint32 = 35; + repeated sint64 repeated_sint64 = 36; + repeated fixed32 repeated_fixed32 = 37; + repeated fixed64 repeated_fixed64 = 38; + repeated sfixed32 repeated_sfixed32 = 39; + repeated sfixed64 repeated_sfixed64 = 40; + repeated float repeated_float = 41; + repeated double repeated_double = 42; + repeated bool repeated_bool = 43; + repeated string repeated_string = 44; + repeated bytes repeated_bytes = 45; + + repeated NestedMessage repeated_nested_message = 48; + repeated ForeignMessage repeated_foreign_message = 49; + + repeated NestedEnum repeated_nested_enum = 51; + repeated ForeignEnum repeated_foreign_enum = 52; + + repeated string repeated_string_piece = 54 [ctype=STRING_PIECE]; + repeated string repeated_cord = 55 [ctype=CORD]; + + // Map + map < int32, int32> map_int32_int32 = 56; + map < int64, int64> map_int64_int64 = 57; + map < uint32, uint32> map_uint32_uint32 = 58; + map < uint64, uint64> map_uint64_uint64 = 59; + map < sint32, sint32> map_sint32_sint32 = 60; + map < sint64, sint64> map_sint64_sint64 = 61; + map < fixed32, fixed32> map_fixed32_fixed32 = 62; + map < fixed64, fixed64> map_fixed64_fixed64 = 63; + map map_sfixed32_sfixed32 = 64; + map map_sfixed64_sfixed64 = 65; + map < int32, float> map_int32_float = 66; + map < int32, double> map_int32_double = 67; + map < bool, bool> map_bool_bool = 68; + map < string, string> map_string_string = 69; + map < string, bytes> map_string_bytes = 70; + map < string, NestedMessage> map_string_nested_message = 71; + map < string, ForeignMessage> map_string_foreign_message = 72; + map < string, NestedEnum> map_string_nested_enum = 73; + map < string, ForeignEnum> map_string_foreign_enum = 74; + + oneof oneof_field { + uint32 oneof_uint32 = 111; + NestedMessage oneof_nested_message = 112; + string oneof_string = 113; + bytes oneof_bytes = 114; + bool oneof_bool = 115; + uint64 oneof_uint64 = 116; + float oneof_float = 117; + double oneof_double = 118; + NestedEnum oneof_enum = 119; + } + + // Well-known types + google.protobuf.BoolValue optional_bool_wrapper = 201; + google.protobuf.Int32Value optional_int32_wrapper = 202; + google.protobuf.Int64Value optional_int64_wrapper = 203; + google.protobuf.UInt32Value optional_uint32_wrapper = 204; + google.protobuf.UInt64Value optional_uint64_wrapper = 205; + google.protobuf.FloatValue optional_float_wrapper = 206; + google.protobuf.DoubleValue optional_double_wrapper = 207; + google.protobuf.StringValue optional_string_wrapper = 208; + google.protobuf.BytesValue optional_bytes_wrapper = 209; + + repeated google.protobuf.BoolValue repeated_bool_wrapper = 211; + repeated google.protobuf.Int32Value repeated_int32_wrapper = 212; + repeated google.protobuf.Int64Value repeated_int64_wrapper = 213; + repeated google.protobuf.UInt32Value repeated_uint32_wrapper = 214; + repeated google.protobuf.UInt64Value repeated_uint64_wrapper = 215; + repeated google.protobuf.FloatValue repeated_float_wrapper = 216; + repeated google.protobuf.DoubleValue repeated_double_wrapper = 217; + repeated google.protobuf.StringValue repeated_string_wrapper = 218; + repeated google.protobuf.BytesValue repeated_bytes_wrapper = 219; + + google.protobuf.Duration optional_duration = 301; + google.protobuf.Timestamp optional_timestamp = 302; + google.protobuf.FieldMask optional_field_mask = 303; + google.protobuf.Struct optional_struct = 304; + google.protobuf.Any optional_any = 305; + google.protobuf.Value optional_value = 306; + + repeated google.protobuf.Duration repeated_duration = 311; + repeated google.protobuf.Timestamp repeated_timestamp = 312; + repeated google.protobuf.FieldMask repeated_fieldmask = 313; + repeated google.protobuf.Struct repeated_struct = 324; + repeated google.protobuf.Any repeated_any = 315; + repeated google.protobuf.Value repeated_value = 316; + + // Test field-name-to-JSON-name convention. + // (protobuf says names can be any valid C/C++ identifier.) + int32 fieldname1 = 401; + int32 field_name2 = 402; + int32 _field_name3 = 403; + int32 field__name4_ = 404; + int32 field0name5 = 405; + int32 field_0_name6 = 406; + int32 fieldName7 = 407; + int32 FieldName8 = 408; + int32 field_Name9 = 409; + int32 Field_Name10 = 410; + int32 FIELD_NAME11 = 411; + int32 FIELD_name12 = 412; + int32 __field_name13 = 413; + int32 __Field_name14 = 414; + int32 field__name15 = 415; + int32 field__Name16 = 416; + int32 field_name17__ = 417; + int32 Field_name18__ = 418; + + // Reserved for testing unknown fields + reserved 501 to 510; +} + +message ForeignMessage { + int32 c = 1; +} + +enum ForeignEnum { + FOREIGN_FOO = 0; + FOREIGN_BAR = 1; + FOREIGN_BAZ = 2; +} diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util.cc new file mode 100644 index 000000000..795cb6ae1 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util.cc @@ -0,0 +1,47 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifdef _WIN32 +// Verify that #including windows.h does not break anything (e.g. because +// windows.h #defines GetMessage() as a macro). +#include +#endif + +#include + +namespace google { +namespace protobuf { + +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util.h new file mode 100644 index 000000000..b9abb6717 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util.h @@ -0,0 +1,1301 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. + +#ifndef GOOGLE_PROTOBUF_TEST_UTIL_H__ +#define GOOGLE_PROTOBUF_TEST_UTIL_H__ + +#include + +#define UNITTEST ::protobuf_unittest +#define UNITTEST_IMPORT ::protobuf_unittest_import +// Must be included when the preprocessor symbols above are defined. +#include +#undef UNITTEST +#undef UNITTEST_IMPORT + + +namespace google { +namespace protobuf { +// This file doesn't use these declarations, but some .cc files do. +namespace unittest = ::protobuf_unittest; +namespace unittest_import = ::protobuf_unittest_import; + +namespace TestUtil { + +class ReflectionTester { + public: + // base_descriptor must be a descriptor for TestAllTypes or + // TestAllExtensions. In the former case, ReflectionTester fetches from + // it the FieldDescriptors needed to use the reflection interface. In + // the latter case, ReflectionTester searches for extension fields in + // its file. + explicit ReflectionTester(const Descriptor* base_descriptor); + + void SetAllFieldsViaReflection(Message* message); + void ModifyRepeatedFieldsViaReflection(Message* message); + void ExpectAllFieldsSetViaReflection(const Message& message); + void ExpectClearViaReflection(const Message& message); + + void SetPackedFieldsViaReflection(Message* message); + void ModifyPackedFieldsViaReflection(Message* message); + void ExpectPackedFieldsSetViaReflection(const Message& message); + void ExpectPackedClearViaReflection(const Message& message); + + void RemoveLastRepeatedsViaReflection(Message* message); + void ReleaseLastRepeatedsViaReflection(Message* message, + bool expect_extensions_notnull); + void SwapRepeatedsViaReflection(Message* message); + void SetAllocatedOptionalMessageFieldsToNullViaReflection(Message* message); + static void SetAllocatedOptionalMessageFieldsToMessageViaReflection( + Message* from_message, Message* to_message); + + enum MessageReleaseState { + IS_NULL, + CAN_BE_NULL, + NOT_NULL, + }; + void ExpectMessagesReleasedViaReflection( + Message* message, MessageReleaseState expected_release_state); + + // Set and check functions for TestOneof2 messages. No need to construct + // the ReflectionTester by TestAllTypes nor TestAllExtensions. + static void SetOneofViaReflection(Message* message); + static void ExpectOneofSetViaReflection(const Message& message); + + private: + const FieldDescriptor* F(const string& name); + + const Descriptor* base_descriptor_; + + const FieldDescriptor* group_a_; + const FieldDescriptor* repeated_group_a_; + const FieldDescriptor* nested_b_; + const FieldDescriptor* foreign_c_; + const FieldDescriptor* import_d_; + const FieldDescriptor* import_e_; + + const EnumValueDescriptor* nested_foo_; + const EnumValueDescriptor* nested_bar_; + const EnumValueDescriptor* nested_baz_; + const EnumValueDescriptor* foreign_foo_; + const EnumValueDescriptor* foreign_bar_; + const EnumValueDescriptor* foreign_baz_; + const EnumValueDescriptor* import_foo_; + const EnumValueDescriptor* import_bar_; + const EnumValueDescriptor* import_baz_; + + // We have to split this into three function otherwise it creates a stack + // frame so large that it triggers a warning. + void ExpectAllFieldsSetViaReflection1(const Message& message); + void ExpectAllFieldsSetViaReflection2(const Message& message); + void ExpectAllFieldsSetViaReflection3(const Message& message); + + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionTester); +}; + +inline TestUtil::ReflectionTester::ReflectionTester( + const Descriptor* base_descriptor) + : base_descriptor_(base_descriptor) { + const DescriptorPool* pool = base_descriptor->file()->pool(); + string package = base_descriptor->file()->package(); + const FieldDescriptor* import_descriptor = + pool->FindFieldByName(package + ".TestAllTypes.optional_import_message"); + string import_package = import_descriptor->message_type()->file()->package(); + + nested_b_ = pool->FindFieldByName(package + ".TestAllTypes.NestedMessage.bb"); + foreign_c_ = pool->FindFieldByName(package + ".ForeignMessage.c"); + import_d_ = pool->FindFieldByName(import_package + ".ImportMessage.d"); + import_e_ = pool->FindFieldByName(import_package + ".PublicImportMessage.e"); + nested_foo_ = pool->FindEnumValueByName(package + ".TestAllTypes.FOO"); + nested_bar_ = pool->FindEnumValueByName(package + ".TestAllTypes.BAR"); + nested_baz_ = pool->FindEnumValueByName(package + ".TestAllTypes.BAZ"); + foreign_foo_ = pool->FindEnumValueByName(package + ".FOREIGN_FOO"); + foreign_bar_ = pool->FindEnumValueByName(package + ".FOREIGN_BAR"); + foreign_baz_ = pool->FindEnumValueByName(package + ".FOREIGN_BAZ"); + import_foo_ = pool->FindEnumValueByName(import_package + ".IMPORT_FOO"); + import_bar_ = pool->FindEnumValueByName(import_package + ".IMPORT_BAR"); + import_baz_ = pool->FindEnumValueByName(import_package + ".IMPORT_BAZ"); + + if (base_descriptor_->name() == "TestAllExtensions") { + group_a_ = pool->FindFieldByName(package + ".OptionalGroup_extension.a"); + repeated_group_a_ = + pool->FindFieldByName(package + ".RepeatedGroup_extension.a"); + } else { + group_a_ = pool->FindFieldByName(package + ".TestAllTypes.OptionalGroup.a"); + repeated_group_a_ = + pool->FindFieldByName(package + ".TestAllTypes.RepeatedGroup.a"); + } + + EXPECT_TRUE(group_a_ != nullptr); + EXPECT_TRUE(repeated_group_a_ != nullptr); + EXPECT_TRUE(nested_b_ != nullptr); + EXPECT_TRUE(foreign_c_ != nullptr); + EXPECT_TRUE(import_d_ != nullptr); + EXPECT_TRUE(import_e_ != nullptr); + EXPECT_TRUE(nested_foo_ != nullptr); + EXPECT_TRUE(nested_bar_ != nullptr); + EXPECT_TRUE(nested_baz_ != nullptr); + EXPECT_TRUE(foreign_foo_ != nullptr); + EXPECT_TRUE(foreign_bar_ != nullptr); + EXPECT_TRUE(foreign_baz_ != nullptr); + EXPECT_TRUE(import_foo_ != nullptr); + EXPECT_TRUE(import_bar_ != nullptr); + EXPECT_TRUE(import_baz_ != nullptr); +} + +// Shorthand to get a FieldDescriptor for a field of TestAllTypes. +inline const FieldDescriptor* TestUtil::ReflectionTester::F( + const string& name) { + const FieldDescriptor* result = nullptr; + if (base_descriptor_->name() == "TestAllExtensions" || + base_descriptor_->name() == "TestPackedExtensions") { + result = base_descriptor_->file()->FindExtensionByName(name + "_extension"); + } else { + result = base_descriptor_->FindFieldByName(name); + } + GOOGLE_CHECK(result != nullptr); + return result; +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ReflectionTester::SetAllFieldsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + Message* sub_message; + + reflection->SetInt32(message, F("optional_int32"), 101); + reflection->SetInt64(message, F("optional_int64"), 102); + reflection->SetUInt32(message, F("optional_uint32"), 103); + reflection->SetUInt64(message, F("optional_uint64"), 104); + reflection->SetInt32(message, F("optional_sint32"), 105); + reflection->SetInt64(message, F("optional_sint64"), 106); + reflection->SetUInt32(message, F("optional_fixed32"), 107); + reflection->SetUInt64(message, F("optional_fixed64"), 108); + reflection->SetInt32(message, F("optional_sfixed32"), 109); + reflection->SetInt64(message, F("optional_sfixed64"), 110); + reflection->SetFloat(message, F("optional_float"), 111); + reflection->SetDouble(message, F("optional_double"), 112); + reflection->SetBool(message, F("optional_bool"), true); + reflection->SetString(message, F("optional_string"), "115"); + reflection->SetString(message, F("optional_bytes"), "116"); + + sub_message = reflection->MutableMessage(message, F("optionalgroup")); + sub_message->GetReflection()->SetInt32(sub_message, group_a_, 117); + sub_message = + reflection->MutableMessage(message, F("optional_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 118); + sub_message = + reflection->MutableMessage(message, F("optional_foreign_message")); + sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 119); + sub_message = + reflection->MutableMessage(message, F("optional_import_message")); + sub_message->GetReflection()->SetInt32(sub_message, import_d_, 120); + + reflection->SetEnum(message, F("optional_nested_enum"), nested_baz_); + reflection->SetEnum(message, F("optional_foreign_enum"), foreign_baz_); + reflection->SetEnum(message, F("optional_import_enum"), import_baz_); + + reflection->SetString(message, F("optional_string_piece"), "124"); + reflection->SetString(message, F("optional_cord"), "125"); + + sub_message = + reflection->MutableMessage(message, F("optional_public_import_message")); + sub_message->GetReflection()->SetInt32(sub_message, import_e_, 126); + + sub_message = reflection->MutableMessage(message, F("optional_lazy_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 127); + + // ----------------------------------------------------------------- + + reflection->AddInt32(message, F("repeated_int32"), 201); + reflection->AddInt64(message, F("repeated_int64"), 202); + reflection->AddUInt32(message, F("repeated_uint32"), 203); + reflection->AddUInt64(message, F("repeated_uint64"), 204); + reflection->AddInt32(message, F("repeated_sint32"), 205); + reflection->AddInt64(message, F("repeated_sint64"), 206); + reflection->AddUInt32(message, F("repeated_fixed32"), 207); + reflection->AddUInt64(message, F("repeated_fixed64"), 208); + reflection->AddInt32(message, F("repeated_sfixed32"), 209); + reflection->AddInt64(message, F("repeated_sfixed64"), 210); + reflection->AddFloat(message, F("repeated_float"), 211); + reflection->AddDouble(message, F("repeated_double"), 212); + reflection->AddBool(message, F("repeated_bool"), true); + reflection->AddString(message, F("repeated_string"), "215"); + reflection->AddString(message, F("repeated_bytes"), "216"); + + sub_message = reflection->AddMessage(message, F("repeatedgroup")); + sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 217); + sub_message = reflection->AddMessage(message, F("repeated_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 218); + sub_message = reflection->AddMessage(message, F("repeated_foreign_message")); + sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 219); + sub_message = reflection->AddMessage(message, F("repeated_import_message")); + sub_message->GetReflection()->SetInt32(sub_message, import_d_, 220); + sub_message = reflection->AddMessage(message, F("repeated_lazy_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 227); + + reflection->AddEnum(message, F("repeated_nested_enum"), nested_bar_); + reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_bar_); + reflection->AddEnum(message, F("repeated_import_enum"), import_bar_); + + reflection->AddString(message, F("repeated_string_piece"), "224"); + reflection->AddString(message, F("repeated_cord"), "225"); + + // Add a second one of each field. + reflection->AddInt32(message, F("repeated_int32"), 301); + reflection->AddInt64(message, F("repeated_int64"), 302); + reflection->AddUInt32(message, F("repeated_uint32"), 303); + reflection->AddUInt64(message, F("repeated_uint64"), 304); + reflection->AddInt32(message, F("repeated_sint32"), 305); + reflection->AddInt64(message, F("repeated_sint64"), 306); + reflection->AddUInt32(message, F("repeated_fixed32"), 307); + reflection->AddUInt64(message, F("repeated_fixed64"), 308); + reflection->AddInt32(message, F("repeated_sfixed32"), 309); + reflection->AddInt64(message, F("repeated_sfixed64"), 310); + reflection->AddFloat(message, F("repeated_float"), 311); + reflection->AddDouble(message, F("repeated_double"), 312); + reflection->AddBool(message, F("repeated_bool"), false); + reflection->AddString(message, F("repeated_string"), "315"); + reflection->AddString(message, F("repeated_bytes"), "316"); + + sub_message = reflection->AddMessage(message, F("repeatedgroup")); + sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 317); + sub_message = reflection->AddMessage(message, F("repeated_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 318); + sub_message = reflection->AddMessage(message, F("repeated_foreign_message")); + sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 319); + sub_message = reflection->AddMessage(message, F("repeated_import_message")); + sub_message->GetReflection()->SetInt32(sub_message, import_d_, 320); + sub_message = reflection->AddMessage(message, F("repeated_lazy_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 327); + + reflection->AddEnum(message, F("repeated_nested_enum"), nested_baz_); + reflection->AddEnum(message, F("repeated_foreign_enum"), foreign_baz_); + reflection->AddEnum(message, F("repeated_import_enum"), import_baz_); + + reflection->AddString(message, F("repeated_string_piece"), "324"); + reflection->AddString(message, F("repeated_cord"), "325"); + + // ----------------------------------------------------------------- + + reflection->SetInt32(message, F("default_int32"), 401); + reflection->SetInt64(message, F("default_int64"), 402); + reflection->SetUInt32(message, F("default_uint32"), 403); + reflection->SetUInt64(message, F("default_uint64"), 404); + reflection->SetInt32(message, F("default_sint32"), 405); + reflection->SetInt64(message, F("default_sint64"), 406); + reflection->SetUInt32(message, F("default_fixed32"), 407); + reflection->SetUInt64(message, F("default_fixed64"), 408); + reflection->SetInt32(message, F("default_sfixed32"), 409); + reflection->SetInt64(message, F("default_sfixed64"), 410); + reflection->SetFloat(message, F("default_float"), 411); + reflection->SetDouble(message, F("default_double"), 412); + reflection->SetBool(message, F("default_bool"), false); + reflection->SetString(message, F("default_string"), "415"); + reflection->SetString(message, F("default_bytes"), "416"); + + reflection->SetEnum(message, F("default_nested_enum"), nested_foo_); + reflection->SetEnum(message, F("default_foreign_enum"), foreign_foo_); + reflection->SetEnum(message, F("default_import_enum"), import_foo_); + + reflection->SetString(message, F("default_string_piece"), "424"); + reflection->SetString(message, F("default_cord"), "425"); + + reflection->SetUInt32(message, F("oneof_uint32"), 601); + sub_message = reflection->MutableMessage(message, F("oneof_nested_message")); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 602); + reflection->SetString(message, F("oneof_string"), "603"); + reflection->SetString(message, F("oneof_bytes"), "604"); +} + +inline void TestUtil::ReflectionTester::SetOneofViaReflection( + Message* message) { + const Descriptor* descriptor = message->GetDescriptor(); + const Reflection* reflection = message->GetReflection(); + Message* sub_message = reflection->MutableMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + sub_message->GetReflection()->SetInt64( + sub_message, sub_message->GetDescriptor()->FindFieldByName("qux_int"), + 100); + + reflection->SetString(message, descriptor->FindFieldByName("bar_cord"), + "101"); + reflection->SetInt32(message, descriptor->FindFieldByName("baz_int"), 102); + reflection->SetString(message, descriptor->FindFieldByName("baz_string"), + "103"); +} + +inline void TestUtil::ReflectionTester::ExpectOneofSetViaReflection( + const Message& message) { + const Descriptor* descriptor = message.GetDescriptor(); + const Reflection* reflection = message.GetReflection(); + string scratch; + EXPECT_TRUE(reflection->HasField( + message, descriptor->FindFieldByName("foo_lazy_message"))); + EXPECT_TRUE( + reflection->HasField(message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_TRUE( + reflection->HasField(message, descriptor->FindFieldByName("baz_int"))); + EXPECT_TRUE( + reflection->HasField(message, descriptor->FindFieldByName("baz_string"))); + + const Message* sub_message = &reflection->GetMessage( + message, descriptor->FindFieldByName("foo_lazy_message")); + EXPECT_EQ(100, sub_message->GetReflection()->GetInt64( + *sub_message, + sub_message->GetDescriptor()->FindFieldByName("qux_int"))); + + EXPECT_EQ("101", reflection->GetString( + message, descriptor->FindFieldByName("bar_cord"))); + EXPECT_EQ("101", + reflection->GetStringReference( + message, descriptor->FindFieldByName("bar_cord"), &scratch)); + + EXPECT_EQ(102, reflection->GetInt32(message, + descriptor->FindFieldByName("baz_int"))); + + EXPECT_EQ("103", reflection->GetString( + message, descriptor->FindFieldByName("baz_string"))); + EXPECT_EQ("103", + reflection->GetStringReference( + message, descriptor->FindFieldByName("baz_string"), &scratch)); +} + +inline void TestUtil::ReflectionTester::SetPackedFieldsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + reflection->AddInt32(message, F("packed_int32"), 601); + reflection->AddInt64(message, F("packed_int64"), 602); + reflection->AddUInt32(message, F("packed_uint32"), 603); + reflection->AddUInt64(message, F("packed_uint64"), 604); + reflection->AddInt32(message, F("packed_sint32"), 605); + reflection->AddInt64(message, F("packed_sint64"), 606); + reflection->AddUInt32(message, F("packed_fixed32"), 607); + reflection->AddUInt64(message, F("packed_fixed64"), 608); + reflection->AddInt32(message, F("packed_sfixed32"), 609); + reflection->AddInt64(message, F("packed_sfixed64"), 610); + reflection->AddFloat(message, F("packed_float"), 611); + reflection->AddDouble(message, F("packed_double"), 612); + reflection->AddBool(message, F("packed_bool"), true); + reflection->AddEnum(message, F("packed_enum"), foreign_bar_); + + reflection->AddInt32(message, F("packed_int32"), 701); + reflection->AddInt64(message, F("packed_int64"), 702); + reflection->AddUInt32(message, F("packed_uint32"), 703); + reflection->AddUInt64(message, F("packed_uint64"), 704); + reflection->AddInt32(message, F("packed_sint32"), 705); + reflection->AddInt64(message, F("packed_sint64"), 706); + reflection->AddUInt32(message, F("packed_fixed32"), 707); + reflection->AddUInt64(message, F("packed_fixed64"), 708); + reflection->AddInt32(message, F("packed_sfixed32"), 709); + reflection->AddInt64(message, F("packed_sfixed64"), 710); + reflection->AddFloat(message, F("packed_float"), 711); + reflection->AddDouble(message, F("packed_double"), 712); + reflection->AddBool(message, F("packed_bool"), false); + reflection->AddEnum(message, F("packed_enum"), foreign_baz_); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection( + const Message& message) { + // We have to split this into three function otherwise it creates a stack + // frame so large that it triggers a warning. + ExpectAllFieldsSetViaReflection1(message); + ExpectAllFieldsSetViaReflection2(message); + ExpectAllFieldsSetViaReflection3(message); +} + +inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection1( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + string scratch; + const Message* sub_message; + + EXPECT_TRUE(reflection->HasField(message, F("optional_int32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_int64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_uint32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_uint64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_sint32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_sint64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_fixed32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_fixed64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_sfixed32"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_sfixed64"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_float"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_double"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_bool"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_string"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_bytes"))); + + EXPECT_TRUE(reflection->HasField(message, F("optionalgroup"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_nested_message"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_message"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_import_message"))); + EXPECT_TRUE( + reflection->HasField(message, F("optional_public_import_message"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_lazy_message"))); + + sub_message = &reflection->GetMessage(message, F("optionalgroup")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, group_a_)); + sub_message = &reflection->GetMessage(message, F("optional_nested_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); + sub_message = &reflection->GetMessage(message, F("optional_foreign_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, foreign_c_)); + sub_message = &reflection->GetMessage(message, F("optional_import_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_d_)); + sub_message = + &reflection->GetMessage(message, F("optional_public_import_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, import_e_)); + sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); + EXPECT_TRUE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); + + EXPECT_TRUE(reflection->HasField(message, F("optional_nested_enum"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_foreign_enum"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_import_enum"))); + + EXPECT_TRUE(reflection->HasField(message, F("optional_string_piece"))); + EXPECT_TRUE(reflection->HasField(message, F("optional_cord"))); + + EXPECT_EQ(101, reflection->GetInt32(message, F("optional_int32"))); + EXPECT_EQ(102, reflection->GetInt64(message, F("optional_int64"))); + EXPECT_EQ(103, reflection->GetUInt32(message, F("optional_uint32"))); + EXPECT_EQ(104, reflection->GetUInt64(message, F("optional_uint64"))); + EXPECT_EQ(105, reflection->GetInt32(message, F("optional_sint32"))); + EXPECT_EQ(106, reflection->GetInt64(message, F("optional_sint64"))); + EXPECT_EQ(107, reflection->GetUInt32(message, F("optional_fixed32"))); + EXPECT_EQ(108, reflection->GetUInt64(message, F("optional_fixed64"))); + EXPECT_EQ(109, reflection->GetInt32(message, F("optional_sfixed32"))); + EXPECT_EQ(110, reflection->GetInt64(message, F("optional_sfixed64"))); + EXPECT_EQ(111, reflection->GetFloat(message, F("optional_float"))); + EXPECT_EQ(112, reflection->GetDouble(message, F("optional_double"))); + EXPECT_TRUE(reflection->GetBool(message, F("optional_bool"))); + EXPECT_EQ("115", reflection->GetString(message, F("optional_string"))); + EXPECT_EQ("116", reflection->GetString(message, F("optional_bytes"))); + + EXPECT_EQ("115", reflection->GetStringReference(message, F("optional_string"), + &scratch)); + EXPECT_EQ("116", reflection->GetStringReference(message, F("optional_bytes"), + &scratch)); + + sub_message = &reflection->GetMessage(message, F("optionalgroup")); + EXPECT_EQ(117, + sub_message->GetReflection()->GetInt32(*sub_message, group_a_)); + sub_message = &reflection->GetMessage(message, F("optional_nested_message")); + EXPECT_EQ(118, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + sub_message = &reflection->GetMessage(message, F("optional_foreign_message")); + EXPECT_EQ(119, + sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); + sub_message = &reflection->GetMessage(message, F("optional_import_message")); + EXPECT_EQ(120, + sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = + &reflection->GetMessage(message, F("optional_public_import_message")); + EXPECT_EQ(126, + sub_message->GetReflection()->GetInt32(*sub_message, import_e_)); + sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); + EXPECT_EQ(127, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + + EXPECT_EQ(nested_baz_, + reflection->GetEnum(message, F("optional_nested_enum"))); + EXPECT_EQ(foreign_baz_, + reflection->GetEnum(message, F("optional_foreign_enum"))); + EXPECT_EQ(import_baz_, + reflection->GetEnum(message, F("optional_import_enum"))); + + EXPECT_EQ("124", reflection->GetString(message, F("optional_string_piece"))); + EXPECT_EQ("124", reflection->GetStringReference( + message, F("optional_string_piece"), &scratch)); + + EXPECT_EQ("125", reflection->GetString(message, F("optional_cord"))); + EXPECT_EQ("125", reflection->GetStringReference(message, F("optional_cord"), + &scratch)); + + EXPECT_TRUE(reflection->HasField(message, F("oneof_bytes"))); + EXPECT_EQ("604", reflection->GetString(message, F("oneof_bytes"))); + + if (base_descriptor_->name() == "TestAllTypes") { + EXPECT_FALSE(reflection->HasField(message, F("oneof_uint32"))); + EXPECT_FALSE(reflection->HasField(message, F("oneof_string"))); + } else { + EXPECT_TRUE(reflection->HasField(message, F("oneof_uint32"))); + EXPECT_TRUE(reflection->HasField(message, F("oneof_string"))); + EXPECT_EQ(601, reflection->GetUInt32(message, F("oneof_uint32"))); + EXPECT_EQ("603", reflection->GetString(message, F("oneof_string"))); + sub_message = &reflection->GetMessage(message, F("oneof_nested_message")); + EXPECT_EQ(602, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + } +} + +inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection2( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + string scratch; + const Message* sub_message; + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_int32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_int64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_uint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_uint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_fixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_fixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sfixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_sfixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_float"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_double"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_bool"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_string"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_bytes"))); + + ASSERT_EQ(2, reflection->FieldSize(message, F("repeatedgroup"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_message"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_message"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_message"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_lazy_message"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_nested_enum"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_foreign_enum"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_import_enum"))); + + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_string_piece"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("repeated_cord"))); + + EXPECT_EQ(201, reflection->GetRepeatedInt32(message, F("repeated_int32"), 0)); + EXPECT_EQ(202, reflection->GetRepeatedInt64(message, F("repeated_int64"), 0)); + EXPECT_EQ(203, + reflection->GetRepeatedUInt32(message, F("repeated_uint32"), 0)); + EXPECT_EQ(204, + reflection->GetRepeatedUInt64(message, F("repeated_uint64"), 0)); + EXPECT_EQ(205, + reflection->GetRepeatedInt32(message, F("repeated_sint32"), 0)); + EXPECT_EQ(206, + reflection->GetRepeatedInt64(message, F("repeated_sint64"), 0)); + EXPECT_EQ(207, + reflection->GetRepeatedUInt32(message, F("repeated_fixed32"), 0)); + EXPECT_EQ(208, + reflection->GetRepeatedUInt64(message, F("repeated_fixed64"), 0)); + EXPECT_EQ(209, + reflection->GetRepeatedInt32(message, F("repeated_sfixed32"), 0)); + EXPECT_EQ(210, + reflection->GetRepeatedInt64(message, F("repeated_sfixed64"), 0)); + EXPECT_EQ(211, reflection->GetRepeatedFloat(message, F("repeated_float"), 0)); + EXPECT_EQ(212, + reflection->GetRepeatedDouble(message, F("repeated_double"), 0)); + EXPECT_TRUE(reflection->GetRepeatedBool(message, F("repeated_bool"), 0)); + EXPECT_EQ("215", + reflection->GetRepeatedString(message, F("repeated_string"), 0)); + EXPECT_EQ("216", + reflection->GetRepeatedString(message, F("repeated_bytes"), 0)); + + EXPECT_EQ("215", reflection->GetRepeatedStringReference( + message, F("repeated_string"), 0, &scratch)); + EXPECT_EQ("216", reflection->GetRepeatedStringReference( + message, F("repeated_bytes"), 0, &scratch)); + + sub_message = &reflection->GetRepeatedMessage(message, F("repeatedgroup"), 0); + EXPECT_EQ(217, sub_message->GetReflection()->GetInt32(*sub_message, + repeated_group_a_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_nested_message"), 0); + EXPECT_EQ(218, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + sub_message = &reflection->GetRepeatedMessage( + message, F("repeated_foreign_message"), 0); + EXPECT_EQ(219, + sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 0); + EXPECT_EQ(220, + sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 0); + EXPECT_EQ(227, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + + EXPECT_EQ(nested_bar_, + reflection->GetRepeatedEnum(message, F("repeated_nested_enum"), 0)); + EXPECT_EQ(foreign_bar_, reflection->GetRepeatedEnum( + message, F("repeated_foreign_enum"), 0)); + EXPECT_EQ(import_bar_, + reflection->GetRepeatedEnum(message, F("repeated_import_enum"), 0)); + + EXPECT_EQ("224", reflection->GetRepeatedString( + message, F("repeated_string_piece"), 0)); + EXPECT_EQ("224", reflection->GetRepeatedStringReference( + message, F("repeated_string_piece"), 0, &scratch)); + + EXPECT_EQ("225", + reflection->GetRepeatedString(message, F("repeated_cord"), 0)); + EXPECT_EQ("225", reflection->GetRepeatedStringReference( + message, F("repeated_cord"), 0, &scratch)); + + EXPECT_EQ(301, reflection->GetRepeatedInt32(message, F("repeated_int32"), 1)); + EXPECT_EQ(302, reflection->GetRepeatedInt64(message, F("repeated_int64"), 1)); + EXPECT_EQ(303, + reflection->GetRepeatedUInt32(message, F("repeated_uint32"), 1)); + EXPECT_EQ(304, + reflection->GetRepeatedUInt64(message, F("repeated_uint64"), 1)); + EXPECT_EQ(305, + reflection->GetRepeatedInt32(message, F("repeated_sint32"), 1)); + EXPECT_EQ(306, + reflection->GetRepeatedInt64(message, F("repeated_sint64"), 1)); + EXPECT_EQ(307, + reflection->GetRepeatedUInt32(message, F("repeated_fixed32"), 1)); + EXPECT_EQ(308, + reflection->GetRepeatedUInt64(message, F("repeated_fixed64"), 1)); + EXPECT_EQ(309, + reflection->GetRepeatedInt32(message, F("repeated_sfixed32"), 1)); + EXPECT_EQ(310, + reflection->GetRepeatedInt64(message, F("repeated_sfixed64"), 1)); + EXPECT_EQ(311, reflection->GetRepeatedFloat(message, F("repeated_float"), 1)); + EXPECT_EQ(312, + reflection->GetRepeatedDouble(message, F("repeated_double"), 1)); + EXPECT_FALSE(reflection->GetRepeatedBool(message, F("repeated_bool"), 1)); + EXPECT_EQ("315", + reflection->GetRepeatedString(message, F("repeated_string"), 1)); + EXPECT_EQ("316", + reflection->GetRepeatedString(message, F("repeated_bytes"), 1)); + + EXPECT_EQ("315", reflection->GetRepeatedStringReference( + message, F("repeated_string"), 1, &scratch)); + EXPECT_EQ("316", reflection->GetRepeatedStringReference( + message, F("repeated_bytes"), 1, &scratch)); + + sub_message = &reflection->GetRepeatedMessage(message, F("repeatedgroup"), 1); + EXPECT_EQ(317, sub_message->GetReflection()->GetInt32(*sub_message, + repeated_group_a_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_nested_message"), 1); + EXPECT_EQ(318, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + sub_message = &reflection->GetRepeatedMessage( + message, F("repeated_foreign_message"), 1); + EXPECT_EQ(319, + sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_import_message"), 1); + EXPECT_EQ(320, + sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = + &reflection->GetRepeatedMessage(message, F("repeated_lazy_message"), 1); + EXPECT_EQ(327, + sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + + EXPECT_EQ(nested_baz_, + reflection->GetRepeatedEnum(message, F("repeated_nested_enum"), 1)); + EXPECT_EQ(foreign_baz_, reflection->GetRepeatedEnum( + message, F("repeated_foreign_enum"), 1)); + EXPECT_EQ(import_baz_, + reflection->GetRepeatedEnum(message, F("repeated_import_enum"), 1)); + + EXPECT_EQ("324", reflection->GetRepeatedString( + message, F("repeated_string_piece"), 1)); + EXPECT_EQ("324", reflection->GetRepeatedStringReference( + message, F("repeated_string_piece"), 1, &scratch)); + + EXPECT_EQ("325", + reflection->GetRepeatedString(message, F("repeated_cord"), 1)); + EXPECT_EQ("325", reflection->GetRepeatedStringReference( + message, F("repeated_cord"), 1, &scratch)); +} + +inline void TestUtil::ReflectionTester::ExpectAllFieldsSetViaReflection3( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + string scratch; + + // ----------------------------------------------------------------- + + EXPECT_TRUE(reflection->HasField(message, F("default_int32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_int64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_uint32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_uint64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_sint32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_sint64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_fixed32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_fixed64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_sfixed32"))); + EXPECT_TRUE(reflection->HasField(message, F("default_sfixed64"))); + EXPECT_TRUE(reflection->HasField(message, F("default_float"))); + EXPECT_TRUE(reflection->HasField(message, F("default_double"))); + EXPECT_TRUE(reflection->HasField(message, F("default_bool"))); + EXPECT_TRUE(reflection->HasField(message, F("default_string"))); + EXPECT_TRUE(reflection->HasField(message, F("default_bytes"))); + + EXPECT_TRUE(reflection->HasField(message, F("default_nested_enum"))); + EXPECT_TRUE(reflection->HasField(message, F("default_foreign_enum"))); + EXPECT_TRUE(reflection->HasField(message, F("default_import_enum"))); + + EXPECT_TRUE(reflection->HasField(message, F("default_string_piece"))); + EXPECT_TRUE(reflection->HasField(message, F("default_cord"))); + + EXPECT_EQ(401, reflection->GetInt32(message, F("default_int32"))); + EXPECT_EQ(402, reflection->GetInt64(message, F("default_int64"))); + EXPECT_EQ(403, reflection->GetUInt32(message, F("default_uint32"))); + EXPECT_EQ(404, reflection->GetUInt64(message, F("default_uint64"))); + EXPECT_EQ(405, reflection->GetInt32(message, F("default_sint32"))); + EXPECT_EQ(406, reflection->GetInt64(message, F("default_sint64"))); + EXPECT_EQ(407, reflection->GetUInt32(message, F("default_fixed32"))); + EXPECT_EQ(408, reflection->GetUInt64(message, F("default_fixed64"))); + EXPECT_EQ(409, reflection->GetInt32(message, F("default_sfixed32"))); + EXPECT_EQ(410, reflection->GetInt64(message, F("default_sfixed64"))); + EXPECT_EQ(411, reflection->GetFloat(message, F("default_float"))); + EXPECT_EQ(412, reflection->GetDouble(message, F("default_double"))); + EXPECT_FALSE(reflection->GetBool(message, F("default_bool"))); + EXPECT_EQ("415", reflection->GetString(message, F("default_string"))); + EXPECT_EQ("416", reflection->GetString(message, F("default_bytes"))); + + EXPECT_EQ("415", reflection->GetStringReference(message, F("default_string"), + &scratch)); + EXPECT_EQ("416", reflection->GetStringReference(message, F("default_bytes"), + &scratch)); + + EXPECT_EQ(nested_foo_, + reflection->GetEnum(message, F("default_nested_enum"))); + EXPECT_EQ(foreign_foo_, + reflection->GetEnum(message, F("default_foreign_enum"))); + EXPECT_EQ(import_foo_, + reflection->GetEnum(message, F("default_import_enum"))); + + EXPECT_EQ("424", reflection->GetString(message, F("default_string_piece"))); + EXPECT_EQ("424", reflection->GetStringReference( + message, F("default_string_piece"), &scratch)); + + EXPECT_EQ("425", reflection->GetString(message, F("default_cord"))); + EXPECT_EQ("425", reflection->GetStringReference(message, F("default_cord"), + &scratch)); +} + +inline void TestUtil::ReflectionTester::ExpectPackedFieldsSetViaReflection( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_int64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_uint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sint64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_fixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed32"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_sfixed64"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_float"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_double"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_bool"))); + ASSERT_EQ(2, reflection->FieldSize(message, F("packed_enum"))); + + EXPECT_EQ(601, reflection->GetRepeatedInt32(message, F("packed_int32"), 0)); + EXPECT_EQ(602, reflection->GetRepeatedInt64(message, F("packed_int64"), 0)); + EXPECT_EQ(603, reflection->GetRepeatedUInt32(message, F("packed_uint32"), 0)); + EXPECT_EQ(604, reflection->GetRepeatedUInt64(message, F("packed_uint64"), 0)); + EXPECT_EQ(605, reflection->GetRepeatedInt32(message, F("packed_sint32"), 0)); + EXPECT_EQ(606, reflection->GetRepeatedInt64(message, F("packed_sint64"), 0)); + EXPECT_EQ(607, + reflection->GetRepeatedUInt32(message, F("packed_fixed32"), 0)); + EXPECT_EQ(608, + reflection->GetRepeatedUInt64(message, F("packed_fixed64"), 0)); + EXPECT_EQ(609, + reflection->GetRepeatedInt32(message, F("packed_sfixed32"), 0)); + EXPECT_EQ(610, + reflection->GetRepeatedInt64(message, F("packed_sfixed64"), 0)); + EXPECT_EQ(611, reflection->GetRepeatedFloat(message, F("packed_float"), 0)); + EXPECT_EQ(612, reflection->GetRepeatedDouble(message, F("packed_double"), 0)); + EXPECT_TRUE(reflection->GetRepeatedBool(message, F("packed_bool"), 0)); + EXPECT_EQ(foreign_bar_, + reflection->GetRepeatedEnum(message, F("packed_enum"), 0)); + + EXPECT_EQ(701, reflection->GetRepeatedInt32(message, F("packed_int32"), 1)); + EXPECT_EQ(702, reflection->GetRepeatedInt64(message, F("packed_int64"), 1)); + EXPECT_EQ(703, reflection->GetRepeatedUInt32(message, F("packed_uint32"), 1)); + EXPECT_EQ(704, reflection->GetRepeatedUInt64(message, F("packed_uint64"), 1)); + EXPECT_EQ(705, reflection->GetRepeatedInt32(message, F("packed_sint32"), 1)); + EXPECT_EQ(706, reflection->GetRepeatedInt64(message, F("packed_sint64"), 1)); + EXPECT_EQ(707, + reflection->GetRepeatedUInt32(message, F("packed_fixed32"), 1)); + EXPECT_EQ(708, + reflection->GetRepeatedUInt64(message, F("packed_fixed64"), 1)); + EXPECT_EQ(709, + reflection->GetRepeatedInt32(message, F("packed_sfixed32"), 1)); + EXPECT_EQ(710, + reflection->GetRepeatedInt64(message, F("packed_sfixed64"), 1)); + EXPECT_EQ(711, reflection->GetRepeatedFloat(message, F("packed_float"), 1)); + EXPECT_EQ(712, reflection->GetRepeatedDouble(message, F("packed_double"), 1)); + EXPECT_FALSE(reflection->GetRepeatedBool(message, F("packed_bool"), 1)); + EXPECT_EQ(foreign_baz_, + reflection->GetRepeatedEnum(message, F("packed_enum"), 1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ReflectionTester::ExpectClearViaReflection( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + string scratch; + const Message* sub_message; + + // has_blah() should initially be false for all optional fields. + EXPECT_FALSE(reflection->HasField(message, F("optional_int32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_int64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_uint32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_uint64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_sint32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_sint64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_fixed32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_fixed64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_sfixed32"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_sfixed64"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_float"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_double"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_bool"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_string"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_bytes"))); + + EXPECT_FALSE(reflection->HasField(message, F("optionalgroup"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_nested_message"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_message"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_import_message"))); + EXPECT_FALSE( + reflection->HasField(message, F("optional_public_import_message"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_lazy_message"))); + + EXPECT_FALSE(reflection->HasField(message, F("optional_nested_enum"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_foreign_enum"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_import_enum"))); + + EXPECT_FALSE(reflection->HasField(message, F("optional_string_piece"))); + EXPECT_FALSE(reflection->HasField(message, F("optional_cord"))); + + // Optional fields without defaults are set to zero or something like it. + EXPECT_EQ(0, reflection->GetInt32(message, F("optional_int32"))); + EXPECT_EQ(0, reflection->GetInt64(message, F("optional_int64"))); + EXPECT_EQ(0, reflection->GetUInt32(message, F("optional_uint32"))); + EXPECT_EQ(0, reflection->GetUInt64(message, F("optional_uint64"))); + EXPECT_EQ(0, reflection->GetInt32(message, F("optional_sint32"))); + EXPECT_EQ(0, reflection->GetInt64(message, F("optional_sint64"))); + EXPECT_EQ(0, reflection->GetUInt32(message, F("optional_fixed32"))); + EXPECT_EQ(0, reflection->GetUInt64(message, F("optional_fixed64"))); + EXPECT_EQ(0, reflection->GetInt32(message, F("optional_sfixed32"))); + EXPECT_EQ(0, reflection->GetInt64(message, F("optional_sfixed64"))); + EXPECT_EQ(0, reflection->GetFloat(message, F("optional_float"))); + EXPECT_EQ(0, reflection->GetDouble(message, F("optional_double"))); + EXPECT_FALSE(reflection->GetBool(message, F("optional_bool"))); + EXPECT_EQ("", reflection->GetString(message, F("optional_string"))); + EXPECT_EQ("", reflection->GetString(message, F("optional_bytes"))); + + EXPECT_EQ("", reflection->GetStringReference(message, F("optional_string"), + &scratch)); + EXPECT_EQ("", reflection->GetStringReference(message, F("optional_bytes"), + &scratch)); + + // Embedded messages should also be clear. + sub_message = &reflection->GetMessage(message, F("optionalgroup")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, group_a_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, group_a_)); + sub_message = &reflection->GetMessage(message, F("optional_nested_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + sub_message = &reflection->GetMessage(message, F("optional_foreign_message")); + EXPECT_FALSE( + sub_message->GetReflection()->HasField(*sub_message, foreign_c_)); + EXPECT_EQ(0, + sub_message->GetReflection()->GetInt32(*sub_message, foreign_c_)); + sub_message = &reflection->GetMessage(message, F("optional_import_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_d_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_d_)); + sub_message = + &reflection->GetMessage(message, F("optional_public_import_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, import_e_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, import_e_)); + sub_message = &reflection->GetMessage(message, F("optional_lazy_message")); + EXPECT_FALSE(sub_message->GetReflection()->HasField(*sub_message, nested_b_)); + EXPECT_EQ(0, sub_message->GetReflection()->GetInt32(*sub_message, nested_b_)); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(nested_foo_, + reflection->GetEnum(message, F("optional_nested_enum"))); + EXPECT_EQ(foreign_foo_, + reflection->GetEnum(message, F("optional_foreign_enum"))); + EXPECT_EQ(import_foo_, + reflection->GetEnum(message, F("optional_import_enum"))); + + EXPECT_EQ("", reflection->GetString(message, F("optional_string_piece"))); + EXPECT_EQ("", reflection->GetStringReference( + message, F("optional_string_piece"), &scratch)); + + EXPECT_EQ("", reflection->GetString(message, F("optional_cord"))); + EXPECT_EQ("", reflection->GetStringReference(message, F("optional_cord"), + &scratch)); + + // Repeated fields are empty. + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_int64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_uint32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_uint64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sint32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sint64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_fixed32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_fixed64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sfixed32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_sfixed64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_float"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_double"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_bool"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_string"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_bytes"))); + + EXPECT_EQ(0, reflection->FieldSize(message, F("repeatedgroup"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_message"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_message"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_message"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_lazy_message"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_nested_enum"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_foreign_enum"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_import_enum"))); + + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_string_piece"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("repeated_cord"))); + + // has_blah() should also be false for all default fields. + EXPECT_FALSE(reflection->HasField(message, F("default_int32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_int64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_uint32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_uint64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_sint32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_sint64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_fixed32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_fixed64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_sfixed32"))); + EXPECT_FALSE(reflection->HasField(message, F("default_sfixed64"))); + EXPECT_FALSE(reflection->HasField(message, F("default_float"))); + EXPECT_FALSE(reflection->HasField(message, F("default_double"))); + EXPECT_FALSE(reflection->HasField(message, F("default_bool"))); + EXPECT_FALSE(reflection->HasField(message, F("default_string"))); + EXPECT_FALSE(reflection->HasField(message, F("default_bytes"))); + + EXPECT_FALSE(reflection->HasField(message, F("default_nested_enum"))); + EXPECT_FALSE(reflection->HasField(message, F("default_foreign_enum"))); + EXPECT_FALSE(reflection->HasField(message, F("default_import_enum"))); + + EXPECT_FALSE(reflection->HasField(message, F("default_string_piece"))); + EXPECT_FALSE(reflection->HasField(message, F("default_cord"))); + + // Fields with defaults have their default values (duh). + EXPECT_EQ(41, reflection->GetInt32(message, F("default_int32"))); + EXPECT_EQ(42, reflection->GetInt64(message, F("default_int64"))); + EXPECT_EQ(43, reflection->GetUInt32(message, F("default_uint32"))); + EXPECT_EQ(44, reflection->GetUInt64(message, F("default_uint64"))); + EXPECT_EQ(-45, reflection->GetInt32(message, F("default_sint32"))); + EXPECT_EQ(46, reflection->GetInt64(message, F("default_sint64"))); + EXPECT_EQ(47, reflection->GetUInt32(message, F("default_fixed32"))); + EXPECT_EQ(48, reflection->GetUInt64(message, F("default_fixed64"))); + EXPECT_EQ(49, reflection->GetInt32(message, F("default_sfixed32"))); + EXPECT_EQ(-50, reflection->GetInt64(message, F("default_sfixed64"))); + EXPECT_EQ(51.5, reflection->GetFloat(message, F("default_float"))); + EXPECT_EQ(52e3, reflection->GetDouble(message, F("default_double"))); + EXPECT_TRUE(reflection->GetBool(message, F("default_bool"))); + EXPECT_EQ("hello", reflection->GetString(message, F("default_string"))); + EXPECT_EQ("world", reflection->GetString(message, F("default_bytes"))); + + EXPECT_EQ("hello", reflection->GetStringReference( + message, F("default_string"), &scratch)); + EXPECT_EQ("world", reflection->GetStringReference(message, F("default_bytes"), + &scratch)); + + EXPECT_EQ(nested_bar_, + reflection->GetEnum(message, F("default_nested_enum"))); + EXPECT_EQ(foreign_bar_, + reflection->GetEnum(message, F("default_foreign_enum"))); + EXPECT_EQ(import_bar_, + reflection->GetEnum(message, F("default_import_enum"))); + + EXPECT_EQ("abc", reflection->GetString(message, F("default_string_piece"))); + EXPECT_EQ("abc", reflection->GetStringReference( + message, F("default_string_piece"), &scratch)); + + EXPECT_EQ("123", reflection->GetString(message, F("default_cord"))); + EXPECT_EQ("123", reflection->GetStringReference(message, F("default_cord"), + &scratch)); +} + +inline void TestUtil::ReflectionTester::ExpectPackedClearViaReflection( + const Message& message) { + const Reflection* reflection = message.GetReflection(); + + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_int32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_int64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_uint32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_uint64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sint32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sint64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_fixed32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_fixed64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sfixed32"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_sfixed64"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_float"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_double"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_bool"))); + EXPECT_EQ(0, reflection->FieldSize(message, F("packed_enum"))); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ReflectionTester::ModifyRepeatedFieldsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + Message* sub_message; + + reflection->SetRepeatedInt32(message, F("repeated_int32"), 1, 501); + reflection->SetRepeatedInt64(message, F("repeated_int64"), 1, 502); + reflection->SetRepeatedUInt32(message, F("repeated_uint32"), 1, 503); + reflection->SetRepeatedUInt64(message, F("repeated_uint64"), 1, 504); + reflection->SetRepeatedInt32(message, F("repeated_sint32"), 1, 505); + reflection->SetRepeatedInt64(message, F("repeated_sint64"), 1, 506); + reflection->SetRepeatedUInt32(message, F("repeated_fixed32"), 1, 507); + reflection->SetRepeatedUInt64(message, F("repeated_fixed64"), 1, 508); + reflection->SetRepeatedInt32(message, F("repeated_sfixed32"), 1, 509); + reflection->SetRepeatedInt64(message, F("repeated_sfixed64"), 1, 510); + reflection->SetRepeatedFloat(message, F("repeated_float"), 1, 511); + reflection->SetRepeatedDouble(message, F("repeated_double"), 1, 512); + reflection->SetRepeatedBool(message, F("repeated_bool"), 1, true); + reflection->SetRepeatedString(message, F("repeated_string"), 1, "515"); + reflection->SetRepeatedString(message, F("repeated_bytes"), 1, "516"); + + sub_message = + reflection->MutableRepeatedMessage(message, F("repeatedgroup"), 1); + sub_message->GetReflection()->SetInt32(sub_message, repeated_group_a_, 517); + sub_message = reflection->MutableRepeatedMessage( + message, F("repeated_nested_message"), 1); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 518); + sub_message = reflection->MutableRepeatedMessage( + message, F("repeated_foreign_message"), 1); + sub_message->GetReflection()->SetInt32(sub_message, foreign_c_, 519); + sub_message = reflection->MutableRepeatedMessage( + message, F("repeated_import_message"), 1); + sub_message->GetReflection()->SetInt32(sub_message, import_d_, 520); + sub_message = reflection->MutableRepeatedMessage( + message, F("repeated_lazy_message"), 1); + sub_message->GetReflection()->SetInt32(sub_message, nested_b_, 527); + + reflection->SetRepeatedEnum(message, F("repeated_nested_enum"), 1, + nested_foo_); + reflection->SetRepeatedEnum(message, F("repeated_foreign_enum"), 1, + foreign_foo_); + reflection->SetRepeatedEnum(message, F("repeated_import_enum"), 1, + import_foo_); + + reflection->SetRepeatedString(message, F("repeated_string_piece"), 1, "524"); + reflection->SetRepeatedString(message, F("repeated_cord"), 1, "525"); +} + +inline void TestUtil::ReflectionTester::ModifyPackedFieldsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + reflection->SetRepeatedInt32(message, F("packed_int32"), 1, 801); + reflection->SetRepeatedInt64(message, F("packed_int64"), 1, 802); + reflection->SetRepeatedUInt32(message, F("packed_uint32"), 1, 803); + reflection->SetRepeatedUInt64(message, F("packed_uint64"), 1, 804); + reflection->SetRepeatedInt32(message, F("packed_sint32"), 1, 805); + reflection->SetRepeatedInt64(message, F("packed_sint64"), 1, 806); + reflection->SetRepeatedUInt32(message, F("packed_fixed32"), 1, 807); + reflection->SetRepeatedUInt64(message, F("packed_fixed64"), 1, 808); + reflection->SetRepeatedInt32(message, F("packed_sfixed32"), 1, 809); + reflection->SetRepeatedInt64(message, F("packed_sfixed64"), 1, 810); + reflection->SetRepeatedFloat(message, F("packed_float"), 1, 811); + reflection->SetRepeatedDouble(message, F("packed_double"), 1, 812); + reflection->SetRepeatedBool(message, F("packed_bool"), 1, true); + reflection->SetRepeatedEnum(message, F("packed_enum"), 1, foreign_foo_); +} + +inline void TestUtil::ReflectionTester::RemoveLastRepeatedsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + std::vector output; + reflection->ListFields(*message, &output); + for (int i = 0; i < output.size(); ++i) { + const FieldDescriptor* field = output[i]; + if (!field->is_repeated()) continue; + + reflection->RemoveLast(message, field); + } +} + +inline void TestUtil::ReflectionTester::ReleaseLastRepeatedsViaReflection( + Message* message, bool expect_extensions_notnull) { + const Reflection* reflection = message->GetReflection(); + + std::vector output; + reflection->ListFields(*message, &output); + for (int i = 0; i < output.size(); ++i) { + const FieldDescriptor* field = output[i]; + if (!field->is_repeated()) continue; + if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) continue; + + Message* released = reflection->ReleaseLast(message, field); + if (!field->is_extension() || expect_extensions_notnull) { + ASSERT_TRUE(released != nullptr) + << "ReleaseLast returned nullptr for: " << field->name(); + } + delete released; + } +} + +inline void TestUtil::ReflectionTester::SwapRepeatedsViaReflection( + Message* message) { + const Reflection* reflection = message->GetReflection(); + + std::vector output; + reflection->ListFields(*message, &output); + for (int i = 0; i < output.size(); ++i) { + const FieldDescriptor* field = output[i]; + if (!field->is_repeated()) continue; + + reflection->SwapElements(message, field, 0, 1); + } +} + +inline void TestUtil::ReflectionTester:: + SetAllocatedOptionalMessageFieldsToNullViaReflection(Message* message) { + const Reflection* reflection = message->GetReflection(); + + std::vector fields; + reflection->ListFields(*message, &fields); + + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + if (!field->is_optional() || + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) + continue; + + reflection->SetAllocatedMessage(message, nullptr, field); + } +} + +inline void TestUtil::ReflectionTester:: + SetAllocatedOptionalMessageFieldsToMessageViaReflection( + Message* from_message, Message* to_message) { + EXPECT_EQ(from_message->GetDescriptor(), to_message->GetDescriptor()); + const Reflection* from_reflection = from_message->GetReflection(); + const Reflection* to_reflection = to_message->GetReflection(); + + std::vector fields; + from_reflection->ListFields(*from_message, &fields); + + for (int i = 0; i < fields.size(); ++i) { + const FieldDescriptor* field = fields[i]; + if (!field->is_optional() || + field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) + continue; + + Message* sub_message = from_reflection->ReleaseMessage(from_message, field); + to_reflection->SetAllocatedMessage(to_message, sub_message, field); + } +} + +inline void TestUtil::ReflectionTester::ExpectMessagesReleasedViaReflection( + Message* message, + TestUtil::ReflectionTester::MessageReleaseState expected_release_state) { + const Reflection* reflection = message->GetReflection(); + + static const char* fields[] = { + "optionalgroup", + "optional_nested_message", + "optional_foreign_message", + "optional_import_message", + }; + for (int i = 0; i < GOOGLE_ARRAYSIZE(fields); i++) { + const Message& sub_message = reflection->GetMessage(*message, F(fields[i])); + Message* released = reflection->ReleaseMessage(message, F(fields[i])); + switch (expected_release_state) { + case IS_NULL: + EXPECT_TRUE(released == nullptr); + break; + case NOT_NULL: + EXPECT_TRUE(released != nullptr); + if (message->GetArena() == nullptr) { + // released message must be same as sub_message if source message is + // not on arena. + EXPECT_EQ(&sub_message, released); + } + break; + case CAN_BE_NULL: + break; + } + delete released; + EXPECT_FALSE(reflection->HasField(*message, F(fields[i]))); + } +} + +// Check that the passed-in serialization is the canonical serialization we +// expect for a TestFieldOrderings message filled in by +// SetAllFieldsAndExtensions(). +inline void ExpectAllFieldsAndExtensionsInOrder( + const string& serialized) { + // We set each field individually, serialize separately, and concatenate all + // the strings in canonical order to determine the expected serialization. + string expected; + unittest::TestFieldOrderings message; + message.set_my_int(1); // Field 1. + message.AppendToString(&expected); + message.Clear(); + message.SetExtension(unittest::my_extension_int, 23); // Field 5. + message.AppendToString(&expected); + message.Clear(); + message.set_my_string("foo"); // Field 11. + message.AppendToString(&expected); + message.Clear(); + message.SetExtension(unittest::my_extension_string, "bar"); // Field 50. + message.AppendToString(&expected); + message.Clear(); + message.set_my_float(1.0); // Field 101. + message.AppendToString(&expected); + message.Clear(); + + // We don't EXPECT_EQ() since we don't want to print raw bytes to stdout. + EXPECT_TRUE(serialized == expected); +} + +} // namespace TestUtil +} // namespace protobuf + +} // namespace google +#endif // GOOGLE_PROTOBUF_TEST_UTIL_H__ diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util.inc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util.inc new file mode 100644 index 000000000..185f68d90 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util.inc @@ -0,0 +1,2600 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +// Author: kenton@google.com (Kenton Varda) +// Based on original Protocol Buffers design by +// Sanjay Ghemawat, Jeff Dean, and others. +// +// This file needs to be included as .inc as it depends on the namespaces +// (unittest and unittest_import) being set up properly. It is also included +// within an enclosing namespace and requires header files to be included +// out of this file. + +#include +#include +#include +#include +#include +#include + +namespace google { +namespace protobuf { +namespace TestUtil { + +// Set every field in the message to a unique value. +inline void SetAllFields(UNITTEST::TestAllTypes* message); +inline void SetOptionalFields(UNITTEST::TestAllTypes* message); +inline void AddRepeatedFields1(UNITTEST::TestAllTypes* message); +inline void AddRepeatedFields2(UNITTEST::TestAllTypes* message); +inline void SetDefaultFields(UNITTEST::TestAllTypes* message); +inline void SetOneofFields(UNITTEST::TestAllTypes* message); +inline void SetAllExtensions(UNITTEST::TestAllExtensions* message); +inline void SetOneofFields(UNITTEST::TestAllExtensions* message); +inline void SetAllFieldsAndExtensions(UNITTEST::TestFieldOrderings* message); +inline void SetPackedFields(UNITTEST::TestPackedTypes* message); +inline void SetPackedExtensions(UNITTEST::TestPackedExtensions* message); +inline void SetUnpackedFields(UNITTEST::TestUnpackedTypes* message); +inline void SetOneof1(UNITTEST::TestOneof2* message); +inline void SetOneof2(UNITTEST::TestOneof2* message); + +// Use the repeated versions of the set_*() accessors to modify all the +// repeated fields of the message (which should already have been +// initialized with Set*Fields()). Set*Fields() itself only tests +// the add_*() accessors. +inline void ModifyRepeatedFields(UNITTEST::TestAllTypes* message); +inline void ModifyRepeatedExtensions(UNITTEST::TestAllExtensions* message); +inline void ModifyPackedFields(UNITTEST::TestPackedTypes* message); +inline void ModifyPackedExtensions(UNITTEST::TestPackedExtensions* message); + +// Check that all fields have the values that they should have after +// Set*Fields() is called. +inline void ExpectAllFieldsSet(const UNITTEST::TestAllTypes& message); +inline void ExpectAllExtensionsSet(const UNITTEST::TestAllExtensions& message); +inline void ExpectPackedFieldsSet(const UNITTEST::TestPackedTypes& message); +inline void ExpectPackedExtensionsSet( + const UNITTEST::TestPackedExtensions& message); +inline void ExpectUnpackedFieldsSet(const UNITTEST::TestUnpackedTypes& message); +inline void ExpectUnpackedExtensionsSet( + const UNITTEST::TestUnpackedExtensions& message); +inline void ExpectOneofSet1(const UNITTEST::TestOneof2& message); +inline void ExpectOneofSet2(const UNITTEST::TestOneof2& message); + +// Expect that the message is modified as would be expected from +// Modify*Fields(). +inline void ExpectRepeatedFieldsModified(const UNITTEST::TestAllTypes& message); +inline void ExpectRepeatedExtensionsModified( + const UNITTEST::TestAllExtensions& message); +inline void ExpectPackedFieldsModified( + const UNITTEST::TestPackedTypes& message); +inline void ExpectPackedExtensionsModified( + const UNITTEST::TestPackedExtensions& message); + +// Check that all fields have their default values. +inline void ExpectClear(const UNITTEST::TestAllTypes& message); +inline void ExpectExtensionsClear(const UNITTEST::TestAllExtensions& message); +inline void ExpectPackedClear(const UNITTEST::TestPackedTypes& message); +inline void ExpectPackedExtensionsClear( + const UNITTEST::TestPackedExtensions& message); +inline void ExpectOneofClear(const UNITTEST::TestOneof2& message); + +// Check that all repeated fields have had their last elements removed. +inline void ExpectLastRepeatedsRemoved(const UNITTEST::TestAllTypes& message); +inline void ExpectLastRepeatedExtensionsRemoved( + const UNITTEST::TestAllExtensions& message); +inline void ExpectLastRepeatedsReleased(const UNITTEST::TestAllTypes& message); +inline void ExpectLastRepeatedExtensionsReleased( + const UNITTEST::TestAllExtensions& message); + +// Check that all repeated fields have had their first and last elements +// swapped. +inline void ExpectRepeatedsSwapped(const UNITTEST::TestAllTypes& message); +inline void ExpectRepeatedExtensionsSwapped( + const UNITTEST::TestAllExtensions& message); + +inline void ExpectAtMostOneFieldSetInOneof(const UNITTEST::TestOneof2& message); + +} // namespace TestUtil + +inline void TestUtil::SetAllFields(UNITTEST::TestAllTypes* message) { + SetOptionalFields(message); + AddRepeatedFields1(message); + AddRepeatedFields2(message); + SetDefaultFields(message); + SetOneofFields(message); +} + +inline void TestUtil::SetOptionalFields(UNITTEST::TestAllTypes* message) { + message->set_optional_int32(101); + message->set_optional_int64(102); + message->set_optional_uint32(103); + message->set_optional_uint64(104); + message->set_optional_sint32(105); + message->set_optional_sint64(106); + message->set_optional_fixed32(107); + message->set_optional_fixed64(108); + message->set_optional_sfixed32(109); + message->set_optional_sfixed64(110); + message->set_optional_float(111); + message->set_optional_double(112); + message->set_optional_bool(true); + message->set_optional_string("115"); + message->set_optional_bytes("116"); + + message->mutable_optionalgroup()->set_a(117); + message->mutable_optional_nested_message()->set_bb(118); + message->mutable_optional_foreign_message()->set_c(119); + message->mutable_optional_import_message()->set_d(120); + message->mutable_optional_public_import_message()->set_e(126); + message->mutable_optional_lazy_message()->set_bb(127); + + message->set_optional_nested_enum(UNITTEST::TestAllTypes::BAZ); + message->set_optional_foreign_enum(UNITTEST::FOREIGN_BAZ); + message->set_optional_import_enum(UNITTEST_IMPORT::IMPORT_BAZ); + + // StringPiece and Cord fields are only accessible via reflection in the + // open source release; see comments in compiler/cpp/string_field.cc. +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->SetString( + message, + message->GetDescriptor()->FindFieldByName("optional_string_piece"), + "124"); + message->GetReflection()->SetString( + message, message->GetDescriptor()->FindFieldByName("optional_cord"), + "125"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +// ------------------------------------------------------------------- + +inline void TestUtil::AddRepeatedFields1(UNITTEST::TestAllTypes* message) { + message->add_repeated_int32(201); + message->add_repeated_int64(202); + message->add_repeated_uint32(203); + message->add_repeated_uint64(204); + message->add_repeated_sint32(205); + message->add_repeated_sint64(206); + message->add_repeated_fixed32(207); + message->add_repeated_fixed64(208); + message->add_repeated_sfixed32(209); + message->add_repeated_sfixed64(210); + message->add_repeated_float(211); + message->add_repeated_double(212); + message->add_repeated_bool(true); + message->add_repeated_string("215"); + message->add_repeated_bytes("216"); + + message->add_repeatedgroup()->set_a(217); + message->add_repeated_nested_message()->set_bb(218); + message->add_repeated_foreign_message()->set_c(219); + message->add_repeated_import_message()->set_d(220); + message->add_repeated_lazy_message()->set_bb(227); + + message->add_repeated_nested_enum(UNITTEST::TestAllTypes::BAR); + message->add_repeated_foreign_enum(UNITTEST::FOREIGN_BAR); + message->add_repeated_import_enum(UNITTEST_IMPORT::IMPORT_BAR); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->AddString( + message, + message->GetDescriptor()->FindFieldByName("repeated_string_piece"), + "224"); + message->GetReflection()->AddString( + message, message->GetDescriptor()->FindFieldByName("repeated_cord"), + "225"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +inline void TestUtil::AddRepeatedFields2(UNITTEST::TestAllTypes* message) { + // Add a second one of each field. + message->add_repeated_int32(301); + message->add_repeated_int64(302); + message->add_repeated_uint32(303); + message->add_repeated_uint64(304); + message->add_repeated_sint32(305); + message->add_repeated_sint64(306); + message->add_repeated_fixed32(307); + message->add_repeated_fixed64(308); + message->add_repeated_sfixed32(309); + message->add_repeated_sfixed64(310); + message->add_repeated_float(311); + message->add_repeated_double(312); + message->add_repeated_bool(false); + message->add_repeated_string("315"); + message->add_repeated_bytes("316"); + + message->add_repeatedgroup()->set_a(317); + message->add_repeated_nested_message()->set_bb(318); + message->add_repeated_foreign_message()->set_c(319); + message->add_repeated_import_message()->set_d(320); + message->add_repeated_lazy_message()->set_bb(327); + + message->add_repeated_nested_enum(UNITTEST::TestAllTypes::BAZ); + message->add_repeated_foreign_enum(UNITTEST::FOREIGN_BAZ); + message->add_repeated_import_enum(UNITTEST_IMPORT::IMPORT_BAZ); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->AddString( + message, + message->GetDescriptor()->FindFieldByName("repeated_string_piece"), + "324"); + message->GetReflection()->AddString( + message, message->GetDescriptor()->FindFieldByName("repeated_cord"), + "325"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +// ------------------------------------------------------------------- + +inline void TestUtil::SetDefaultFields(UNITTEST::TestAllTypes* message) { + message->set_default_int32(401); + message->set_default_int64(402); + message->set_default_uint32(403); + message->set_default_uint64(404); + message->set_default_sint32(405); + message->set_default_sint64(406); + message->set_default_fixed32(407); + message->set_default_fixed64(408); + message->set_default_sfixed32(409); + message->set_default_sfixed64(410); + message->set_default_float(411); + message->set_default_double(412); + message->set_default_bool(false); + message->set_default_string("415"); + message->set_default_bytes("416"); + + message->set_default_nested_enum(UNITTEST::TestAllTypes::FOO); + message->set_default_foreign_enum(UNITTEST::FOREIGN_FOO); + message->set_default_import_enum(UNITTEST_IMPORT::IMPORT_FOO); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->SetString( + message, + message->GetDescriptor()->FindFieldByName("default_string_piece"), "424"); + message->GetReflection()->SetString( + message, message->GetDescriptor()->FindFieldByName("default_cord"), + "425"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ModifyRepeatedFields(UNITTEST::TestAllTypes* message) { + message->set_repeated_int32(1, 501); + message->set_repeated_int64(1, 502); + message->set_repeated_uint32(1, 503); + message->set_repeated_uint64(1, 504); + message->set_repeated_sint32(1, 505); + message->set_repeated_sint64(1, 506); + message->set_repeated_fixed32(1, 507); + message->set_repeated_fixed64(1, 508); + message->set_repeated_sfixed32(1, 509); + message->set_repeated_sfixed64(1, 510); + message->set_repeated_float(1, 511); + message->set_repeated_double(1, 512); + message->set_repeated_bool(1, true); + message->set_repeated_string(1, "515"); + message->set_repeated_bytes(1, "516"); + + message->mutable_repeatedgroup(1)->set_a(517); + message->mutable_repeated_nested_message(1)->set_bb(518); + message->mutable_repeated_foreign_message(1)->set_c(519); + message->mutable_repeated_import_message(1)->set_d(520); + message->mutable_repeated_lazy_message(1)->set_bb(527); + + message->set_repeated_nested_enum(1, UNITTEST::TestAllTypes::FOO); + message->set_repeated_foreign_enum(1, UNITTEST::FOREIGN_FOO); + message->set_repeated_import_enum(1, UNITTEST_IMPORT::IMPORT_FOO); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + message->GetReflection()->SetRepeatedString( + message, + message->GetDescriptor()->FindFieldByName("repeated_string_piece"), 1, + "524"); + message->GetReflection()->SetRepeatedString( + message, message->GetDescriptor()->FindFieldByName("repeated_cord"), 1, + "525"); +#endif // !PROTOBUF_TEST_NO_DESCRIPTORS +} + +// ------------------------------------------------------------------ +inline void TestUtil::SetOneofFields(UNITTEST::TestAllTypes* message) { + message->set_oneof_uint32(601); + message->mutable_oneof_nested_message()->set_bb(602); + message->set_oneof_string("603"); + message->set_oneof_bytes("604"); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectAllFieldsSet( + const UNITTEST::TestAllTypes& message) { + EXPECT_TRUE(message.has_optional_int32()); + EXPECT_TRUE(message.has_optional_int64()); + EXPECT_TRUE(message.has_optional_uint32()); + EXPECT_TRUE(message.has_optional_uint64()); + EXPECT_TRUE(message.has_optional_sint32()); + EXPECT_TRUE(message.has_optional_sint64()); + EXPECT_TRUE(message.has_optional_fixed32()); + EXPECT_TRUE(message.has_optional_fixed64()); + EXPECT_TRUE(message.has_optional_sfixed32()); + EXPECT_TRUE(message.has_optional_sfixed64()); + EXPECT_TRUE(message.has_optional_float()); + EXPECT_TRUE(message.has_optional_double()); + EXPECT_TRUE(message.has_optional_bool()); + EXPECT_TRUE(message.has_optional_string()); + EXPECT_TRUE(message.has_optional_bytes()); + + EXPECT_TRUE(message.has_optionalgroup()); + EXPECT_TRUE(message.has_optional_nested_message()); + EXPECT_TRUE(message.has_optional_foreign_message()); + EXPECT_TRUE(message.has_optional_import_message()); + EXPECT_TRUE(message.has_optional_public_import_message()); + EXPECT_TRUE(message.has_optional_lazy_message()); + + EXPECT_TRUE(message.optionalgroup().has_a()); + EXPECT_TRUE(message.optional_nested_message().has_bb()); + EXPECT_TRUE(message.optional_foreign_message().has_c()); + EXPECT_TRUE(message.optional_import_message().has_d()); + EXPECT_TRUE(message.optional_public_import_message().has_e()); + EXPECT_TRUE(message.optional_lazy_message().has_bb()); + + EXPECT_TRUE(message.has_optional_nested_enum()); + EXPECT_TRUE(message.has_optional_foreign_enum()); + EXPECT_TRUE(message.has_optional_import_enum()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + EXPECT_TRUE(message.has_optional_string_piece()); + EXPECT_TRUE(message.has_optional_cord()); +#endif + + EXPECT_EQ(101, message.optional_int32()); + EXPECT_EQ(102, message.optional_int64()); + EXPECT_EQ(103, message.optional_uint32()); + EXPECT_EQ(104, message.optional_uint64()); + EXPECT_EQ(105, message.optional_sint32()); + EXPECT_EQ(106, message.optional_sint64()); + EXPECT_EQ(107, message.optional_fixed32()); + EXPECT_EQ(108, message.optional_fixed64()); + EXPECT_EQ(109, message.optional_sfixed32()); + EXPECT_EQ(110, message.optional_sfixed64()); + EXPECT_EQ(111, message.optional_float()); + EXPECT_EQ(112, message.optional_double()); + EXPECT_TRUE(message.optional_bool()); + EXPECT_EQ("115", message.optional_string()); + EXPECT_EQ("116", message.optional_bytes()); + + EXPECT_EQ(117, message.optionalgroup().a()); + EXPECT_EQ(118, message.optional_nested_message().bb()); + EXPECT_EQ(119, message.optional_foreign_message().c()); + EXPECT_EQ(120, message.optional_import_message().d()); + EXPECT_EQ(126, message.optional_public_import_message().e()); + EXPECT_EQ(127, message.optional_lazy_message().bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, message.optional_nested_enum()); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.optional_foreign_enum()); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, message.optional_import_enum()); + + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, message.repeated_int32_size()); + ASSERT_EQ(2, message.repeated_int64_size()); + ASSERT_EQ(2, message.repeated_uint32_size()); + ASSERT_EQ(2, message.repeated_uint64_size()); + ASSERT_EQ(2, message.repeated_sint32_size()); + ASSERT_EQ(2, message.repeated_sint64_size()); + ASSERT_EQ(2, message.repeated_fixed32_size()); + ASSERT_EQ(2, message.repeated_fixed64_size()); + ASSERT_EQ(2, message.repeated_sfixed32_size()); + ASSERT_EQ(2, message.repeated_sfixed64_size()); + ASSERT_EQ(2, message.repeated_float_size()); + ASSERT_EQ(2, message.repeated_double_size()); + ASSERT_EQ(2, message.repeated_bool_size()); + ASSERT_EQ(2, message.repeated_string_size()); + ASSERT_EQ(2, message.repeated_bytes_size()); + + ASSERT_EQ(2, message.repeatedgroup_size()); + ASSERT_EQ(2, message.repeated_nested_message_size()); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_lazy_message_size()); + ASSERT_EQ(2, message.repeated_nested_enum_size()); + ASSERT_EQ(2, message.repeated_foreign_enum_size()); + ASSERT_EQ(2, message.repeated_import_enum_size()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + ASSERT_EQ(2, message.repeated_string_piece_size()); + ASSERT_EQ(2, message.repeated_cord_size()); +#endif + + EXPECT_EQ(201, message.repeated_int32(0)); + EXPECT_EQ(202, message.repeated_int64(0)); + EXPECT_EQ(203, message.repeated_uint32(0)); + EXPECT_EQ(204, message.repeated_uint64(0)); + EXPECT_EQ(205, message.repeated_sint32(0)); + EXPECT_EQ(206, message.repeated_sint64(0)); + EXPECT_EQ(207, message.repeated_fixed32(0)); + EXPECT_EQ(208, message.repeated_fixed64(0)); + EXPECT_EQ(209, message.repeated_sfixed32(0)); + EXPECT_EQ(210, message.repeated_sfixed64(0)); + EXPECT_EQ(211, message.repeated_float(0)); + EXPECT_EQ(212, message.repeated_double(0)); + EXPECT_TRUE(message.repeated_bool(0)); + EXPECT_EQ("215", message.repeated_string(0)); + EXPECT_EQ("216", message.repeated_bytes(0)); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(227, message.repeated_lazy_message(0).bb()); + + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.repeated_nested_enum(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeated_foreign_enum(0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.repeated_import_enum(0)); + + EXPECT_EQ(301, message.repeated_int32(1)); + EXPECT_EQ(302, message.repeated_int64(1)); + EXPECT_EQ(303, message.repeated_uint32(1)); + EXPECT_EQ(304, message.repeated_uint64(1)); + EXPECT_EQ(305, message.repeated_sint32(1)); + EXPECT_EQ(306, message.repeated_sint64(1)); + EXPECT_EQ(307, message.repeated_fixed32(1)); + EXPECT_EQ(308, message.repeated_fixed64(1)); + EXPECT_EQ(309, message.repeated_sfixed32(1)); + EXPECT_EQ(310, message.repeated_sfixed64(1)); + EXPECT_EQ(311, message.repeated_float(1)); + EXPECT_EQ(312, message.repeated_double(1)); + EXPECT_FALSE(message.repeated_bool(1)); + EXPECT_EQ("315", message.repeated_string(1)); + EXPECT_EQ("316", message.repeated_bytes(1)); + + EXPECT_EQ(317, message.repeatedgroup(1).a()); + EXPECT_EQ(318, message.repeated_nested_message(1).bb()); + EXPECT_EQ(319, message.repeated_foreign_message(1).c()); + EXPECT_EQ(320, message.repeated_import_message(1).d()); + EXPECT_EQ(327, message.repeated_lazy_message(1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, message.repeated_nested_enum(1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.repeated_foreign_enum(1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, message.repeated_import_enum(1)); + + + // ----------------------------------------------------------------- + + EXPECT_TRUE(message.has_default_int32()); + EXPECT_TRUE(message.has_default_int64()); + EXPECT_TRUE(message.has_default_uint32()); + EXPECT_TRUE(message.has_default_uint64()); + EXPECT_TRUE(message.has_default_sint32()); + EXPECT_TRUE(message.has_default_sint64()); + EXPECT_TRUE(message.has_default_fixed32()); + EXPECT_TRUE(message.has_default_fixed64()); + EXPECT_TRUE(message.has_default_sfixed32()); + EXPECT_TRUE(message.has_default_sfixed64()); + EXPECT_TRUE(message.has_default_float()); + EXPECT_TRUE(message.has_default_double()); + EXPECT_TRUE(message.has_default_bool()); + EXPECT_TRUE(message.has_default_string()); + EXPECT_TRUE(message.has_default_bytes()); + + EXPECT_TRUE(message.has_default_nested_enum()); + EXPECT_TRUE(message.has_default_foreign_enum()); + EXPECT_TRUE(message.has_default_import_enum()); + + + EXPECT_EQ(401, message.default_int32()); + EXPECT_EQ(402, message.default_int64()); + EXPECT_EQ(403, message.default_uint32()); + EXPECT_EQ(404, message.default_uint64()); + EXPECT_EQ(405, message.default_sint32()); + EXPECT_EQ(406, message.default_sint64()); + EXPECT_EQ(407, message.default_fixed32()); + EXPECT_EQ(408, message.default_fixed64()); + EXPECT_EQ(409, message.default_sfixed32()); + EXPECT_EQ(410, message.default_sfixed64()); + EXPECT_EQ(411, message.default_float()); + EXPECT_EQ(412, message.default_double()); + EXPECT_FALSE(message.default_bool()); + EXPECT_EQ("415", message.default_string()); + EXPECT_EQ("416", message.default_bytes()); + + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message.default_nested_enum()); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.default_foreign_enum()); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, message.default_import_enum()); + + + EXPECT_FALSE(message.has_oneof_uint32()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string()); + EXPECT_TRUE(message.has_oneof_bytes()); + + EXPECT_EQ("604", message.oneof_bytes()); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectClear(const UNITTEST::TestAllTypes& message) { + // has_blah() should initially be false for all optional fields. + EXPECT_FALSE(message.has_optional_int32()); + EXPECT_FALSE(message.has_optional_int64()); + EXPECT_FALSE(message.has_optional_uint32()); + EXPECT_FALSE(message.has_optional_uint64()); + EXPECT_FALSE(message.has_optional_sint32()); + EXPECT_FALSE(message.has_optional_sint64()); + EXPECT_FALSE(message.has_optional_fixed32()); + EXPECT_FALSE(message.has_optional_fixed64()); + EXPECT_FALSE(message.has_optional_sfixed32()); + EXPECT_FALSE(message.has_optional_sfixed64()); + EXPECT_FALSE(message.has_optional_float()); + EXPECT_FALSE(message.has_optional_double()); + EXPECT_FALSE(message.has_optional_bool()); + EXPECT_FALSE(message.has_optional_string()); + EXPECT_FALSE(message.has_optional_bytes()); + + EXPECT_FALSE(message.has_optionalgroup()); + EXPECT_FALSE(message.has_optional_nested_message()); + EXPECT_FALSE(message.has_optional_foreign_message()); + EXPECT_FALSE(message.has_optional_import_message()); + EXPECT_FALSE(message.has_optional_public_import_message()); + EXPECT_FALSE(message.has_optional_lazy_message()); + + EXPECT_FALSE(message.has_optional_nested_enum()); + EXPECT_FALSE(message.has_optional_foreign_enum()); + EXPECT_FALSE(message.has_optional_import_enum()); + + EXPECT_FALSE(message.has_optional_string_piece()); + EXPECT_FALSE(message.has_optional_cord()); + + // Optional fields without defaults are set to zero or something like it. + EXPECT_EQ(0, message.optional_int32()); + EXPECT_EQ(0, message.optional_int64()); + EXPECT_EQ(0, message.optional_uint32()); + EXPECT_EQ(0, message.optional_uint64()); + EXPECT_EQ(0, message.optional_sint32()); + EXPECT_EQ(0, message.optional_sint64()); + EXPECT_EQ(0, message.optional_fixed32()); + EXPECT_EQ(0, message.optional_fixed64()); + EXPECT_EQ(0, message.optional_sfixed32()); + EXPECT_EQ(0, message.optional_sfixed64()); + EXPECT_EQ(0, message.optional_float()); + EXPECT_EQ(0, message.optional_double()); + EXPECT_FALSE(message.optional_bool()); + EXPECT_EQ("", message.optional_string()); + EXPECT_EQ("", message.optional_bytes()); + + // Embedded messages should also be clear. + EXPECT_FALSE(message.optionalgroup().has_a()); + EXPECT_FALSE(message.optional_nested_message().has_bb()); + EXPECT_FALSE(message.optional_foreign_message().has_c()); + EXPECT_FALSE(message.optional_import_message().has_d()); + EXPECT_FALSE(message.optional_public_import_message().has_e()); + EXPECT_FALSE(message.optional_lazy_message().has_bb()); + + EXPECT_EQ(0, message.optionalgroup().a()); + EXPECT_EQ(0, message.optional_nested_message().bb()); + EXPECT_EQ(0, message.optional_foreign_message().c()); + EXPECT_EQ(0, message.optional_import_message().d()); + EXPECT_EQ(0, message.optional_public_import_message().e()); + EXPECT_EQ(0, message.optional_lazy_message().bb()); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message.optional_nested_enum()); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.optional_foreign_enum()); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, message.optional_import_enum()); + + + // Repeated fields are empty. + EXPECT_EQ(0, message.repeated_int32_size()); + EXPECT_EQ(0, message.repeated_int64_size()); + EXPECT_EQ(0, message.repeated_uint32_size()); + EXPECT_EQ(0, message.repeated_uint64_size()); + EXPECT_EQ(0, message.repeated_sint32_size()); + EXPECT_EQ(0, message.repeated_sint64_size()); + EXPECT_EQ(0, message.repeated_fixed32_size()); + EXPECT_EQ(0, message.repeated_fixed64_size()); + EXPECT_EQ(0, message.repeated_sfixed32_size()); + EXPECT_EQ(0, message.repeated_sfixed64_size()); + EXPECT_EQ(0, message.repeated_float_size()); + EXPECT_EQ(0, message.repeated_double_size()); + EXPECT_EQ(0, message.repeated_bool_size()); + EXPECT_EQ(0, message.repeated_string_size()); + EXPECT_EQ(0, message.repeated_bytes_size()); + + EXPECT_EQ(0, message.repeatedgroup_size()); + EXPECT_EQ(0, message.repeated_nested_message_size()); + EXPECT_EQ(0, message.repeated_foreign_message_size()); + EXPECT_EQ(0, message.repeated_import_message_size()); + EXPECT_EQ(0, message.repeated_lazy_message_size()); + EXPECT_EQ(0, message.repeated_nested_enum_size()); + EXPECT_EQ(0, message.repeated_foreign_enum_size()); + EXPECT_EQ(0, message.repeated_import_enum_size()); + + EXPECT_EQ(0, message.repeated_string_piece_size()); + EXPECT_EQ(0, message.repeated_cord_size()); + + // has_blah() should also be false for all default fields. + EXPECT_FALSE(message.has_default_int32()); + EXPECT_FALSE(message.has_default_int64()); + EXPECT_FALSE(message.has_default_uint32()); + EXPECT_FALSE(message.has_default_uint64()); + EXPECT_FALSE(message.has_default_sint32()); + EXPECT_FALSE(message.has_default_sint64()); + EXPECT_FALSE(message.has_default_fixed32()); + EXPECT_FALSE(message.has_default_fixed64()); + EXPECT_FALSE(message.has_default_sfixed32()); + EXPECT_FALSE(message.has_default_sfixed64()); + EXPECT_FALSE(message.has_default_float()); + EXPECT_FALSE(message.has_default_double()); + EXPECT_FALSE(message.has_default_bool()); + EXPECT_FALSE(message.has_default_string()); + EXPECT_FALSE(message.has_default_bytes()); + + EXPECT_FALSE(message.has_default_nested_enum()); + EXPECT_FALSE(message.has_default_foreign_enum()); + EXPECT_FALSE(message.has_default_import_enum()); + + + // Fields with defaults have their default values (duh). + EXPECT_EQ(41, message.default_int32()); + EXPECT_EQ(42, message.default_int64()); + EXPECT_EQ(43, message.default_uint32()); + EXPECT_EQ(44, message.default_uint64()); + EXPECT_EQ(-45, message.default_sint32()); + EXPECT_EQ(46, message.default_sint64()); + EXPECT_EQ(47, message.default_fixed32()); + EXPECT_EQ(48, message.default_fixed64()); + EXPECT_EQ(49, message.default_sfixed32()); + EXPECT_EQ(-50, message.default_sfixed64()); + EXPECT_EQ(51.5, message.default_float()); + EXPECT_EQ(52e3, message.default_double()); + EXPECT_TRUE(message.default_bool()); + EXPECT_EQ("hello", message.default_string()); + EXPECT_EQ("world", message.default_bytes()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.default_nested_enum()); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.default_foreign_enum()); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.default_import_enum()); + + + EXPECT_FALSE(message.has_oneof_uint32()); + EXPECT_FALSE(message.has_oneof_nested_message()); + EXPECT_FALSE(message.has_oneof_string()); + EXPECT_FALSE(message.has_oneof_bytes()); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectRepeatedFieldsModified( + const UNITTEST::TestAllTypes& message) { + // ModifyRepeatedFields only sets the second repeated element of each + // field. In addition to verifying this, we also verify that the first + // element and size were *not* modified. + ASSERT_EQ(2, message.repeated_int32_size()); + ASSERT_EQ(2, message.repeated_int64_size()); + ASSERT_EQ(2, message.repeated_uint32_size()); + ASSERT_EQ(2, message.repeated_uint64_size()); + ASSERT_EQ(2, message.repeated_sint32_size()); + ASSERT_EQ(2, message.repeated_sint64_size()); + ASSERT_EQ(2, message.repeated_fixed32_size()); + ASSERT_EQ(2, message.repeated_fixed64_size()); + ASSERT_EQ(2, message.repeated_sfixed32_size()); + ASSERT_EQ(2, message.repeated_sfixed64_size()); + ASSERT_EQ(2, message.repeated_float_size()); + ASSERT_EQ(2, message.repeated_double_size()); + ASSERT_EQ(2, message.repeated_bool_size()); + ASSERT_EQ(2, message.repeated_string_size()); + ASSERT_EQ(2, message.repeated_bytes_size()); + + ASSERT_EQ(2, message.repeatedgroup_size()); + ASSERT_EQ(2, message.repeated_nested_message_size()); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_lazy_message_size()); + ASSERT_EQ(2, message.repeated_nested_enum_size()); + ASSERT_EQ(2, message.repeated_foreign_enum_size()); + ASSERT_EQ(2, message.repeated_import_enum_size()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + ASSERT_EQ(2, message.repeated_string_piece_size()); + ASSERT_EQ(2, message.repeated_cord_size()); +#endif + + EXPECT_EQ(201, message.repeated_int32(0)); + EXPECT_EQ(202, message.repeated_int64(0)); + EXPECT_EQ(203, message.repeated_uint32(0)); + EXPECT_EQ(204, message.repeated_uint64(0)); + EXPECT_EQ(205, message.repeated_sint32(0)); + EXPECT_EQ(206, message.repeated_sint64(0)); + EXPECT_EQ(207, message.repeated_fixed32(0)); + EXPECT_EQ(208, message.repeated_fixed64(0)); + EXPECT_EQ(209, message.repeated_sfixed32(0)); + EXPECT_EQ(210, message.repeated_sfixed64(0)); + EXPECT_EQ(211, message.repeated_float(0)); + EXPECT_EQ(212, message.repeated_double(0)); + EXPECT_TRUE(message.repeated_bool(0)); + EXPECT_EQ("215", message.repeated_string(0)); + EXPECT_EQ("216", message.repeated_bytes(0)); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(227, message.repeated_lazy_message(0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.repeated_nested_enum(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeated_foreign_enum(0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.repeated_import_enum(0)); + + + // Actually verify the second (modified) elements now. + EXPECT_EQ(501, message.repeated_int32(1)); + EXPECT_EQ(502, message.repeated_int64(1)); + EXPECT_EQ(503, message.repeated_uint32(1)); + EXPECT_EQ(504, message.repeated_uint64(1)); + EXPECT_EQ(505, message.repeated_sint32(1)); + EXPECT_EQ(506, message.repeated_sint64(1)); + EXPECT_EQ(507, message.repeated_fixed32(1)); + EXPECT_EQ(508, message.repeated_fixed64(1)); + EXPECT_EQ(509, message.repeated_sfixed32(1)); + EXPECT_EQ(510, message.repeated_sfixed64(1)); + EXPECT_EQ(511, message.repeated_float(1)); + EXPECT_EQ(512, message.repeated_double(1)); + EXPECT_TRUE(message.repeated_bool(1)); + EXPECT_EQ("515", message.repeated_string(1)); + EXPECT_EQ("516", message.repeated_bytes(1)); + + EXPECT_EQ(517, message.repeatedgroup(1).a()); + EXPECT_EQ(518, message.repeated_nested_message(1).bb()); + EXPECT_EQ(519, message.repeated_foreign_message(1).c()); + EXPECT_EQ(520, message.repeated_import_message(1).d()); + EXPECT_EQ(527, message.repeated_lazy_message(1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, message.repeated_nested_enum(1)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.repeated_foreign_enum(1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, message.repeated_import_enum(1)); + +} + +// ------------------------------------------------------------------- + +inline void TestUtil::SetPackedFields(UNITTEST::TestPackedTypes* message) { + message->add_packed_int32(601); + message->add_packed_int64(602); + message->add_packed_uint32(603); + message->add_packed_uint64(604); + message->add_packed_sint32(605); + message->add_packed_sint64(606); + message->add_packed_fixed32(607); + message->add_packed_fixed64(608); + message->add_packed_sfixed32(609); + message->add_packed_sfixed64(610); + message->add_packed_float(611); + message->add_packed_double(612); + message->add_packed_bool(true); + message->add_packed_enum(UNITTEST::FOREIGN_BAR); + // add a second one of each field + message->add_packed_int32(701); + message->add_packed_int64(702); + message->add_packed_uint32(703); + message->add_packed_uint64(704); + message->add_packed_sint32(705); + message->add_packed_sint64(706); + message->add_packed_fixed32(707); + message->add_packed_fixed64(708); + message->add_packed_sfixed32(709); + message->add_packed_sfixed64(710); + message->add_packed_float(711); + message->add_packed_double(712); + message->add_packed_bool(false); + message->add_packed_enum(UNITTEST::FOREIGN_BAZ); +} + +inline void TestUtil::SetUnpackedFields(UNITTEST::TestUnpackedTypes* message) { + // The values applied here must match those of SetPackedFields. + + message->add_unpacked_int32(601); + message->add_unpacked_int64(602); + message->add_unpacked_uint32(603); + message->add_unpacked_uint64(604); + message->add_unpacked_sint32(605); + message->add_unpacked_sint64(606); + message->add_unpacked_fixed32(607); + message->add_unpacked_fixed64(608); + message->add_unpacked_sfixed32(609); + message->add_unpacked_sfixed64(610); + message->add_unpacked_float(611); + message->add_unpacked_double(612); + message->add_unpacked_bool(true); + message->add_unpacked_enum(UNITTEST::FOREIGN_BAR); + // add a second one of each field + message->add_unpacked_int32(701); + message->add_unpacked_int64(702); + message->add_unpacked_uint32(703); + message->add_unpacked_uint64(704); + message->add_unpacked_sint32(705); + message->add_unpacked_sint64(706); + message->add_unpacked_fixed32(707); + message->add_unpacked_fixed64(708); + message->add_unpacked_sfixed32(709); + message->add_unpacked_sfixed64(710); + message->add_unpacked_float(711); + message->add_unpacked_double(712); + message->add_unpacked_bool(false); + message->add_unpacked_enum(UNITTEST::FOREIGN_BAZ); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ModifyPackedFields(UNITTEST::TestPackedTypes* message) { + message->set_packed_int32(1, 801); + message->set_packed_int64(1, 802); + message->set_packed_uint32(1, 803); + message->set_packed_uint64(1, 804); + message->set_packed_sint32(1, 805); + message->set_packed_sint64(1, 806); + message->set_packed_fixed32(1, 807); + message->set_packed_fixed64(1, 808); + message->set_packed_sfixed32(1, 809); + message->set_packed_sfixed64(1, 810); + message->set_packed_float(1, 811); + message->set_packed_double(1, 812); + message->set_packed_bool(1, true); + message->set_packed_enum(1, UNITTEST::FOREIGN_FOO); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectPackedFieldsSet( + const UNITTEST::TestPackedTypes& message) { + ASSERT_EQ(2, message.packed_int32_size()); + ASSERT_EQ(2, message.packed_int64_size()); + ASSERT_EQ(2, message.packed_uint32_size()); + ASSERT_EQ(2, message.packed_uint64_size()); + ASSERT_EQ(2, message.packed_sint32_size()); + ASSERT_EQ(2, message.packed_sint64_size()); + ASSERT_EQ(2, message.packed_fixed32_size()); + ASSERT_EQ(2, message.packed_fixed64_size()); + ASSERT_EQ(2, message.packed_sfixed32_size()); + ASSERT_EQ(2, message.packed_sfixed64_size()); + ASSERT_EQ(2, message.packed_float_size()); + ASSERT_EQ(2, message.packed_double_size()); + ASSERT_EQ(2, message.packed_bool_size()); + ASSERT_EQ(2, message.packed_enum_size()); + + EXPECT_EQ(601, message.packed_int32(0)); + EXPECT_EQ(602, message.packed_int64(0)); + EXPECT_EQ(603, message.packed_uint32(0)); + EXPECT_EQ(604, message.packed_uint64(0)); + EXPECT_EQ(605, message.packed_sint32(0)); + EXPECT_EQ(606, message.packed_sint64(0)); + EXPECT_EQ(607, message.packed_fixed32(0)); + EXPECT_EQ(608, message.packed_fixed64(0)); + EXPECT_EQ(609, message.packed_sfixed32(0)); + EXPECT_EQ(610, message.packed_sfixed64(0)); + EXPECT_EQ(611, message.packed_float(0)); + EXPECT_EQ(612, message.packed_double(0)); + EXPECT_TRUE(message.packed_bool(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.packed_enum(0)); + + EXPECT_EQ(701, message.packed_int32(1)); + EXPECT_EQ(702, message.packed_int64(1)); + EXPECT_EQ(703, message.packed_uint32(1)); + EXPECT_EQ(704, message.packed_uint64(1)); + EXPECT_EQ(705, message.packed_sint32(1)); + EXPECT_EQ(706, message.packed_sint64(1)); + EXPECT_EQ(707, message.packed_fixed32(1)); + EXPECT_EQ(708, message.packed_fixed64(1)); + EXPECT_EQ(709, message.packed_sfixed32(1)); + EXPECT_EQ(710, message.packed_sfixed64(1)); + EXPECT_EQ(711, message.packed_float(1)); + EXPECT_EQ(712, message.packed_double(1)); + EXPECT_FALSE(message.packed_bool(1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.packed_enum(1)); +} + +inline void TestUtil::ExpectUnpackedFieldsSet( + const UNITTEST::TestUnpackedTypes& message) { + // The values expected here must match those of ExpectPackedFieldsSet. + + ASSERT_EQ(2, message.unpacked_int32_size()); + ASSERT_EQ(2, message.unpacked_int64_size()); + ASSERT_EQ(2, message.unpacked_uint32_size()); + ASSERT_EQ(2, message.unpacked_uint64_size()); + ASSERT_EQ(2, message.unpacked_sint32_size()); + ASSERT_EQ(2, message.unpacked_sint64_size()); + ASSERT_EQ(2, message.unpacked_fixed32_size()); + ASSERT_EQ(2, message.unpacked_fixed64_size()); + ASSERT_EQ(2, message.unpacked_sfixed32_size()); + ASSERT_EQ(2, message.unpacked_sfixed64_size()); + ASSERT_EQ(2, message.unpacked_float_size()); + ASSERT_EQ(2, message.unpacked_double_size()); + ASSERT_EQ(2, message.unpacked_bool_size()); + ASSERT_EQ(2, message.unpacked_enum_size()); + + EXPECT_EQ(601, message.unpacked_int32(0)); + EXPECT_EQ(602, message.unpacked_int64(0)); + EXPECT_EQ(603, message.unpacked_uint32(0)); + EXPECT_EQ(604, message.unpacked_uint64(0)); + EXPECT_EQ(605, message.unpacked_sint32(0)); + EXPECT_EQ(606, message.unpacked_sint64(0)); + EXPECT_EQ(607, message.unpacked_fixed32(0)); + EXPECT_EQ(608, message.unpacked_fixed64(0)); + EXPECT_EQ(609, message.unpacked_sfixed32(0)); + EXPECT_EQ(610, message.unpacked_sfixed64(0)); + EXPECT_EQ(611, message.unpacked_float(0)); + EXPECT_EQ(612, message.unpacked_double(0)); + EXPECT_TRUE(message.unpacked_bool(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.unpacked_enum(0)); + + EXPECT_EQ(701, message.unpacked_int32(1)); + EXPECT_EQ(702, message.unpacked_int64(1)); + EXPECT_EQ(703, message.unpacked_uint32(1)); + EXPECT_EQ(704, message.unpacked_uint64(1)); + EXPECT_EQ(705, message.unpacked_sint32(1)); + EXPECT_EQ(706, message.unpacked_sint64(1)); + EXPECT_EQ(707, message.unpacked_fixed32(1)); + EXPECT_EQ(708, message.unpacked_fixed64(1)); + EXPECT_EQ(709, message.unpacked_sfixed32(1)); + EXPECT_EQ(710, message.unpacked_sfixed64(1)); + EXPECT_EQ(711, message.unpacked_float(1)); + EXPECT_EQ(712, message.unpacked_double(1)); + EXPECT_FALSE(message.unpacked_bool(1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.unpacked_enum(1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectPackedClear( + const UNITTEST::TestPackedTypes& message) { + // Packed repeated fields are empty. + EXPECT_EQ(0, message.packed_int32_size()); + EXPECT_EQ(0, message.packed_int64_size()); + EXPECT_EQ(0, message.packed_uint32_size()); + EXPECT_EQ(0, message.packed_uint64_size()); + EXPECT_EQ(0, message.packed_sint32_size()); + EXPECT_EQ(0, message.packed_sint64_size()); + EXPECT_EQ(0, message.packed_fixed32_size()); + EXPECT_EQ(0, message.packed_fixed64_size()); + EXPECT_EQ(0, message.packed_sfixed32_size()); + EXPECT_EQ(0, message.packed_sfixed64_size()); + EXPECT_EQ(0, message.packed_float_size()); + EXPECT_EQ(0, message.packed_double_size()); + EXPECT_EQ(0, message.packed_bool_size()); + EXPECT_EQ(0, message.packed_enum_size()); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectPackedFieldsModified( + const UNITTEST::TestPackedTypes& message) { + // Do the same for packed repeated fields. + ASSERT_EQ(2, message.packed_int32_size()); + ASSERT_EQ(2, message.packed_int64_size()); + ASSERT_EQ(2, message.packed_uint32_size()); + ASSERT_EQ(2, message.packed_uint64_size()); + ASSERT_EQ(2, message.packed_sint32_size()); + ASSERT_EQ(2, message.packed_sint64_size()); + ASSERT_EQ(2, message.packed_fixed32_size()); + ASSERT_EQ(2, message.packed_fixed64_size()); + ASSERT_EQ(2, message.packed_sfixed32_size()); + ASSERT_EQ(2, message.packed_sfixed64_size()); + ASSERT_EQ(2, message.packed_float_size()); + ASSERT_EQ(2, message.packed_double_size()); + ASSERT_EQ(2, message.packed_bool_size()); + ASSERT_EQ(2, message.packed_enum_size()); + + EXPECT_EQ(601, message.packed_int32(0)); + EXPECT_EQ(602, message.packed_int64(0)); + EXPECT_EQ(603, message.packed_uint32(0)); + EXPECT_EQ(604, message.packed_uint64(0)); + EXPECT_EQ(605, message.packed_sint32(0)); + EXPECT_EQ(606, message.packed_sint64(0)); + EXPECT_EQ(607, message.packed_fixed32(0)); + EXPECT_EQ(608, message.packed_fixed64(0)); + EXPECT_EQ(609, message.packed_sfixed32(0)); + EXPECT_EQ(610, message.packed_sfixed64(0)); + EXPECT_EQ(611, message.packed_float(0)); + EXPECT_EQ(612, message.packed_double(0)); + EXPECT_TRUE(message.packed_bool(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.packed_enum(0)); + // Actually verify the second (modified) elements now. + EXPECT_EQ(801, message.packed_int32(1)); + EXPECT_EQ(802, message.packed_int64(1)); + EXPECT_EQ(803, message.packed_uint32(1)); + EXPECT_EQ(804, message.packed_uint64(1)); + EXPECT_EQ(805, message.packed_sint32(1)); + EXPECT_EQ(806, message.packed_sint64(1)); + EXPECT_EQ(807, message.packed_fixed32(1)); + EXPECT_EQ(808, message.packed_fixed64(1)); + EXPECT_EQ(809, message.packed_sfixed32(1)); + EXPECT_EQ(810, message.packed_sfixed64(1)); + EXPECT_EQ(811, message.packed_float(1)); + EXPECT_EQ(812, message.packed_double(1)); + EXPECT_TRUE(message.packed_bool(1)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, message.packed_enum(1)); +} + +// =================================================================== +// Extensions +// +// All this code is exactly equivalent to the above code except that it's +// manipulating extension fields instead of normal ones. + +inline void TestUtil::SetAllExtensions(UNITTEST::TestAllExtensions* message) { + message->SetExtension(UNITTEST::optional_int32_extension, 101); + message->SetExtension(UNITTEST::optional_int64_extension, 102); + message->SetExtension(UNITTEST::optional_uint32_extension, 103); + message->SetExtension(UNITTEST::optional_uint64_extension, 104); + message->SetExtension(UNITTEST::optional_sint32_extension, 105); + message->SetExtension(UNITTEST::optional_sint64_extension, 106); + message->SetExtension(UNITTEST::optional_fixed32_extension, 107); + message->SetExtension(UNITTEST::optional_fixed64_extension, 108); + message->SetExtension(UNITTEST::optional_sfixed32_extension, 109); + message->SetExtension(UNITTEST::optional_sfixed64_extension, 110); + message->SetExtension(UNITTEST::optional_float_extension, 111); + message->SetExtension(UNITTEST::optional_double_extension, 112); + message->SetExtension(UNITTEST::optional_bool_extension, true); + message->SetExtension(UNITTEST::optional_string_extension, "115"); + message->SetExtension(UNITTEST::optional_bytes_extension, "116"); + + message->MutableExtension(UNITTEST::optionalgroup_extension)->set_a(117); + message->MutableExtension(UNITTEST::optional_nested_message_extension) + ->set_bb(118); + message->MutableExtension(UNITTEST::optional_foreign_message_extension) + ->set_c(119); + message->MutableExtension(UNITTEST::optional_import_message_extension) + ->set_d(120); + + message->SetExtension(UNITTEST::optional_nested_enum_extension, + UNITTEST::TestAllTypes::BAZ); + message->SetExtension(UNITTEST::optional_foreign_enum_extension, + UNITTEST::FOREIGN_BAZ); + message->SetExtension(UNITTEST::optional_import_enum_extension, + UNITTEST_IMPORT::IMPORT_BAZ); + + message->SetExtension(UNITTEST::optional_string_piece_extension, "124"); + message->SetExtension(UNITTEST::optional_cord_extension, "125"); + + message->MutableExtension(UNITTEST::optional_public_import_message_extension) + ->set_e(126); + message->MutableExtension(UNITTEST::optional_lazy_message_extension) + ->set_bb(127); + + // ----------------------------------------------------------------- + + message->AddExtension(UNITTEST::repeated_int32_extension, 201); + message->AddExtension(UNITTEST::repeated_int64_extension, 202); + message->AddExtension(UNITTEST::repeated_uint32_extension, 203); + message->AddExtension(UNITTEST::repeated_uint64_extension, 204); + message->AddExtension(UNITTEST::repeated_sint32_extension, 205); + message->AddExtension(UNITTEST::repeated_sint64_extension, 206); + message->AddExtension(UNITTEST::repeated_fixed32_extension, 207); + message->AddExtension(UNITTEST::repeated_fixed64_extension, 208); + message->AddExtension(UNITTEST::repeated_sfixed32_extension, 209); + message->AddExtension(UNITTEST::repeated_sfixed64_extension, 210); + message->AddExtension(UNITTEST::repeated_float_extension, 211); + message->AddExtension(UNITTEST::repeated_double_extension, 212); + message->AddExtension(UNITTEST::repeated_bool_extension, true); + message->AddExtension(UNITTEST::repeated_string_extension, "215"); + message->AddExtension(UNITTEST::repeated_bytes_extension, "216"); + + message->AddExtension(UNITTEST::repeatedgroup_extension)->set_a(217); + message->AddExtension(UNITTEST::repeated_nested_message_extension) + ->set_bb(218); + message->AddExtension(UNITTEST::repeated_foreign_message_extension) + ->set_c(219); + message->AddExtension(UNITTEST::repeated_import_message_extension) + ->set_d(220); + message->AddExtension(UNITTEST::repeated_lazy_message_extension)->set_bb(227); + + message->AddExtension(UNITTEST::repeated_nested_enum_extension, + UNITTEST::TestAllTypes::BAR); + message->AddExtension(UNITTEST::repeated_foreign_enum_extension, + UNITTEST::FOREIGN_BAR); + message->AddExtension(UNITTEST::repeated_import_enum_extension, + UNITTEST_IMPORT::IMPORT_BAR); + + message->AddExtension(UNITTEST::repeated_string_piece_extension, "224"); + message->AddExtension(UNITTEST::repeated_cord_extension, "225"); + + // Add a second one of each field. + message->AddExtension(UNITTEST::repeated_int32_extension, 301); + message->AddExtension(UNITTEST::repeated_int64_extension, 302); + message->AddExtension(UNITTEST::repeated_uint32_extension, 303); + message->AddExtension(UNITTEST::repeated_uint64_extension, 304); + message->AddExtension(UNITTEST::repeated_sint32_extension, 305); + message->AddExtension(UNITTEST::repeated_sint64_extension, 306); + message->AddExtension(UNITTEST::repeated_fixed32_extension, 307); + message->AddExtension(UNITTEST::repeated_fixed64_extension, 308); + message->AddExtension(UNITTEST::repeated_sfixed32_extension, 309); + message->AddExtension(UNITTEST::repeated_sfixed64_extension, 310); + message->AddExtension(UNITTEST::repeated_float_extension, 311); + message->AddExtension(UNITTEST::repeated_double_extension, 312); + message->AddExtension(UNITTEST::repeated_bool_extension, false); + message->AddExtension(UNITTEST::repeated_string_extension, "315"); + message->AddExtension(UNITTEST::repeated_bytes_extension, "316"); + + message->AddExtension(UNITTEST::repeatedgroup_extension)->set_a(317); + message->AddExtension(UNITTEST::repeated_nested_message_extension) + ->set_bb(318); + message->AddExtension(UNITTEST::repeated_foreign_message_extension) + ->set_c(319); + message->AddExtension(UNITTEST::repeated_import_message_extension) + ->set_d(320); + message->AddExtension(UNITTEST::repeated_lazy_message_extension)->set_bb(327); + + message->AddExtension(UNITTEST::repeated_nested_enum_extension, + UNITTEST::TestAllTypes::BAZ); + message->AddExtension(UNITTEST::repeated_foreign_enum_extension, + UNITTEST::FOREIGN_BAZ); + message->AddExtension(UNITTEST::repeated_import_enum_extension, + UNITTEST_IMPORT::IMPORT_BAZ); + + message->AddExtension(UNITTEST::repeated_string_piece_extension, "324"); + message->AddExtension(UNITTEST::repeated_cord_extension, "325"); + + // ----------------------------------------------------------------- + + message->SetExtension(UNITTEST::default_int32_extension, 401); + message->SetExtension(UNITTEST::default_int64_extension, 402); + message->SetExtension(UNITTEST::default_uint32_extension, 403); + message->SetExtension(UNITTEST::default_uint64_extension, 404); + message->SetExtension(UNITTEST::default_sint32_extension, 405); + message->SetExtension(UNITTEST::default_sint64_extension, 406); + message->SetExtension(UNITTEST::default_fixed32_extension, 407); + message->SetExtension(UNITTEST::default_fixed64_extension, 408); + message->SetExtension(UNITTEST::default_sfixed32_extension, 409); + message->SetExtension(UNITTEST::default_sfixed64_extension, 410); + message->SetExtension(UNITTEST::default_float_extension, 411); + message->SetExtension(UNITTEST::default_double_extension, 412); + message->SetExtension(UNITTEST::default_bool_extension, false); + message->SetExtension(UNITTEST::default_string_extension, "415"); + message->SetExtension(UNITTEST::default_bytes_extension, "416"); + + message->SetExtension(UNITTEST::default_nested_enum_extension, + UNITTEST::TestAllTypes::FOO); + message->SetExtension(UNITTEST::default_foreign_enum_extension, + UNITTEST::FOREIGN_FOO); + message->SetExtension(UNITTEST::default_import_enum_extension, + UNITTEST_IMPORT::IMPORT_FOO); + + message->SetExtension(UNITTEST::default_string_piece_extension, "424"); + message->SetExtension(UNITTEST::default_cord_extension, "425"); + + SetOneofFields(message); +} + +inline void TestUtil::SetOneofFields(UNITTEST::TestAllExtensions* message) { + message->SetExtension(UNITTEST::oneof_uint32_extension, 601); + message->MutableExtension(UNITTEST::oneof_nested_message_extension) + ->set_bb(602); + message->SetExtension(UNITTEST::oneof_string_extension, "603"); + message->SetExtension(UNITTEST::oneof_bytes_extension, "604"); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::SetAllFieldsAndExtensions( + UNITTEST::TestFieldOrderings* message) { + GOOGLE_CHECK(message); + message->set_my_int(1); + message->set_my_string("foo"); + message->set_my_float(1.0); + message->SetExtension(UNITTEST::my_extension_int, 23); + message->SetExtension(UNITTEST::my_extension_string, "bar"); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ModifyRepeatedExtensions( + UNITTEST::TestAllExtensions* message) { + message->SetExtension(UNITTEST::repeated_int32_extension, 1, 501); + message->SetExtension(UNITTEST::repeated_int64_extension, 1, 502); + message->SetExtension(UNITTEST::repeated_uint32_extension, 1, 503); + message->SetExtension(UNITTEST::repeated_uint64_extension, 1, 504); + message->SetExtension(UNITTEST::repeated_sint32_extension, 1, 505); + message->SetExtension(UNITTEST::repeated_sint64_extension, 1, 506); + message->SetExtension(UNITTEST::repeated_fixed32_extension, 1, 507); + message->SetExtension(UNITTEST::repeated_fixed64_extension, 1, 508); + message->SetExtension(UNITTEST::repeated_sfixed32_extension, 1, 509); + message->SetExtension(UNITTEST::repeated_sfixed64_extension, 1, 510); + message->SetExtension(UNITTEST::repeated_float_extension, 1, 511); + message->SetExtension(UNITTEST::repeated_double_extension, 1, 512); + message->SetExtension(UNITTEST::repeated_bool_extension, 1, true); + message->SetExtension(UNITTEST::repeated_string_extension, 1, "515"); + message->SetExtension(UNITTEST::repeated_bytes_extension, 1, "516"); + + message->MutableExtension(UNITTEST::repeatedgroup_extension, 1)->set_a(517); + message->MutableExtension(UNITTEST::repeated_nested_message_extension, 1) + ->set_bb(518); + message->MutableExtension(UNITTEST::repeated_foreign_message_extension, 1) + ->set_c(519); + message->MutableExtension(UNITTEST::repeated_import_message_extension, 1) + ->set_d(520); + message->MutableExtension(UNITTEST::repeated_lazy_message_extension, 1) + ->set_bb(527); + + message->SetExtension(UNITTEST::repeated_nested_enum_extension, 1, + UNITTEST::TestAllTypes::FOO); + message->SetExtension(UNITTEST::repeated_foreign_enum_extension, 1, + UNITTEST::FOREIGN_FOO); + message->SetExtension(UNITTEST::repeated_import_enum_extension, 1, + UNITTEST_IMPORT::IMPORT_FOO); + + message->SetExtension(UNITTEST::repeated_string_piece_extension, 1, "524"); + message->SetExtension(UNITTEST::repeated_cord_extension, 1, "525"); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectAllExtensionsSet( + const UNITTEST::TestAllExtensions& message) { + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_int32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_int64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_uint32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_uint64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_sint32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_sint64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_fixed32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_fixed64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_sfixed32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_sfixed64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_float_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_double_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_bool_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_string_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_bytes_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::optionalgroup_extension)); + EXPECT_TRUE( + message.HasExtension(UNITTEST::optional_nested_message_extension)); + EXPECT_TRUE( + message.HasExtension(UNITTEST::optional_foreign_message_extension)); + EXPECT_TRUE( + message.HasExtension(UNITTEST::optional_import_message_extension)); + EXPECT_TRUE( + message.HasExtension(UNITTEST::optional_public_import_message_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_lazy_message_extension)); + + EXPECT_TRUE(message.GetExtension(UNITTEST::optionalgroup_extension).has_a()); + EXPECT_TRUE(message.GetExtension(UNITTEST::optional_nested_message_extension) + .has_bb()); + EXPECT_TRUE(message.GetExtension(UNITTEST::optional_foreign_message_extension) + .has_c()); + EXPECT_TRUE(message.GetExtension(UNITTEST::optional_import_message_extension) + .has_d()); + EXPECT_TRUE( + message.GetExtension(UNITTEST::optional_public_import_message_extension) + .has_e()); + EXPECT_TRUE( + message.GetExtension(UNITTEST::optional_lazy_message_extension).has_bb()); + + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_nested_enum_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_foreign_enum_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_import_enum_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_string_piece_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::optional_cord_extension)); + + EXPECT_EQ(101, message.GetExtension(UNITTEST::optional_int32_extension)); + EXPECT_EQ(102, message.GetExtension(UNITTEST::optional_int64_extension)); + EXPECT_EQ(103, message.GetExtension(UNITTEST::optional_uint32_extension)); + EXPECT_EQ(104, message.GetExtension(UNITTEST::optional_uint64_extension)); + EXPECT_EQ(105, message.GetExtension(UNITTEST::optional_sint32_extension)); + EXPECT_EQ(106, message.GetExtension(UNITTEST::optional_sint64_extension)); + EXPECT_EQ(107, message.GetExtension(UNITTEST::optional_fixed32_extension)); + EXPECT_EQ(108, message.GetExtension(UNITTEST::optional_fixed64_extension)); + EXPECT_EQ(109, message.GetExtension(UNITTEST::optional_sfixed32_extension)); + EXPECT_EQ(110, message.GetExtension(UNITTEST::optional_sfixed64_extension)); + EXPECT_EQ(111, message.GetExtension(UNITTEST::optional_float_extension)); + EXPECT_EQ(112, message.GetExtension(UNITTEST::optional_double_extension)); + EXPECT_TRUE(message.GetExtension(UNITTEST::optional_bool_extension)); + EXPECT_EQ("115", message.GetExtension(UNITTEST::optional_string_extension)); + EXPECT_EQ("116", message.GetExtension(UNITTEST::optional_bytes_extension)); + + EXPECT_EQ(117, message.GetExtension(UNITTEST::optionalgroup_extension).a()); + EXPECT_EQ( + 118, + message.GetExtension(UNITTEST::optional_nested_message_extension).bb()); + EXPECT_EQ( + 119, + message.GetExtension(UNITTEST::optional_foreign_message_extension).c()); + EXPECT_EQ( + 120, + message.GetExtension(UNITTEST::optional_import_message_extension).d()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, + message.GetExtension(UNITTEST::optional_nested_enum_extension)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::optional_foreign_enum_extension)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, + message.GetExtension(UNITTEST::optional_import_enum_extension)); + + EXPECT_EQ("124", + message.GetExtension(UNITTEST::optional_string_piece_extension)); + EXPECT_EQ("125", message.GetExtension(UNITTEST::optional_cord_extension)); + EXPECT_EQ( + 126, + message.GetExtension(UNITTEST::optional_public_import_message_extension) + .e()); + EXPECT_EQ( + 127, + message.GetExtension(UNITTEST::optional_lazy_message_extension).bb()); + + // ----------------------------------------------------------------- + + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_string_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 2, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + EXPECT_EQ(201, message.GetExtension(UNITTEST::repeated_int32_extension, 0)); + EXPECT_EQ(202, message.GetExtension(UNITTEST::repeated_int64_extension, 0)); + EXPECT_EQ(203, message.GetExtension(UNITTEST::repeated_uint32_extension, 0)); + EXPECT_EQ(204, message.GetExtension(UNITTEST::repeated_uint64_extension, 0)); + EXPECT_EQ(205, message.GetExtension(UNITTEST::repeated_sint32_extension, 0)); + EXPECT_EQ(206, message.GetExtension(UNITTEST::repeated_sint64_extension, 0)); + EXPECT_EQ(207, message.GetExtension(UNITTEST::repeated_fixed32_extension, 0)); + EXPECT_EQ(208, message.GetExtension(UNITTEST::repeated_fixed64_extension, 0)); + EXPECT_EQ(209, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 0)); + EXPECT_EQ(210, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 0)); + EXPECT_EQ(211, message.GetExtension(UNITTEST::repeated_float_extension, 0)); + EXPECT_EQ(212, message.GetExtension(UNITTEST::repeated_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 0)); + EXPECT_EQ("215", + message.GetExtension(UNITTEST::repeated_string_extension, 0)); + EXPECT_EQ("216", message.GetExtension(UNITTEST::repeated_bytes_extension, 0)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 0)); + + EXPECT_EQ("224", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 0)); + EXPECT_EQ("225", message.GetExtension(UNITTEST::repeated_cord_extension, 0)); + + EXPECT_EQ(301, message.GetExtension(UNITTEST::repeated_int32_extension, 1)); + EXPECT_EQ(302, message.GetExtension(UNITTEST::repeated_int64_extension, 1)); + EXPECT_EQ(303, message.GetExtension(UNITTEST::repeated_uint32_extension, 1)); + EXPECT_EQ(304, message.GetExtension(UNITTEST::repeated_uint64_extension, 1)); + EXPECT_EQ(305, message.GetExtension(UNITTEST::repeated_sint32_extension, 1)); + EXPECT_EQ(306, message.GetExtension(UNITTEST::repeated_sint64_extension, 1)); + EXPECT_EQ(307, message.GetExtension(UNITTEST::repeated_fixed32_extension, 1)); + EXPECT_EQ(308, message.GetExtension(UNITTEST::repeated_fixed64_extension, 1)); + EXPECT_EQ(309, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 1)); + EXPECT_EQ(310, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 1)); + EXPECT_EQ(311, message.GetExtension(UNITTEST::repeated_float_extension, 1)); + EXPECT_EQ(312, message.GetExtension(UNITTEST::repeated_double_extension, 1)); + EXPECT_FALSE(message.GetExtension(UNITTEST::repeated_bool_extension, 1)); + EXPECT_EQ("315", + message.GetExtension(UNITTEST::repeated_string_extension, 1)); + EXPECT_EQ("316", message.GetExtension(UNITTEST::repeated_bytes_extension, 1)); + + EXPECT_EQ(317, + message.GetExtension(UNITTEST::repeatedgroup_extension, 1).a()); + EXPECT_EQ(318, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 1) + .bb()); + EXPECT_EQ( + 319, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 1) + .c()); + EXPECT_EQ( + 320, + message.GetExtension(UNITTEST::repeated_import_message_extension, 1).d()); + EXPECT_EQ( + 327, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 1)); + + EXPECT_EQ("324", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 1)); + EXPECT_EQ("325", message.GetExtension(UNITTEST::repeated_cord_extension, 1)); + + // ----------------------------------------------------------------- + + EXPECT_TRUE(message.HasExtension(UNITTEST::default_int32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_int64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_uint32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_uint64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_sint32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_sint64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_fixed32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_fixed64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_sfixed32_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_sfixed64_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_float_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_double_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_bool_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_string_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_bytes_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::default_nested_enum_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_foreign_enum_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_import_enum_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::default_string_piece_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::default_cord_extension)); + + EXPECT_EQ(401, message.GetExtension(UNITTEST::default_int32_extension)); + EXPECT_EQ(402, message.GetExtension(UNITTEST::default_int64_extension)); + EXPECT_EQ(403, message.GetExtension(UNITTEST::default_uint32_extension)); + EXPECT_EQ(404, message.GetExtension(UNITTEST::default_uint64_extension)); + EXPECT_EQ(405, message.GetExtension(UNITTEST::default_sint32_extension)); + EXPECT_EQ(406, message.GetExtension(UNITTEST::default_sint64_extension)); + EXPECT_EQ(407, message.GetExtension(UNITTEST::default_fixed32_extension)); + EXPECT_EQ(408, message.GetExtension(UNITTEST::default_fixed64_extension)); + EXPECT_EQ(409, message.GetExtension(UNITTEST::default_sfixed32_extension)); + EXPECT_EQ(410, message.GetExtension(UNITTEST::default_sfixed64_extension)); + EXPECT_EQ(411, message.GetExtension(UNITTEST::default_float_extension)); + EXPECT_EQ(412, message.GetExtension(UNITTEST::default_double_extension)); + EXPECT_FALSE(message.GetExtension(UNITTEST::default_bool_extension)); + EXPECT_EQ("415", message.GetExtension(UNITTEST::default_string_extension)); + EXPECT_EQ("416", message.GetExtension(UNITTEST::default_bytes_extension)); + + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, + message.GetExtension(UNITTEST::default_nested_enum_extension)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, + message.GetExtension(UNITTEST::default_foreign_enum_extension)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, + message.GetExtension(UNITTEST::default_import_enum_extension)); + + EXPECT_EQ("424", + message.GetExtension(UNITTEST::default_string_piece_extension)); + EXPECT_EQ("425", message.GetExtension(UNITTEST::default_cord_extension)); + + EXPECT_TRUE(message.HasExtension(UNITTEST::oneof_uint32_extension)); + EXPECT_TRUE( + message.GetExtension(UNITTEST::oneof_nested_message_extension).has_bb()); + EXPECT_TRUE(message.HasExtension(UNITTEST::oneof_string_extension)); + EXPECT_TRUE(message.HasExtension(UNITTEST::oneof_bytes_extension)); + + EXPECT_EQ(601, message.GetExtension(UNITTEST::oneof_uint32_extension)); + EXPECT_EQ( + 602, message.GetExtension(UNITTEST::oneof_nested_message_extension).bb()); + EXPECT_EQ("603", message.GetExtension(UNITTEST::oneof_string_extension)); + EXPECT_EQ("604", message.GetExtension(UNITTEST::oneof_bytes_extension)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectExtensionsClear( + const UNITTEST::TestAllExtensions& message) { + string serialized; + ASSERT_TRUE(message.SerializeToString(&serialized)); + EXPECT_EQ("", serialized); + EXPECT_EQ(0, message.ByteSizeLong()); + + // has_blah() should initially be false for all optional fields. + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_int32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_int64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_uint32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_uint64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_sint32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_sint64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_fixed32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_fixed64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_sfixed32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_sfixed64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_float_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_double_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_bool_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_string_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_bytes_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::optionalgroup_extension)); + EXPECT_FALSE( + message.HasExtension(UNITTEST::optional_nested_message_extension)); + EXPECT_FALSE( + message.HasExtension(UNITTEST::optional_foreign_message_extension)); + EXPECT_FALSE( + message.HasExtension(UNITTEST::optional_import_message_extension)); + EXPECT_FALSE( + message.HasExtension(UNITTEST::optional_public_import_message_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_lazy_message_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_nested_enum_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_foreign_enum_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_import_enum_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_string_piece_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::optional_cord_extension)); + + // Optional fields without defaults are set to zero or something like it. + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_int32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_int64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_uint32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_uint64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_sint32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_sint64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_fixed32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_fixed64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_sfixed32_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_sfixed64_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_float_extension)); + EXPECT_EQ(0, message.GetExtension(UNITTEST::optional_double_extension)); + EXPECT_FALSE(message.GetExtension(UNITTEST::optional_bool_extension)); + EXPECT_EQ("", message.GetExtension(UNITTEST::optional_string_extension)); + EXPECT_EQ("", message.GetExtension(UNITTEST::optional_bytes_extension)); + + // Embedded messages should also be clear. + EXPECT_FALSE(message.GetExtension(UNITTEST::optionalgroup_extension).has_a()); + EXPECT_FALSE(message.GetExtension(UNITTEST::optional_nested_message_extension) + .has_bb()); + EXPECT_FALSE( + message.GetExtension(UNITTEST::optional_foreign_message_extension) + .has_c()); + EXPECT_FALSE(message.GetExtension(UNITTEST::optional_import_message_extension) + .has_d()); + EXPECT_FALSE( + message.GetExtension(UNITTEST::optional_public_import_message_extension) + .has_e()); + EXPECT_FALSE( + message.GetExtension(UNITTEST::optional_lazy_message_extension).has_bb()); + + EXPECT_EQ(0, message.GetExtension(UNITTEST::optionalgroup_extension).a()); + EXPECT_EQ( + 0, + message.GetExtension(UNITTEST::optional_nested_message_extension).bb()); + EXPECT_EQ( + 0, + message.GetExtension(UNITTEST::optional_foreign_message_extension).c()); + EXPECT_EQ( + 0, message.GetExtension(UNITTEST::optional_import_message_extension).d()); + EXPECT_EQ( + 0, + message.GetExtension(UNITTEST::optional_public_import_message_extension) + .e()); + EXPECT_EQ( + 0, message.GetExtension(UNITTEST::optional_lazy_message_extension).bb()); + + // Enums without defaults are set to the first value in the enum. + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, + message.GetExtension(UNITTEST::optional_nested_enum_extension)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, + message.GetExtension(UNITTEST::optional_foreign_enum_extension)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, + message.GetExtension(UNITTEST::optional_import_enum_extension)); + + EXPECT_EQ("", + message.GetExtension(UNITTEST::optional_string_piece_extension)); + EXPECT_EQ("", message.GetExtension(UNITTEST::optional_cord_extension)); + + // Repeated fields are empty. + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_float_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_double_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_string_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + EXPECT_EQ( + 0, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + EXPECT_EQ(0, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + // has_blah() should also be false for all default fields. + EXPECT_FALSE(message.HasExtension(UNITTEST::default_int32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_int64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_uint32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_uint64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_sint32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_sint64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_fixed32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_fixed64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_sfixed32_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_sfixed64_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_float_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_double_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_bool_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_string_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_bytes_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::default_nested_enum_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_foreign_enum_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_import_enum_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::default_string_piece_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::default_cord_extension)); + + // Fields with defaults have their default values (duh). + EXPECT_EQ(41, message.GetExtension(UNITTEST::default_int32_extension)); + EXPECT_EQ(42, message.GetExtension(UNITTEST::default_int64_extension)); + EXPECT_EQ(43, message.GetExtension(UNITTEST::default_uint32_extension)); + EXPECT_EQ(44, message.GetExtension(UNITTEST::default_uint64_extension)); + EXPECT_EQ(-45, message.GetExtension(UNITTEST::default_sint32_extension)); + EXPECT_EQ(46, message.GetExtension(UNITTEST::default_sint64_extension)); + EXPECT_EQ(47, message.GetExtension(UNITTEST::default_fixed32_extension)); + EXPECT_EQ(48, message.GetExtension(UNITTEST::default_fixed64_extension)); + EXPECT_EQ(49, message.GetExtension(UNITTEST::default_sfixed32_extension)); + EXPECT_EQ(-50, message.GetExtension(UNITTEST::default_sfixed64_extension)); + EXPECT_EQ(51.5, message.GetExtension(UNITTEST::default_float_extension)); + EXPECT_EQ(52e3, message.GetExtension(UNITTEST::default_double_extension)); + EXPECT_TRUE(message.GetExtension(UNITTEST::default_bool_extension)); + EXPECT_EQ("hello", message.GetExtension(UNITTEST::default_string_extension)); + EXPECT_EQ("world", message.GetExtension(UNITTEST::default_bytes_extension)); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::default_nested_enum_extension)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::default_foreign_enum_extension)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::default_import_enum_extension)); + + EXPECT_EQ("abc", + message.GetExtension(UNITTEST::default_string_piece_extension)); + EXPECT_EQ("123", message.GetExtension(UNITTEST::default_cord_extension)); + + EXPECT_FALSE(message.HasExtension(UNITTEST::oneof_uint32_extension)); + EXPECT_FALSE( + message.GetExtension(UNITTEST::oneof_nested_message_extension).has_bb()); + EXPECT_FALSE(message.HasExtension(UNITTEST::oneof_string_extension)); + EXPECT_FALSE(message.HasExtension(UNITTEST::oneof_bytes_extension)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectRepeatedExtensionsModified( + const UNITTEST::TestAllExtensions& message) { + // ModifyRepeatedFields only sets the second repeated element of each + // field. In addition to verifying this, we also verify that the first + // element and size were *not* modified. + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_string_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 2, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + EXPECT_EQ(201, message.GetExtension(UNITTEST::repeated_int32_extension, 0)); + EXPECT_EQ(202, message.GetExtension(UNITTEST::repeated_int64_extension, 0)); + EXPECT_EQ(203, message.GetExtension(UNITTEST::repeated_uint32_extension, 0)); + EXPECT_EQ(204, message.GetExtension(UNITTEST::repeated_uint64_extension, 0)); + EXPECT_EQ(205, message.GetExtension(UNITTEST::repeated_sint32_extension, 0)); + EXPECT_EQ(206, message.GetExtension(UNITTEST::repeated_sint64_extension, 0)); + EXPECT_EQ(207, message.GetExtension(UNITTEST::repeated_fixed32_extension, 0)); + EXPECT_EQ(208, message.GetExtension(UNITTEST::repeated_fixed64_extension, 0)); + EXPECT_EQ(209, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 0)); + EXPECT_EQ(210, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 0)); + EXPECT_EQ(211, message.GetExtension(UNITTEST::repeated_float_extension, 0)); + EXPECT_EQ(212, message.GetExtension(UNITTEST::repeated_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 0)); + EXPECT_EQ("215", + message.GetExtension(UNITTEST::repeated_string_extension, 0)); + EXPECT_EQ("216", message.GetExtension(UNITTEST::repeated_bytes_extension, 0)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 0)); + + EXPECT_EQ("224", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 0)); + EXPECT_EQ("225", message.GetExtension(UNITTEST::repeated_cord_extension, 0)); + + // Actually verify the second (modified) elements now. + EXPECT_EQ(501, message.GetExtension(UNITTEST::repeated_int32_extension, 1)); + EXPECT_EQ(502, message.GetExtension(UNITTEST::repeated_int64_extension, 1)); + EXPECT_EQ(503, message.GetExtension(UNITTEST::repeated_uint32_extension, 1)); + EXPECT_EQ(504, message.GetExtension(UNITTEST::repeated_uint64_extension, 1)); + EXPECT_EQ(505, message.GetExtension(UNITTEST::repeated_sint32_extension, 1)); + EXPECT_EQ(506, message.GetExtension(UNITTEST::repeated_sint64_extension, 1)); + EXPECT_EQ(507, message.GetExtension(UNITTEST::repeated_fixed32_extension, 1)); + EXPECT_EQ(508, message.GetExtension(UNITTEST::repeated_fixed64_extension, 1)); + EXPECT_EQ(509, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 1)); + EXPECT_EQ(510, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 1)); + EXPECT_EQ(511, message.GetExtension(UNITTEST::repeated_float_extension, 1)); + EXPECT_EQ(512, message.GetExtension(UNITTEST::repeated_double_extension, 1)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 1)); + EXPECT_EQ("515", + message.GetExtension(UNITTEST::repeated_string_extension, 1)); + EXPECT_EQ("516", message.GetExtension(UNITTEST::repeated_bytes_extension, 1)); + + EXPECT_EQ(517, + message.GetExtension(UNITTEST::repeatedgroup_extension, 1).a()); + EXPECT_EQ(518, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 1) + .bb()); + EXPECT_EQ( + 519, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 1) + .c()); + EXPECT_EQ( + 520, + message.GetExtension(UNITTEST::repeated_import_message_extension, 1).d()); + EXPECT_EQ( + 527, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::FOO, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_FOO, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 1)); + + EXPECT_EQ("524", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 1)); + EXPECT_EQ("525", message.GetExtension(UNITTEST::repeated_cord_extension, 1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::SetPackedExtensions( + UNITTEST::TestPackedExtensions* message) { + message->AddExtension(UNITTEST::packed_int32_extension, 601); + message->AddExtension(UNITTEST::packed_int64_extension, 602); + message->AddExtension(UNITTEST::packed_uint32_extension, 603); + message->AddExtension(UNITTEST::packed_uint64_extension, 604); + message->AddExtension(UNITTEST::packed_sint32_extension, 605); + message->AddExtension(UNITTEST::packed_sint64_extension, 606); + message->AddExtension(UNITTEST::packed_fixed32_extension, 607); + message->AddExtension(UNITTEST::packed_fixed64_extension, 608); + message->AddExtension(UNITTEST::packed_sfixed32_extension, 609); + message->AddExtension(UNITTEST::packed_sfixed64_extension, 610); + message->AddExtension(UNITTEST::packed_float_extension, 611); + message->AddExtension(UNITTEST::packed_double_extension, 612); + message->AddExtension(UNITTEST::packed_bool_extension, true); + message->AddExtension(UNITTEST::packed_enum_extension, UNITTEST::FOREIGN_BAR); + // add a second one of each field + message->AddExtension(UNITTEST::packed_int32_extension, 701); + message->AddExtension(UNITTEST::packed_int64_extension, 702); + message->AddExtension(UNITTEST::packed_uint32_extension, 703); + message->AddExtension(UNITTEST::packed_uint64_extension, 704); + message->AddExtension(UNITTEST::packed_sint32_extension, 705); + message->AddExtension(UNITTEST::packed_sint64_extension, 706); + message->AddExtension(UNITTEST::packed_fixed32_extension, 707); + message->AddExtension(UNITTEST::packed_fixed64_extension, 708); + message->AddExtension(UNITTEST::packed_sfixed32_extension, 709); + message->AddExtension(UNITTEST::packed_sfixed64_extension, 710); + message->AddExtension(UNITTEST::packed_float_extension, 711); + message->AddExtension(UNITTEST::packed_double_extension, 712); + message->AddExtension(UNITTEST::packed_bool_extension, false); + message->AddExtension(UNITTEST::packed_enum_extension, UNITTEST::FOREIGN_BAZ); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ModifyPackedExtensions( + UNITTEST::TestPackedExtensions* message) { + message->SetExtension(UNITTEST::packed_int32_extension, 1, 801); + message->SetExtension(UNITTEST::packed_int64_extension, 1, 802); + message->SetExtension(UNITTEST::packed_uint32_extension, 1, 803); + message->SetExtension(UNITTEST::packed_uint64_extension, 1, 804); + message->SetExtension(UNITTEST::packed_sint32_extension, 1, 805); + message->SetExtension(UNITTEST::packed_sint64_extension, 1, 806); + message->SetExtension(UNITTEST::packed_fixed32_extension, 1, 807); + message->SetExtension(UNITTEST::packed_fixed64_extension, 1, 808); + message->SetExtension(UNITTEST::packed_sfixed32_extension, 1, 809); + message->SetExtension(UNITTEST::packed_sfixed64_extension, 1, 810); + message->SetExtension(UNITTEST::packed_float_extension, 1, 811); + message->SetExtension(UNITTEST::packed_double_extension, 1, 812); + message->SetExtension(UNITTEST::packed_bool_extension, 1, true); + message->SetExtension(UNITTEST::packed_enum_extension, 1, + UNITTEST::FOREIGN_FOO); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectPackedExtensionsSet( + const UNITTEST::TestPackedExtensions& message) { + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_enum_extension)); + + EXPECT_EQ(601, message.GetExtension(UNITTEST::packed_int32_extension, 0)); + EXPECT_EQ(602, message.GetExtension(UNITTEST::packed_int64_extension, 0)); + EXPECT_EQ(603, message.GetExtension(UNITTEST::packed_uint32_extension, 0)); + EXPECT_EQ(604, message.GetExtension(UNITTEST::packed_uint64_extension, 0)); + EXPECT_EQ(605, message.GetExtension(UNITTEST::packed_sint32_extension, 0)); + EXPECT_EQ(606, message.GetExtension(UNITTEST::packed_sint64_extension, 0)); + EXPECT_EQ(607, message.GetExtension(UNITTEST::packed_fixed32_extension, 0)); + EXPECT_EQ(608, message.GetExtension(UNITTEST::packed_fixed64_extension, 0)); + EXPECT_EQ(609, message.GetExtension(UNITTEST::packed_sfixed32_extension, 0)); + EXPECT_EQ(610, message.GetExtension(UNITTEST::packed_sfixed64_extension, 0)); + EXPECT_EQ(611, message.GetExtension(UNITTEST::packed_float_extension, 0)); + EXPECT_EQ(612, message.GetExtension(UNITTEST::packed_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::packed_bool_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::packed_enum_extension, 0)); + EXPECT_EQ(701, message.GetExtension(UNITTEST::packed_int32_extension, 1)); + EXPECT_EQ(702, message.GetExtension(UNITTEST::packed_int64_extension, 1)); + EXPECT_EQ(703, message.GetExtension(UNITTEST::packed_uint32_extension, 1)); + EXPECT_EQ(704, message.GetExtension(UNITTEST::packed_uint64_extension, 1)); + EXPECT_EQ(705, message.GetExtension(UNITTEST::packed_sint32_extension, 1)); + EXPECT_EQ(706, message.GetExtension(UNITTEST::packed_sint64_extension, 1)); + EXPECT_EQ(707, message.GetExtension(UNITTEST::packed_fixed32_extension, 1)); + EXPECT_EQ(708, message.GetExtension(UNITTEST::packed_fixed64_extension, 1)); + EXPECT_EQ(709, message.GetExtension(UNITTEST::packed_sfixed32_extension, 1)); + EXPECT_EQ(710, message.GetExtension(UNITTEST::packed_sfixed64_extension, 1)); + EXPECT_EQ(711, message.GetExtension(UNITTEST::packed_float_extension, 1)); + EXPECT_EQ(712, message.GetExtension(UNITTEST::packed_double_extension, 1)); + EXPECT_FALSE(message.GetExtension(UNITTEST::packed_bool_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::packed_enum_extension, 1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectPackedExtensionsClear( + const UNITTEST::TestPackedExtensions& message) { + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_int32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_int64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_uint32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_uint64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_sint32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_sint64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_fixed32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_fixed64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_sfixed32_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_sfixed64_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_float_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_double_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_bool_extension)); + EXPECT_EQ(0, message.ExtensionSize(UNITTEST::packed_enum_extension)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectPackedExtensionsModified( + const UNITTEST::TestPackedExtensions& message) { + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::packed_enum_extension)); + EXPECT_EQ(601, message.GetExtension(UNITTEST::packed_int32_extension, 0)); + EXPECT_EQ(602, message.GetExtension(UNITTEST::packed_int64_extension, 0)); + EXPECT_EQ(603, message.GetExtension(UNITTEST::packed_uint32_extension, 0)); + EXPECT_EQ(604, message.GetExtension(UNITTEST::packed_uint64_extension, 0)); + EXPECT_EQ(605, message.GetExtension(UNITTEST::packed_sint32_extension, 0)); + EXPECT_EQ(606, message.GetExtension(UNITTEST::packed_sint64_extension, 0)); + EXPECT_EQ(607, message.GetExtension(UNITTEST::packed_fixed32_extension, 0)); + EXPECT_EQ(608, message.GetExtension(UNITTEST::packed_fixed64_extension, 0)); + EXPECT_EQ(609, message.GetExtension(UNITTEST::packed_sfixed32_extension, 0)); + EXPECT_EQ(610, message.GetExtension(UNITTEST::packed_sfixed64_extension, 0)); + EXPECT_EQ(611, message.GetExtension(UNITTEST::packed_float_extension, 0)); + EXPECT_EQ(612, message.GetExtension(UNITTEST::packed_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::packed_bool_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::packed_enum_extension, 0)); + + // Actually verify the second (modified) elements now. + EXPECT_EQ(801, message.GetExtension(UNITTEST::packed_int32_extension, 1)); + EXPECT_EQ(802, message.GetExtension(UNITTEST::packed_int64_extension, 1)); + EXPECT_EQ(803, message.GetExtension(UNITTEST::packed_uint32_extension, 1)); + EXPECT_EQ(804, message.GetExtension(UNITTEST::packed_uint64_extension, 1)); + EXPECT_EQ(805, message.GetExtension(UNITTEST::packed_sint32_extension, 1)); + EXPECT_EQ(806, message.GetExtension(UNITTEST::packed_sint64_extension, 1)); + EXPECT_EQ(807, message.GetExtension(UNITTEST::packed_fixed32_extension, 1)); + EXPECT_EQ(808, message.GetExtension(UNITTEST::packed_fixed64_extension, 1)); + EXPECT_EQ(809, message.GetExtension(UNITTEST::packed_sfixed32_extension, 1)); + EXPECT_EQ(810, message.GetExtension(UNITTEST::packed_sfixed64_extension, 1)); + EXPECT_EQ(811, message.GetExtension(UNITTEST::packed_float_extension, 1)); + EXPECT_EQ(812, message.GetExtension(UNITTEST::packed_double_extension, 1)); + EXPECT_TRUE(message.GetExtension(UNITTEST::packed_bool_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_FOO, + message.GetExtension(UNITTEST::packed_enum_extension, 1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectUnpackedExtensionsSet( + const UNITTEST::TestUnpackedExtensions& message) { + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::unpacked_enum_extension)); + + EXPECT_EQ(601, message.GetExtension(UNITTEST::unpacked_int32_extension, 0)); + EXPECT_EQ(602, message.GetExtension(UNITTEST::unpacked_int64_extension, 0)); + EXPECT_EQ(603, message.GetExtension(UNITTEST::unpacked_uint32_extension, 0)); + EXPECT_EQ(604, message.GetExtension(UNITTEST::unpacked_uint64_extension, 0)); + EXPECT_EQ(605, message.GetExtension(UNITTEST::unpacked_sint32_extension, 0)); + EXPECT_EQ(606, message.GetExtension(UNITTEST::unpacked_sint64_extension, 0)); + EXPECT_EQ(607, message.GetExtension(UNITTEST::unpacked_fixed32_extension, 0)); + EXPECT_EQ(608, message.GetExtension(UNITTEST::unpacked_fixed64_extension, 0)); + EXPECT_EQ(609, + message.GetExtension(UNITTEST::unpacked_sfixed32_extension, 0)); + EXPECT_EQ(610, + message.GetExtension(UNITTEST::unpacked_sfixed64_extension, 0)); + EXPECT_EQ(611, message.GetExtension(UNITTEST::unpacked_float_extension, 0)); + EXPECT_EQ(612, message.GetExtension(UNITTEST::unpacked_double_extension, 0)); + EXPECT_EQ(true, message.GetExtension(UNITTEST::unpacked_bool_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::unpacked_enum_extension, 0)); + EXPECT_EQ(701, message.GetExtension(UNITTEST::unpacked_int32_extension, 1)); + EXPECT_EQ(702, message.GetExtension(UNITTEST::unpacked_int64_extension, 1)); + EXPECT_EQ(703, message.GetExtension(UNITTEST::unpacked_uint32_extension, 1)); + EXPECT_EQ(704, message.GetExtension(UNITTEST::unpacked_uint64_extension, 1)); + EXPECT_EQ(705, message.GetExtension(UNITTEST::unpacked_sint32_extension, 1)); + EXPECT_EQ(706, message.GetExtension(UNITTEST::unpacked_sint64_extension, 1)); + EXPECT_EQ(707, message.GetExtension(UNITTEST::unpacked_fixed32_extension, 1)); + EXPECT_EQ(708, message.GetExtension(UNITTEST::unpacked_fixed64_extension, 1)); + EXPECT_EQ(709, + message.GetExtension(UNITTEST::unpacked_sfixed32_extension, 1)); + EXPECT_EQ(710, + message.GetExtension(UNITTEST::unpacked_sfixed64_extension, 1)); + EXPECT_EQ(711, message.GetExtension(UNITTEST::unpacked_float_extension, 1)); + EXPECT_EQ(712, message.GetExtension(UNITTEST::unpacked_double_extension, 1)); + EXPECT_EQ(false, message.GetExtension(UNITTEST::unpacked_bool_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::unpacked_enum_extension, 1)); +} + +// ------------------------------------------------------------------- + +inline void TestUtil::ExpectLastRepeatedsRemoved( + const UNITTEST::TestAllTypes& message) { + ASSERT_EQ(1, message.repeated_int32_size()); + ASSERT_EQ(1, message.repeated_int64_size()); + ASSERT_EQ(1, message.repeated_uint32_size()); + ASSERT_EQ(1, message.repeated_uint64_size()); + ASSERT_EQ(1, message.repeated_sint32_size()); + ASSERT_EQ(1, message.repeated_sint64_size()); + ASSERT_EQ(1, message.repeated_fixed32_size()); + ASSERT_EQ(1, message.repeated_fixed64_size()); + ASSERT_EQ(1, message.repeated_sfixed32_size()); + ASSERT_EQ(1, message.repeated_sfixed64_size()); + ASSERT_EQ(1, message.repeated_float_size()); + ASSERT_EQ(1, message.repeated_double_size()); + ASSERT_EQ(1, message.repeated_bool_size()); + ASSERT_EQ(1, message.repeated_string_size()); + ASSERT_EQ(1, message.repeated_bytes_size()); + + ASSERT_EQ(1, message.repeatedgroup_size()); + ASSERT_EQ(1, message.repeated_nested_message_size()); + ASSERT_EQ(1, message.repeated_foreign_message_size()); + ASSERT_EQ(1, message.repeated_import_message_size()); + ASSERT_EQ(1, message.repeated_import_message_size()); + ASSERT_EQ(1, message.repeated_nested_enum_size()); + ASSERT_EQ(1, message.repeated_foreign_enum_size()); + ASSERT_EQ(1, message.repeated_import_enum_size()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + ASSERT_EQ(1, message.repeated_string_piece_size()); + ASSERT_EQ(1, message.repeated_cord_size()); +#endif + + // Test that the remaining element is the correct one. + EXPECT_EQ(201, message.repeated_int32(0)); + EXPECT_EQ(202, message.repeated_int64(0)); + EXPECT_EQ(203, message.repeated_uint32(0)); + EXPECT_EQ(204, message.repeated_uint64(0)); + EXPECT_EQ(205, message.repeated_sint32(0)); + EXPECT_EQ(206, message.repeated_sint64(0)); + EXPECT_EQ(207, message.repeated_fixed32(0)); + EXPECT_EQ(208, message.repeated_fixed64(0)); + EXPECT_EQ(209, message.repeated_sfixed32(0)); + EXPECT_EQ(210, message.repeated_sfixed64(0)); + EXPECT_EQ(211, message.repeated_float(0)); + EXPECT_EQ(212, message.repeated_double(0)); + EXPECT_TRUE(message.repeated_bool(0)); + EXPECT_EQ("215", message.repeated_string(0)); + EXPECT_EQ("216", message.repeated_bytes(0)); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.repeated_nested_enum(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeated_foreign_enum(0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.repeated_import_enum(0)); +} + +inline void TestUtil::ExpectLastRepeatedExtensionsRemoved( + const UNITTEST::TestAllExtensions& message) { + // Test that one element was removed. + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_float_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_double_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_string_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 1, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + // Test that the remaining element is the correct one. + EXPECT_EQ(201, message.GetExtension(UNITTEST::repeated_int32_extension, 0)); + EXPECT_EQ(202, message.GetExtension(UNITTEST::repeated_int64_extension, 0)); + EXPECT_EQ(203, message.GetExtension(UNITTEST::repeated_uint32_extension, 0)); + EXPECT_EQ(204, message.GetExtension(UNITTEST::repeated_uint64_extension, 0)); + EXPECT_EQ(205, message.GetExtension(UNITTEST::repeated_sint32_extension, 0)); + EXPECT_EQ(206, message.GetExtension(UNITTEST::repeated_sint64_extension, 0)); + EXPECT_EQ(207, message.GetExtension(UNITTEST::repeated_fixed32_extension, 0)); + EXPECT_EQ(208, message.GetExtension(UNITTEST::repeated_fixed64_extension, 0)); + EXPECT_EQ(209, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 0)); + EXPECT_EQ(210, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 0)); + EXPECT_EQ(211, message.GetExtension(UNITTEST::repeated_float_extension, 0)); + EXPECT_EQ(212, message.GetExtension(UNITTEST::repeated_double_extension, 0)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 0)); + EXPECT_EQ("215", + message.GetExtension(UNITTEST::repeated_string_extension, 0)); + EXPECT_EQ("216", message.GetExtension(UNITTEST::repeated_bytes_extension, 0)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 0)); + + EXPECT_EQ("224", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 0)); + EXPECT_EQ("225", message.GetExtension(UNITTEST::repeated_cord_extension, 0)); +} + +inline void TestUtil::ExpectLastRepeatedsReleased( + const UNITTEST::TestAllTypes& message) { + ASSERT_EQ(1, message.repeatedgroup_size()); + ASSERT_EQ(1, message.repeated_nested_message_size()); + ASSERT_EQ(1, message.repeated_foreign_message_size()); + ASSERT_EQ(1, message.repeated_import_message_size()); + ASSERT_EQ(1, message.repeated_import_message_size()); + + EXPECT_EQ(217, message.repeatedgroup(0).a()); + EXPECT_EQ(218, message.repeated_nested_message(0).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(0).c()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); + EXPECT_EQ(220, message.repeated_import_message(0).d()); +} + +inline void TestUtil::ExpectLastRepeatedExtensionsReleased( + const UNITTEST::TestAllExtensions& message) { + ASSERT_EQ(1, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 1, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(1, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); +} + +inline void TestUtil::ExpectRepeatedsSwapped( + const UNITTEST::TestAllTypes& message) { + ASSERT_EQ(2, message.repeated_int32_size()); + ASSERT_EQ(2, message.repeated_int64_size()); + ASSERT_EQ(2, message.repeated_uint32_size()); + ASSERT_EQ(2, message.repeated_uint64_size()); + ASSERT_EQ(2, message.repeated_sint32_size()); + ASSERT_EQ(2, message.repeated_sint64_size()); + ASSERT_EQ(2, message.repeated_fixed32_size()); + ASSERT_EQ(2, message.repeated_fixed64_size()); + ASSERT_EQ(2, message.repeated_sfixed32_size()); + ASSERT_EQ(2, message.repeated_sfixed64_size()); + ASSERT_EQ(2, message.repeated_float_size()); + ASSERT_EQ(2, message.repeated_double_size()); + ASSERT_EQ(2, message.repeated_bool_size()); + ASSERT_EQ(2, message.repeated_string_size()); + ASSERT_EQ(2, message.repeated_bytes_size()); + + ASSERT_EQ(2, message.repeatedgroup_size()); + ASSERT_EQ(2, message.repeated_nested_message_size()); + ASSERT_EQ(2, message.repeated_foreign_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_import_message_size()); + ASSERT_EQ(2, message.repeated_nested_enum_size()); + ASSERT_EQ(2, message.repeated_foreign_enum_size()); + ASSERT_EQ(2, message.repeated_import_enum_size()); + +#ifndef PROTOBUF_TEST_NO_DESCRIPTORS + ASSERT_EQ(2, message.repeated_string_piece_size()); + ASSERT_EQ(2, message.repeated_cord_size()); +#endif + + // Test that the first element and second element are flipped. + EXPECT_EQ(201, message.repeated_int32(1)); + EXPECT_EQ(202, message.repeated_int64(1)); + EXPECT_EQ(203, message.repeated_uint32(1)); + EXPECT_EQ(204, message.repeated_uint64(1)); + EXPECT_EQ(205, message.repeated_sint32(1)); + EXPECT_EQ(206, message.repeated_sint64(1)); + EXPECT_EQ(207, message.repeated_fixed32(1)); + EXPECT_EQ(208, message.repeated_fixed64(1)); + EXPECT_EQ(209, message.repeated_sfixed32(1)); + EXPECT_EQ(210, message.repeated_sfixed64(1)); + EXPECT_EQ(211, message.repeated_float(1)); + EXPECT_EQ(212, message.repeated_double(1)); + EXPECT_TRUE(message.repeated_bool(1)); + EXPECT_EQ("215", message.repeated_string(1)); + EXPECT_EQ("216", message.repeated_bytes(1)); + + EXPECT_EQ(217, message.repeatedgroup(1).a()); + EXPECT_EQ(218, message.repeated_nested_message(1).bb()); + EXPECT_EQ(219, message.repeated_foreign_message(1).c()); + EXPECT_EQ(220, message.repeated_import_message(1).d()); + EXPECT_EQ(220, message.repeated_import_message(1).d()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, message.repeated_nested_enum(1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, message.repeated_foreign_enum(1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, message.repeated_import_enum(1)); + + EXPECT_EQ(301, message.repeated_int32(0)); + EXPECT_EQ(302, message.repeated_int64(0)); + EXPECT_EQ(303, message.repeated_uint32(0)); + EXPECT_EQ(304, message.repeated_uint64(0)); + EXPECT_EQ(305, message.repeated_sint32(0)); + EXPECT_EQ(306, message.repeated_sint64(0)); + EXPECT_EQ(307, message.repeated_fixed32(0)); + EXPECT_EQ(308, message.repeated_fixed64(0)); + EXPECT_EQ(309, message.repeated_sfixed32(0)); + EXPECT_EQ(310, message.repeated_sfixed64(0)); + EXPECT_EQ(311, message.repeated_float(0)); + EXPECT_EQ(312, message.repeated_double(0)); + EXPECT_FALSE(message.repeated_bool(0)); + EXPECT_EQ("315", message.repeated_string(0)); + EXPECT_EQ("316", message.repeated_bytes(0)); + + EXPECT_EQ(317, message.repeatedgroup(0).a()); + EXPECT_EQ(318, message.repeated_nested_message(0).bb()); + EXPECT_EQ(319, message.repeated_foreign_message(0).c()); + EXPECT_EQ(320, message.repeated_import_message(0).d()); + EXPECT_EQ(320, message.repeated_import_message(0).d()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, message.repeated_nested_enum(0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, message.repeated_foreign_enum(0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, message.repeated_import_enum(0)); +} + +inline void TestUtil::ExpectRepeatedExtensionsSwapped( + const UNITTEST::TestAllExtensions& message) { + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_int64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_uint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sint64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_fixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed32_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_sfixed64_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_float_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_double_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bool_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_string_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_bytes_extension)); + + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeatedgroup_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_nested_message_extension)); + ASSERT_EQ( + 2, message.ExtensionSize(UNITTEST::repeated_foreign_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_import_message_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_lazy_message_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_nested_enum_extension)); + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_foreign_enum_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_import_enum_extension)); + + ASSERT_EQ(2, + message.ExtensionSize(UNITTEST::repeated_string_piece_extension)); + ASSERT_EQ(2, message.ExtensionSize(UNITTEST::repeated_cord_extension)); + + EXPECT_EQ(201, message.GetExtension(UNITTEST::repeated_int32_extension, 1)); + EXPECT_EQ(202, message.GetExtension(UNITTEST::repeated_int64_extension, 1)); + EXPECT_EQ(203, message.GetExtension(UNITTEST::repeated_uint32_extension, 1)); + EXPECT_EQ(204, message.GetExtension(UNITTEST::repeated_uint64_extension, 1)); + EXPECT_EQ(205, message.GetExtension(UNITTEST::repeated_sint32_extension, 1)); + EXPECT_EQ(206, message.GetExtension(UNITTEST::repeated_sint64_extension, 1)); + EXPECT_EQ(207, message.GetExtension(UNITTEST::repeated_fixed32_extension, 1)); + EXPECT_EQ(208, message.GetExtension(UNITTEST::repeated_fixed64_extension, 1)); + EXPECT_EQ(209, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 1)); + EXPECT_EQ(210, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 1)); + EXPECT_EQ(211, message.GetExtension(UNITTEST::repeated_float_extension, 1)); + EXPECT_EQ(212, message.GetExtension(UNITTEST::repeated_double_extension, 1)); + EXPECT_TRUE(message.GetExtension(UNITTEST::repeated_bool_extension, 1)); + EXPECT_EQ("215", + message.GetExtension(UNITTEST::repeated_string_extension, 1)); + EXPECT_EQ("216", message.GetExtension(UNITTEST::repeated_bytes_extension, 1)); + + EXPECT_EQ(217, + message.GetExtension(UNITTEST::repeatedgroup_extension, 1).a()); + EXPECT_EQ(218, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 1) + .bb()); + EXPECT_EQ( + 219, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 1) + .c()); + EXPECT_EQ( + 220, + message.GetExtension(UNITTEST::repeated_import_message_extension, 1).d()); + EXPECT_EQ( + 227, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 1).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAR, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 1)); + EXPECT_EQ(UNITTEST::FOREIGN_BAR, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 1)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAR, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 1)); + + EXPECT_EQ("224", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 1)); + EXPECT_EQ("225", message.GetExtension(UNITTEST::repeated_cord_extension, 1)); + + EXPECT_EQ(301, message.GetExtension(UNITTEST::repeated_int32_extension, 0)); + EXPECT_EQ(302, message.GetExtension(UNITTEST::repeated_int64_extension, 0)); + EXPECT_EQ(303, message.GetExtension(UNITTEST::repeated_uint32_extension, 0)); + EXPECT_EQ(304, message.GetExtension(UNITTEST::repeated_uint64_extension, 0)); + EXPECT_EQ(305, message.GetExtension(UNITTEST::repeated_sint32_extension, 0)); + EXPECT_EQ(306, message.GetExtension(UNITTEST::repeated_sint64_extension, 0)); + EXPECT_EQ(307, message.GetExtension(UNITTEST::repeated_fixed32_extension, 0)); + EXPECT_EQ(308, message.GetExtension(UNITTEST::repeated_fixed64_extension, 0)); + EXPECT_EQ(309, + message.GetExtension(UNITTEST::repeated_sfixed32_extension, 0)); + EXPECT_EQ(310, + message.GetExtension(UNITTEST::repeated_sfixed64_extension, 0)); + EXPECT_EQ(311, message.GetExtension(UNITTEST::repeated_float_extension, 0)); + EXPECT_EQ(312, message.GetExtension(UNITTEST::repeated_double_extension, 0)); + EXPECT_FALSE(message.GetExtension(UNITTEST::repeated_bool_extension, 0)); + EXPECT_EQ("315", + message.GetExtension(UNITTEST::repeated_string_extension, 0)); + EXPECT_EQ("316", message.GetExtension(UNITTEST::repeated_bytes_extension, 0)); + + EXPECT_EQ(317, + message.GetExtension(UNITTEST::repeatedgroup_extension, 0).a()); + EXPECT_EQ(318, + message.GetExtension(UNITTEST::repeated_nested_message_extension, 0) + .bb()); + EXPECT_EQ( + 319, message.GetExtension(UNITTEST::repeated_foreign_message_extension, 0) + .c()); + EXPECT_EQ( + 320, + message.GetExtension(UNITTEST::repeated_import_message_extension, 0).d()); + EXPECT_EQ( + 327, + message.GetExtension(UNITTEST::repeated_lazy_message_extension, 0).bb()); + + EXPECT_EQ(UNITTEST::TestAllTypes::BAZ, + message.GetExtension(UNITTEST::repeated_nested_enum_extension, 0)); + EXPECT_EQ(UNITTEST::FOREIGN_BAZ, + message.GetExtension(UNITTEST::repeated_foreign_enum_extension, 0)); + EXPECT_EQ(UNITTEST_IMPORT::IMPORT_BAZ, + message.GetExtension(UNITTEST::repeated_import_enum_extension, 0)); + + EXPECT_EQ("324", + message.GetExtension(UNITTEST::repeated_string_piece_extension, 0)); + EXPECT_EQ("325", message.GetExtension(UNITTEST::repeated_cord_extension, 0)); +} + +inline void TestUtil::SetOneof1(UNITTEST::TestOneof2* message) { + message->mutable_foo_lazy_message()->set_qux_int(100); + message->set_bar_string("101"); + message->set_baz_int(102); + message->set_baz_string("103"); +} + +inline void TestUtil::SetOneof2(UNITTEST::TestOneof2* message) { + message->set_foo_int(200); + message->set_bar_enum(UNITTEST::TestOneof2::BAZ); + message->set_baz_int(202); + message->set_baz_string("203"); +} + +inline void TestUtil::ExpectOneofSet1(const UNITTEST::TestOneof2& message) { + ExpectAtMostOneFieldSetInOneof(message); + + EXPECT_TRUE(message.has_foo_lazy_message()); + EXPECT_TRUE(message.foo_lazy_message().has_qux_int()); + + EXPECT_TRUE(message.has_bar_string()); + EXPECT_TRUE(message.has_baz_int()); + EXPECT_TRUE(message.has_baz_string()); + + ASSERT_EQ(0, message.foo_lazy_message().corge_int_size()); + + EXPECT_EQ(100, message.foo_lazy_message().qux_int()); + EXPECT_EQ("101", message.bar_string()); + EXPECT_EQ(102, message.baz_int()); + EXPECT_EQ("103", message.baz_string()); +} + +inline void TestUtil::ExpectOneofSet2(const UNITTEST::TestOneof2& message) { + ExpectAtMostOneFieldSetInOneof(message); + + EXPECT_TRUE(message.has_foo_int()); + EXPECT_TRUE(message.has_bar_enum()); + EXPECT_TRUE(message.has_baz_int()); + EXPECT_TRUE(message.has_baz_string()); + + EXPECT_EQ(200, message.foo_int()); + EXPECT_EQ(UNITTEST::TestOneof2::BAZ, message.bar_enum()); + EXPECT_EQ(202, message.baz_int()); + EXPECT_EQ("203", message.baz_string()); +} + +inline void TestUtil::ExpectOneofClear(const UNITTEST::TestOneof2& message) { + EXPECT_FALSE(message.has_foo_int()); + EXPECT_FALSE(message.has_foo_string()); + EXPECT_FALSE(message.has_foo_bytes()); + EXPECT_FALSE(message.has_foo_enum()); + EXPECT_FALSE(message.has_foo_message()); + EXPECT_FALSE(message.has_foogroup()); + EXPECT_FALSE(message.has_foo_lazy_message()); + + EXPECT_FALSE(message.has_bar_int()); + EXPECT_FALSE(message.has_bar_string()); + EXPECT_FALSE(message.has_bar_bytes()); + EXPECT_FALSE(message.has_bar_enum()); + + EXPECT_FALSE(message.has_baz_int()); + EXPECT_FALSE(message.has_baz_string()); + + EXPECT_EQ(UNITTEST::TestOneof2::FOO_NOT_SET, message.foo_case()); + EXPECT_EQ(UNITTEST::TestOneof2::BAR_NOT_SET, message.bar_case()); +} + +inline void TestUtil::ExpectAtMostOneFieldSetInOneof( + const UNITTEST::TestOneof2& message) { + int count = 0; + if (message.has_foo_int()) count++; + if (message.has_foo_string()) count++; + if (message.has_foo_bytes()) count++; + if (message.has_foo_enum()) count++; + if (message.has_foo_message()) count++; + if (message.has_foogroup()) count++; + if (message.has_foo_lazy_message()) count++; + EXPECT_LE(count, 1); + count = 0; + if (message.has_bar_int()) count++; + if (message.has_bar_string()) count++; + if (message.has_bar_bytes()) count++; + if (message.has_bar_enum()) count++; + EXPECT_TRUE(count == 0 || count == 1); +} + +// =================================================================== + +} // namespace protobuf +} // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/test_util_lite.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util_lite.cc similarity index 99% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/test_util_lite.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util_lite.cc index 88eca0ad8..79c5abec6 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/test_util_lite.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util_lite.cc @@ -33,15 +33,11 @@ // Sanjay Ghemawat, Jeff Dean, and others. #include +#include #include +#include -#define EXPECT_TRUE GOOGLE_CHECK -#define ASSERT_TRUE GOOGLE_CHECK -#define EXPECT_FALSE(COND) GOOGLE_CHECK(!(COND)) -#define EXPECT_EQ GOOGLE_CHECK_EQ -#define ASSERT_EQ GOOGLE_CHECK_EQ - namespace google { namespace protobuf { diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/test_util_lite.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util_lite.h similarity index 98% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/test_util_lite.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util_lite.h index f250c937d..47a2269d3 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/test_util_lite.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/test_util_lite.h @@ -52,7 +52,7 @@ class TestUtilLite { static void SetPackedExtensions(unittest::TestPackedExtensionsLite* message); // Use the repeated versions of the set_*() accessors to modify all the - // repeated fields of the messsage (which should already have been + // repeated fields of the message (which should already have been // initialized with Set*Fields()). Set*Fields() itself only tests // the add_*() accessors. static void ModifyRepeatedFields(unittest::TestAllTypesLite* message); diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testdata/bad_utf8_string b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testdata/bad_utf8_string similarity index 100% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testdata/bad_utf8_string rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testdata/bad_utf8_string diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testdata/golden_message b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testdata/golden_message similarity index 100% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testdata/golden_message rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testdata/golden_message diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testdata/golden_message_maps b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testdata/golden_message_maps new file mode 100644 index 0000000000000000000000000000000000000000..c70a4d7cde5b36e9b4970862826b8f8d1be169b3 GIT binary patch literal 13619 zcmd^FdsviJ8vh0d`R3EnugP1aagoczpef@8VV^dlT6>_I^i;cA+cvq`u4VOJS%xYprl7H1=6px9w z%;U$`0bCY*>cZsUx%~J#=fV!gZ)v1p#27Pve0|KA?^{l9ADGmbIsEuK7;`dzv|@7b z!~FO<7<1xm%~c9UjA8llb!vAkFSrpoZeI& zH9V=y)A{jraJjwcK(_WwCD>sp`0;gcxv{q8E(Ig@oAcxA)EFyPrg(H>4oF#smyH2p z3%flO^Cn^}*qJ<8;T+k^gWS!p2F~EMOPmcm6kc0w zhC$@Kb_pPj9T|-%WHzr|0!Y%p?z2-cDYJO(57| z$!K;2B?bjZCOH38;KAZGe1IBOU4enq*YIu!g`-5|&Fl6S5AVe(J)uNPFTvg(Jb4Xgcd1 zJ4hvY(%jJ!T8T=fc?39;+nL#UevK%O=03PYnDk0eXExvvS{5=b2qlS?efaS9R#YfW zJjEhyRt1LD?1REXDpW7EKq{#Y|J*Y_Lo-3jlva4WQ^yL;c^d9pe5#d<2F|JojVL2iPG{mIEJ2vnyN?2txdw zt*uF4VMd7if~5@`RID=C87%GC#`b?1Q*G(M4yPQSg+*2`_beB&*W>&yqV+G15t!$f z7T1j?DJ4{Z?9VMqLK_7wO@M^eoGwHmG}XcUp}eTuW|*78g0ysG4}@R3XNLKymq8$~ zJT`O36ilEnEg>F>C0A3XV8c-jlnI`bjapLNW%u=@GY6q?lfD zc0&X+uk`IP$MTf&8bqeI?sB;~78yN41B@7iO_uVSp7u0lux#14Tz)!>pi%296yWI#G18qpRmN%rRk=gT>cFqYI9w_cgzc zSu9RO*m2>;=r^5_u@z`r7jqJr-MM$9AnsIC=?2Vfn!W(5jqa&Ec&X>?CJaW)3nF&3 zv@Y%R?Uv9$bUYIFI{;Vz*w>bRuQogw1q+!Lz{!3Qdz&u#7004rA*D>F9i>*E_({{?Urz;k{w0IjE&V zp0Rad%e!}sM3fx4tTC~xf^(g@(amuwnRhBs=V)tHE@F?@Bd$)R13L;cB}$CK zVgp=%XLr+dEO&)R0NO(|{iV}Q%Uh6In$y`d4U;OY2*3?)_ig4doG`UOyMKG_4;-dl zTmyj4+}08#!_Z=G2K2tW)i+Sq70*CmaYE7MN^{I&VIlx7H8?%W=)?iqORKVD%rINU z45qYV6$ZPA(wfcfY4SCY{7OeQqdy*IE973Hm-k8=c0_Zy7QN6@@&m~I__R^<5>ERH zK#tY_atxhSC>H_bhn~X`XcMCYAwYUU{I{YFjP^P3t8ZK95f<}HkJv$0O=w*!(Dtq?K*6&6dyNkMe4V;|HfepG= z{Y}xYoe{MtQP7a9T(reN0fua6{B+2)@%DnZs<9bp#+X43#hL zV<4YY&Az=mN8rs0xn>JX2mHJjS-!jS>hWlxXN2u_VFOCKxAS6DsDI~oD2?kKI|O-a z-%w9pa`vsaFrhS!0OnglMl)Zf)Y9hpJ4w5r#{3adCx|@MyYF1ozJ1r1 zVIpbLL5!l)legb(xs>f>G^qp z0~TW*3hNO(JaB6B<3>{m#Ff7=U4@AgrX>U-(Yk**76>uXx?9O3*SH&a*axMaA63$Z(wSXq_mf7rf&Ka zb4AD$U|rt}Eni~RQDy{0*}B=O7=pGuK-9Tb9>fr|SwLJ%xNqw)V}!j29L%|$-+(zN z?rNabEaYZ4rj^z`hzn5<^kd@0?CR+t^DTIUAs>T#heH}^v-ERZv+9tgmv$4`9d_fZAHa{uJ-v~cY6+`f3^g^XG07zgT2 z7GPojzq5X}SmBd{Stw)^IG^%WWiQDJGc;JGiu)uvpLK!f-O8_3U@p;K>E$f{MOomB zi4>E+m%ZF0EItA=Rmj2sd#3DSGzJsK98?d^EQ!Tbi}?{`ey^%Zz+?)08NfWR7N=q` zVG@DrKiWqg!c>ds!lMUR`-0F`3?@u> zQ2p19f9b?jiyNw!tz2fTIe1ygAANH^J9(;mImj;$m(DSo=3dtFCo}%O082wUGyq~K zs23f`XtMxBZNe`40?O3y*Q?9)d-#B}LR#~>+iZPeG8Bs!4zER>OhatodjF!^Em*vUwU zEp6K)Fi|wjK1*bzGCY=h?7jvLsOt!E_z&jG8ur2Q%z`WB1N+~19d+FDQGO@7h9Wh8G$+9VGb|of}CJdlRY9}>F z8!;43Z*YV#;uHD*Xv7>5vLXm1nYA%zek&%BW|xmrMsnx9m%ZCDNA&UsB$B$wurD6P zB+}aOagY&0ARmJhBOD@OLvw;N>7oz5lcw=S6gCd9l+=uCo5Ak}fIvcrH$Pru z^s507CPGl(uK&vTHv_;i(g{z#lw#r+17HK8`gNQ0O#EH|aSteL?H^Yg`dR?EM_QQo zMk}M=3IGcT#*4na04`J;B*3k2V+K#h;qksD;_yc)Qqcoyk#Lc8A3H=yC zFCj7?-oU(Q;?-B}!a=fXH{fX~<|(xkHY$|LGTGj59+10bDczt^9Jf<&^(7V?u(V+rX5(5RDK_ zDdWUE%sht$Q#jzN-MG0FI?*PhTcJHoWu)pg4A!3X9u3rsIXDLbB@s3bx96sS1DFBA z+oRfnlLE{*4w695yvRT_koHfnVk8M3fD9#p4(!O8%iY$^LRAZAe6=e#TMINLxOy9* z`OaV%Ys_Lg{;KUcmO!*2MI6(?mT}Wm%U7&ew$gRw(xt9g28rJU)SqzPf=v^x|8IXc zQ7O!6%b9r$TCTkAio-u918M&X6W;E?`l*bm^pWiNr&c6o6=uoJavmpfag) zgjAVzGQ~IlJbqZ7W|+XVJVy!h&I?p9AG|~jQ%h$Wm^b+{Q$(Lc // Find*File(). :( -#include -#include +// #include #else #include #include #endif #include +#include + namespace google { namespace protobuf { #ifdef _WIN32 -#define mkdir(name, mode) mkdir(name) // Windows doesn't have symbolic links. #define lstat stat -#ifndef F_OK -#define F_OK 00 // not defined by MSVC for whatever reason +// DO NOT include , instead create functions in io_win32.{h,cc} and import +// them like we do below. #endif + +#ifdef _WIN32 +using google::protobuf::internal::win32::access; +using google::protobuf::internal::win32::chdir; +using google::protobuf::internal::win32::fopen; +using google::protobuf::internal::win32::mkdir; +using google::protobuf::internal::win32::stat; #endif bool File::Exists(const string& name) { @@ -91,6 +98,7 @@ bool File::WriteStringToFile(const string& contents, const string& name) { if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) { GOOGLE_LOG(ERROR) << "fwrite(" << name << "): " << strerror(errno); + fclose(file); return false; } @@ -112,6 +120,9 @@ void File::WriteStringToFileOrDie(const string& contents, const string& name) { } bool File::CreateDir(const string& name, int mode) { + if (!name.empty()) { + GOOGLE_CHECK_OK(name[name.size() - 1] != '.'); + } return mkdir(name.c_str(), mode) == 0; } @@ -133,17 +144,19 @@ bool File::RecursivelyCreateDir(const string& path, int mode) { void File::DeleteRecursively(const string& name, void* dummy1, void* dummy2) { + if (name.empty()) return; + // We don't care too much about error checking here since this is only used // in tests to delete temporary directories that are under /tmp anyway. #ifdef _MSC_VER // This interface is so weird. - WIN32_FIND_DATA find_data; - HANDLE find_handle = FindFirstFile((name + "/*").c_str(), &find_data); + WIN32_FIND_DATAA find_data; + HANDLE find_handle = FindFirstFileA((name + "/*").c_str(), &find_data); if (find_handle == INVALID_HANDLE_VALUE) { // Just delete it, whatever it is. - DeleteFile(name.c_str()); - RemoveDirectory(name.c_str()); + DeleteFileA(name.c_str()); + RemoveDirectoryA(name.c_str()); return; } @@ -153,15 +166,15 @@ void File::DeleteRecursively(const string& name, string path = name + "/" + entry_name; if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { DeleteRecursively(path, NULL, NULL); - RemoveDirectory(path.c_str()); + RemoveDirectoryA(path.c_str()); } else { - DeleteFile(path.c_str()); + DeleteFileA(path.c_str()); } } - } while(FindNextFile(find_handle, &find_data)); + } while(FindNextFileA(find_handle, &find_data)); FindClose(find_handle); - RemoveDirectory(name.c_str()); + RemoveDirectoryA(name.c_str()); #else // Use opendir()! Yay! // lstat = Don't follow symbolic links. @@ -190,5 +203,9 @@ void File::DeleteRecursively(const string& name, #endif } +bool File::ChangeWorkingDirectory(const string& new_working_directory) { + return chdir(new_working_directory.c_str()) == 0; +} + } // namespace protobuf } // namespace google diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/file.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/file.h similarity index 96% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/file.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/file.h index d2aeabf2b..2f63f80e7 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/file.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/file.h @@ -77,6 +77,9 @@ class File { static void DeleteRecursively(const string& name, void* dummy1, void* dummy2); + // Change working directory to given directory. + static bool ChangeWorkingDirectory(const string& new_working_directory); + static bool GetContents( const string& name, string* output, bool /*is_default*/) { return ReadFileToString(name, output); diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/googletest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/googletest.cc similarity index 73% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/googletest.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/googletest.cc index d72fa5c00..8c89e5afb 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/googletest.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/googletest.cc @@ -33,14 +33,14 @@ #include #include +#include #include #include #include #include #include #ifdef _MSC_VER -#include -#include +// #include #else #include #endif @@ -53,7 +53,13 @@ namespace google { namespace protobuf { #ifdef _WIN32 -#define mkdir(name, mode) mkdir(name) +// DO NOT include , instead create functions in io_win32.{h,cc} and import +// them like we do below. +using google::protobuf::internal::win32::close; +using google::protobuf::internal::win32::dup2; +using google::protobuf::internal::win32::dup; +using google::protobuf::internal::win32::mkdir; +using google::protobuf::internal::win32::open; #endif #ifndef O_BINARY @@ -65,7 +71,18 @@ namespace protobuf { #endif string TestSourceDir() { -#ifdef _MSC_VER +#ifndef GOOGLE_THIRD_PARTY_PROTOBUF +#ifdef GOOGLE_PROTOBUF_TEST_SOURCE_PATH + return GOOGLE_PROTOBUF_TEST_SOURCE_PATH; +#else +#ifndef _MSC_VER + // automake sets the "srcdir" environment variable. + char* result = getenv("srcdir"); + if (result != NULL) { + return result; + } +#endif // _MSC_VER + // Look for the "src" directory. string prefix = "."; @@ -78,32 +95,55 @@ string TestSourceDir() { prefix += "/.."; } return prefix + "/src"; +#endif // GOOGLE_PROTOBUF_TEST_SOURCE_PATH #else - // automake sets the "srcdir" environment variable. - char* result = getenv("srcdir"); - if (result == NULL) { - // Otherwise, the test must be run from the source directory. - return "."; - } else { - return result; - } -#endif + return "third_party/protobuf/src"; +#endif // GOOGLE_THIRD_PARTY_PROTOBUF } namespace { string GetTemporaryDirectoryName() { + // Tests run under Bazel "should not" use /tmp. Bazel sets this environment + // variable for tests to use instead. + char *from_environment = getenv("TEST_TMPDIR"); + if (from_environment != NULL && from_environment[0] != '\0') { + return string(from_environment) + "/protobuf_tmpdir"; + } + // tmpnam() is generally not considered safe but we're only using it for // testing. We cannot use tmpfile() or mkstemp() since we're creating a // directory. char b[L_tmpnam + 1]; // HPUX multithread return 0 if s is 0 string result = tmpnam(b); #ifdef _WIN32 + // Avoid a trailing dot by changing it to an underscore. On Win32 the names of + // files and directories can, but should not, end with dot. + // + // In MS-DOS and FAT16 filesystem the filenames were 8dot3 style so it didn't + // make sense to have a name ending in dot without an extension, so the shell + // silently ignored trailing dots. To this day the Win32 API still maintains + // this behavior and silently ignores trailing dots in path arguments of + // functions such as CreateFile{A,W}. Even POSIX API function implementations + // seem to wrap the Win32 API functions (e.g. CreateDirectoryA) and behave + // this way. + // It's possible to avoid this behavior and create files / directories with + // trailing dots (using CreateFileW / CreateDirectoryW and prefixing the path + // with "\\?\") but these will be degenerate in the sense that you cannot + // chdir into such directories (or navigate into them with Windows Explorer) + // nor can you open such files with some programs (e.g. Notepad). + if (result[result.size() - 1] == '.') { + result[result.size() - 1] = '_'; + } // On Win32, tmpnam() returns a file prefixed with '\', but which is supposed // to be used in the current working directory. WTF? if (HasPrefixString(result, "\\")) { result.erase(0, 1); } + // The Win32 API accepts forward slashes as a path delimiter as long as the + // path doesn't use the "\\?\" prefix. + // Let's avoid confusion and use only forward slashes. + result = StringReplace(result, "\\", "/", true); #endif // _WIN32 return result; } @@ -223,7 +263,7 @@ ScopedMemoryLog::~ScopedMemoryLog() { active_log_ = NULL; } -const vector& ScopedMemoryLog::GetMessages(LogLevel level) { +const std::vector& ScopedMemoryLog::GetMessages(LogLevel level) { GOOGLE_CHECK(level == ERROR || level == WARNING); return messages_[level]; @@ -246,6 +286,8 @@ namespace { struct ForceShutdown { ~ForceShutdown() { ShutdownProtobufLibrary(); + // Test to shutdown the library twice, which should succeed. + ShutdownProtobufLibrary(); } } force_shutdown; diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/googletest.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/googletest.h similarity index 94% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/googletest.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/googletest.h index c0d99e69a..816374860 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/googletest.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/googletest.h @@ -37,9 +37,10 @@ #include #include #include - +#include // Disable death tests if we use exceptions in CHECK(). -#if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST) +#if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST) && \ + !GTEST_OS_WINDOWS #define PROTOBUF_HAS_DEATH_TEST #endif @@ -82,10 +83,10 @@ class ScopedMemoryLog { virtual ~ScopedMemoryLog(); // Fetches all messages with the given severity level. - const vector& GetMessages(LogLevel error); + const std::vector& GetMessages(LogLevel error); private: - map > messages_; + std::map > messages_; LogHandler* old_handler_; static void HandleLog(LogLevel level, const char* filename, int line, diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/zcgunzip.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/zcgunzip.cc similarity index 91% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/zcgunzip.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/zcgunzip.cc index daf74ff1f..349ad86ee 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/zcgunzip.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/zcgunzip.cc @@ -38,13 +38,20 @@ // Reads gzip stream on standard input and writes decompressed data to standard // output. -#include "config.h" - #include #include #include #include +#ifdef _WIN32 +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif +#endif + #include #include @@ -65,7 +72,10 @@ int main(int argc, const char** argv) { } if (inlen > 0) { int err = write(STDOUT_FILENO, inptr, inlen); - assert(err == inlen); + if (err != inlen) { + fprintf(stderr, "write unexpectedly returned %d.\n", err); + return 1; + } } } diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/zcgzip.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/zcgzip.cc similarity index 95% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/zcgzip.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/zcgzip.cc index a41019996..992ddc6ed 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/testing/zcgzip.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/testing/zcgzip.cc @@ -38,12 +38,19 @@ // Reads data on standard input and writes compressed gzip stream to standard // output. -#include "config.h" - #include #include #include +#ifdef _WIN32 +#ifndef STDIN_FILENO +#define STDIN_FILENO 0 +#endif +#ifndef STDOUT_FILENO +#define STDOUT_FILENO 1 +#endif +#endif + #include #include diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/text_format.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/text_format.cc similarity index 61% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/text_format.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/text_format.cc index c82cf72f3..0732ac352 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/text_format.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/text_format.cc @@ -42,15 +42,22 @@ #include -#include -#include +#include +#include +#include #include +#include #include #include -#include #include -#include +#include +#include +#include +#include +#include #include + + #include #include @@ -74,7 +81,10 @@ inline bool IsOctNumber(const string& str) { string Message::DebugString() const { string debug_string; - TextFormat::PrintToString(*this, &debug_string); + TextFormat::Printer printer; + printer.SetExpandAny(true); + + printer.PrintToString(*this, &debug_string); return debug_string; } @@ -84,6 +94,7 @@ string Message::ShortDebugString() const { TextFormat::Printer printer; printer.SetSingleLineMode(true); + printer.SetExpandAny(true); printer.PrintToString(*this, &debug_string); // Single line mode currently might have an extra space at the end. @@ -100,6 +111,7 @@ string Message::Utf8DebugString() const { TextFormat::Printer printer; printer.SetUseUtf8StringEscaping(true); + printer.SetExpandAny(true); printer.PrintToString(*this, &debug_string); @@ -132,7 +144,7 @@ TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::CreateNested( const FieldDescriptor* field) { // Owned by us in the map. TextFormat::ParseInfoTree* instance = new TextFormat::ParseInfoTree(); - vector* trees = &nested_[field]; + std::vector* trees = &nested_[field]; GOOGLE_CHECK(trees); trees->push_back(instance); return instance; @@ -155,7 +167,7 @@ TextFormat::ParseLocation TextFormat::ParseInfoTree::GetLocation( CheckFieldIndex(field, index); if (index == -1) { index = 0; } - const vector* locations = + const std::vector* locations = FindOrNull(locations_, field); if (locations == NULL || index >= locations->size()) { return TextFormat::ParseLocation(); @@ -169,7 +181,8 @@ TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( CheckFieldIndex(field, index); if (index == -1) { index = 0; } - const vector* trees = FindOrNull(nested_, field); + const std::vector* trees = + FindOrNull(nested_, field); if (trees == NULL || index >= trees->size()) { return NULL; } @@ -177,6 +190,24 @@ TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested( return (*trees)[index]; } +namespace { +// These functions implement the behavior of the "default" TextFormat::Finder, +// they are defined as standalone to be called when finder_ is NULL. +const FieldDescriptor* DefaultFinderFindExtension(Message* message, + const string& name) { + return message->GetReflection()->FindKnownExtensionByName(name); +} + +const Descriptor* DefaultFinderFindAnyType(const Message& message, + const string& prefix, + const string& name) { + if (prefix != internal::kTypeGoogleApisComPrefix && + prefix != internal::kTypeGoogleProdComPrefix) { + return NULL; + } + return message.GetDescriptor()->file()->pool()->FindMessageTypeByName(name); +} +} // namespace // =========================================================================== // Internal class for parsing an ASCII representation of a Protocol Message. @@ -205,14 +236,15 @@ class TextFormat::Parser::ParserImpl { ParserImpl(const Descriptor* root_message_type, io::ZeroCopyInputStream* input_stream, io::ErrorCollector* error_collector, - TextFormat::Finder* finder, + const TextFormat::Finder* finder, ParseInfoTree* parse_info_tree, SingularOverwritePolicy singular_overwrite_policy, bool allow_case_insensitive_field, bool allow_unknown_field, bool allow_unknown_enum, bool allow_field_number, - bool allow_relaxed_whitespace) + bool allow_relaxed_whitespace, + bool allow_partial) : error_collector_(error_collector), finder_(finder), parse_info_tree_(parse_info_tree), @@ -224,6 +256,7 @@ class TextFormat::Parser::ParserImpl { allow_unknown_field_(allow_unknown_field), allow_unknown_enum_(allow_unknown_enum), allow_field_number_(allow_field_number), + allow_partial_(allow_partial), had_errors_(false) { // For backwards-compatibility with proto1, we need to allow the 'f' suffix // for floats. @@ -319,17 +352,27 @@ class TextFormat::Parser::ParserImpl { message); } - // Consumes the specified message with the given starting delimeter. - // This method checks to see that the end delimeter at the conclusion of - // the consumption matches the starting delimeter passed in here. - bool ConsumeMessage(Message* message, const string delimeter) { + // Consumes the specified message with the given starting delimiter. + // This method checks to see that the end delimiter at the conclusion of + // the consumption matches the starting delimiter passed in here. + bool ConsumeMessage(Message* message, const string delimiter) { while (!LookingAt(">") && !LookingAt("}")) { DO(ConsumeField(message)); } - // Confirm that we have a valid ending delimeter. - DO(Consume(delimeter)); + // Confirm that we have a valid ending delimiter. + DO(Consume(delimiter)); + return true; + } + // Consume either "<" or "{". + bool ConsumeMessageDelimiter(string* delimiter) { + if (TryConsume("<")) { + *delimiter = ">"; + } else { + DO(Consume("{")); + *delimiter = "}"; + } return true; } @@ -341,25 +384,53 @@ class TextFormat::Parser::ParserImpl { const Descriptor* descriptor = message->GetDescriptor(); string field_name; - + bool reserved_field = false; const FieldDescriptor* field = NULL; int start_line = tokenizer_.current().line; int start_column = tokenizer_.current().column; + const FieldDescriptor* any_type_url_field; + const FieldDescriptor* any_value_field; + if (internal::GetAnyFieldDescriptors(*message, &any_type_url_field, + &any_value_field) && + TryConsume("[")) { + string full_type_name, prefix; + DO(ConsumeAnyTypeUrl(&full_type_name, &prefix)); + DO(Consume("]")); + TryConsume(":"); // ':' is optional between message labels and values. + string serialized_value; + const Descriptor* value_descriptor = + finder_ ? finder_->FindAnyType(*message, prefix, full_type_name) + : DefaultFinderFindAnyType(*message, prefix, full_type_name); + if (value_descriptor == NULL) { + ReportError("Could not find type \"" + prefix + full_type_name + + "\" stored in google.protobuf.Any."); + return false; + } + DO(ConsumeAnyValue(value_descriptor, &serialized_value)); + if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) { + // Fail if any_type_url_field has already been specified. + if ((!any_type_url_field->is_repeated() && + reflection->HasField(*message, any_type_url_field)) || + (!any_value_field->is_repeated() && + reflection->HasField(*message, any_value_field))) { + ReportError("Non-repeated Any specified multiple times."); + return false; + } + } + reflection->SetString( + message, any_type_url_field, + string(prefix + full_type_name)); + reflection->SetString(message, any_value_field, serialized_value); + return true; + } if (TryConsume("[")) { // Extension. - DO(ConsumeIdentifier(&field_name)); - while (TryConsume(".")) { - string part; - DO(ConsumeIdentifier(&part)); - field_name += "."; - field_name += part; - } + DO(ConsumeFullTypeName(&field_name)); DO(Consume("]")); - field = (finder_ != NULL - ? finder_->FindExtension(message, field_name) - : reflection->FindKnownExtensionByName(field_name)); + field = finder_ ? finder_->FindExtension(message, field_name) + : DefaultFinderFindExtension(message, field_name); if (field == NULL) { if (!allow_unknown_field_) { @@ -380,6 +451,8 @@ class TextFormat::Parser::ParserImpl { if (allow_field_number_ && safe_strto32(field_name, &field_number)) { if (descriptor->IsExtensionNumber(field_number)) { field = reflection->FindKnownExtensionByNumber(field_number); + } else if (descriptor->IsReservedNumber(field_number)) { + reserved_field = true; } else { field = descriptor->FindFieldByNumber(field_number); } @@ -408,9 +481,13 @@ class TextFormat::Parser::ParserImpl { LowerString(&lower_field_name); field = descriptor->FindFieldByLowercaseName(lower_field_name); } + + if (field == NULL) { + reserved_field = descriptor->IsReservedName(field_name); + } } - if (field == NULL) { + if (field == NULL && !reserved_field) { if (!allow_unknown_field_) { ReportError("Message type \"" + descriptor->full_name() + "\" has no field named \"" + field_name + "\"."); @@ -422,13 +499,14 @@ class TextFormat::Parser::ParserImpl { } } - // Skips unknown field. + // Skips unknown or reserved fields. if (field == NULL) { - GOOGLE_CHECK(allow_unknown_field_); + GOOGLE_CHECK(allow_unknown_field_ || reserved_field); + // Try to guess the type of this field. // If this field is not a message, there should be a ":" between the // field name and the field value and also the field value should not - // start with "{" or "<" which indicates the begining of a message body. + // start with "{" or "<" which indicates the beginning of a message body. // If there is no ":" or there is a "{" or "<" after ":", this field has // to be a message or the input is ill-formed. if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) { @@ -461,32 +539,42 @@ class TextFormat::Parser::ParserImpl { // Perform special handling for embedded message types. if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { // ':' is optional here. - TryConsume(":"); + bool consumed_semicolon = TryConsume(":"); + if (consumed_semicolon && field->options().weak() && LookingAtType(io::Tokenizer::TYPE_STRING)) { + // we are getting a bytes string for a weak field. + string tmp; + DO(ConsumeString(&tmp)); + reflection->MutableMessage(message, field)->ParseFromString(tmp); + goto label_skip_parsing; + } } else { // ':' is required here. DO(Consume(":")); } if (field->is_repeated() && TryConsume("[")) { - // Short repeated format, e.g. "foo: [1, 2, 3]" - while (true) { - if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - // Perform special handling for embedded message types. - DO(ConsumeFieldMessage(message, reflection, field)); - } else { - DO(ConsumeFieldValue(message, reflection, field)); - } - if (TryConsume("]")) { - break; + // Short repeated format, e.g. "foo: [1, 2, 3]". + if (!TryConsume("]")) { + // "foo: []" is treated as empty. + while (true) { + if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { + // Perform special handling for embedded message types. + DO(ConsumeFieldMessage(message, reflection, field)); + } else { + DO(ConsumeFieldValue(message, reflection, field)); + } + if (TryConsume("]")) { + break; + } + DO(Consume(",")); } - DO(Consume(",")); } } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { DO(ConsumeFieldMessage(message, reflection, field)); } else { DO(ConsumeFieldValue(message, reflection, field)); } - +label_skip_parsing: // For historical reasons, fields may optionally be separated by commas or // semicolons. TryConsume(";") || TryConsume(","); @@ -508,25 +596,19 @@ class TextFormat::Parser::ParserImpl { // Skips the next field including the field's name and value. bool SkipField() { - string field_name; if (TryConsume("[")) { - // Extension name. - DO(ConsumeIdentifier(&field_name)); - while (TryConsume(".")) { - string part; - DO(ConsumeIdentifier(&part)); - field_name += "."; - field_name += part; - } + // Extension name or type URL. + DO(ConsumeTypeUrlOrFullTypeName()); DO(Consume("]")); } else { + string field_name; DO(ConsumeIdentifier(&field_name)); } // Try to guess the type of this field. // If this field is not a message, there should be a ":" between the // field name and the field value and also the field value should not - // start with "{" or "<" which indicates the begining of a message body. + // start with "{" or "<" which indicates the beginning of a message body. // If there is no ":" or there is a "{" or "<" after ":", this field has // to be a message or the input is ill-formed. if (TryConsume(":") && !LookingAt("{") && !LookingAt("<")) { @@ -551,19 +633,13 @@ class TextFormat::Parser::ParserImpl { parse_info_tree_ = CreateNested(parent, field); } - string delimeter; - if (TryConsume("<")) { - delimeter = ">"; - } else { - DO(Consume("{")); - delimeter = "}"; - } - + string delimiter; + DO(ConsumeMessageDelimiter(&delimiter)); if (field->is_repeated()) { - DO(ConsumeMessage(reflection->AddMessage(message, field), delimeter)); + DO(ConsumeMessage(reflection->AddMessage(message, field), delimiter)); } else { DO(ConsumeMessage(reflection->MutableMessage(message, field), - delimeter)); + delimiter)); } // Reset the parse information tree. @@ -571,20 +647,15 @@ class TextFormat::Parser::ParserImpl { return true; } - // Skips the whole body of a message including the begining delimeter and - // the ending delimeter. + // Skips the whole body of a message including the beginning delimiter and + // the ending delimiter. bool SkipFieldMessage() { - string delimeter; - if (TryConsume("<")) { - delimeter = ">"; - } else { - DO(Consume("{")); - delimeter = "}"; - } + string delimiter; + DO(ConsumeMessageDelimiter(&delimiter)); while (!LookingAt(">") && !LookingAt("}")) { DO(SkipField()); } - DO(Consume(delimeter)); + DO(Consume(delimiter)); return true; } @@ -634,7 +705,7 @@ class TextFormat::Parser::ParserImpl { case FieldDescriptor::CPPTYPE_FLOAT: { double value; DO(ConsumeDouble(&value)); - SET_FIELD(Float, static_cast(value)); + SET_FIELD(Float, io::SafeDoubleToFloat(value)); break; } @@ -690,7 +761,8 @@ class TextFormat::Parser::ParserImpl { value = SimpleItoa(int_value); // for error reporting enum_value = enum_type->FindValueByNumber(int_value); } else { - ReportError("Expected integer or identifier."); + ReportError("Expected integer or identifier, got: " + + tokenizer_.current().text); return false; } @@ -728,6 +800,20 @@ class TextFormat::Parser::ParserImpl { } return true; } + if (TryConsume("[")) { + while (true) { + if (!LookingAt("{") && !LookingAt("<")) { + DO(SkipFieldValue()); + } else { + DO(SkipFieldMessage()); + } + if (TryConsume("]")) { + break; + } + DO(Consume(",")); + } + return true; + } // Possible field values other than string: // 12345 => TYPE_INTEGER // -12345 => TYPE_SYMBOL + TYPE_INTEGER @@ -803,15 +889,36 @@ class TextFormat::Parser::ParserImpl { return true; } - ReportError("Expected identifier."); + ReportError("Expected identifier, got: " + tokenizer_.current().text); return false; } + // Consume a string of form ".....". + bool ConsumeFullTypeName(string* name) { + DO(ConsumeIdentifier(name)); + while (TryConsume(".")) { + string part; + DO(ConsumeIdentifier(&part)); + *name += "."; + *name += part; + } + return true; + } + + bool ConsumeTypeUrlOrFullTypeName() { + string discarded; + DO(ConsumeIdentifier(&discarded)); + while (TryConsume(".") || TryConsume("/")) { + DO(ConsumeIdentifier(&discarded)); + } + return true; + } + // Consumes a string and saves its value in the text parameter. // Returns false if the token is not of type STRING. bool ConsumeString(string* text) { if (!LookingAtType(io::Tokenizer::TYPE_STRING)) { - ReportError("Expected string."); + ReportError("Expected string, got: " + tokenizer_.current().text); return false; } @@ -829,13 +936,13 @@ class TextFormat::Parser::ParserImpl { // Returns false if the token is not of type INTEGER. bool ConsumeUnsignedInteger(uint64* value, uint64 max_value) { if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) { - ReportError("Expected integer."); + ReportError("Expected integer, got: " + tokenizer_.current().text); return false; } if (!io::Tokenizer::ParseInteger(tokenizer_.current().text, max_value, value)) { - ReportError("Integer out of range."); + ReportError("Integer out of range (" + tokenizer_.current().text + ")"); return false; } @@ -862,10 +969,14 @@ class TextFormat::Parser::ParserImpl { DO(ConsumeUnsignedInteger(&unsigned_value, max_value)); - *value = static_cast(unsigned_value); - if (negative) { - *value = -*value; + if ((static_cast(kint64max) + 1) == unsigned_value) { + *value = kint64min; + } else { + *value = -static_cast(unsigned_value); + } + } else { + *value = static_cast(unsigned_value); } return true; @@ -875,18 +986,18 @@ class TextFormat::Parser::ParserImpl { // Accepts decimal numbers only, rejects hex or oct numbers. bool ConsumeUnsignedDecimalInteger(uint64* value, uint64 max_value) { if (!LookingAtType(io::Tokenizer::TYPE_INTEGER)) { - ReportError("Expected integer."); + ReportError("Expected integer, got: " + tokenizer_.current().text); return false; } const string& text = tokenizer_.current().text; if (IsHexNumber(text) || IsOctNumber(text)) { - ReportError("Expect a decimal number."); + ReportError("Expect a decimal number, got: " + text); return false; } if (!io::Tokenizer::ParseInteger(text, max_value, value)) { - ReportError("Integer out of range."); + ReportError("Integer out of range (" + text + ")"); return false; } @@ -931,11 +1042,11 @@ class TextFormat::Parser::ParserImpl { *value = std::numeric_limits::quiet_NaN(); tokenizer_.Next(); } else { - ReportError("Expected double."); + ReportError("Expected double, got: " + text); return false; } } else { - ReportError("Expected double."); + ReportError("Expected double, got: " + tokenizer_.current().text); return false; } @@ -946,6 +1057,52 @@ class TextFormat::Parser::ParserImpl { return true; } + // Consumes Any::type_url value, of form "type.googleapis.com/full.type.Name" + // or "type.googleprod.com/full.type.Name" + bool ConsumeAnyTypeUrl(string* full_type_name, string* prefix) { + // TODO(saito) Extend Consume() to consume multiple tokens at once, so that + // this code can be written as just DO(Consume(kGoogleApisTypePrefix)). + DO(ConsumeIdentifier(prefix)); + while (TryConsume(".")) { + string url; + DO(ConsumeIdentifier(&url)); + *prefix += "." + url; + } + DO(Consume("/")); + *prefix += "/"; + DO(ConsumeFullTypeName(full_type_name)); + + return true; + } + + // A helper function for reconstructing Any::value. Consumes a text of + // full_type_name, then serializes it into serialized_value. + bool ConsumeAnyValue(const Descriptor* value_descriptor, + string* serialized_value) { + DynamicMessageFactory factory; + const Message* value_prototype = factory.GetPrototype(value_descriptor); + if (value_prototype == NULL) { + return false; + } + std::unique_ptr value(value_prototype->New()); + string sub_delimiter; + DO(ConsumeMessageDelimiter(&sub_delimiter)); + DO(ConsumeMessage(value.get(), sub_delimiter)); + + if (allow_partial_) { + value->AppendPartialToString(serialized_value); + } else { + if (!value->IsInitialized()) { + ReportError( + "Value of type \"" + value_descriptor->full_name() + + "\" stored in google.protobuf.Any has missing required fields"); + return false; + } + value->AppendToString(serialized_value); + } + return true; + } + // Consumes a token and confirms that it matches that specified in the // value parameter. Returns false if the token found does not match that // which was specified. @@ -997,7 +1154,7 @@ class TextFormat::Parser::ParserImpl { }; io::ErrorCollector* error_collector_; - TextFormat::Finder* finder_; + const TextFormat::Finder* finder_; ParseInfoTree* parse_info_tree_; ParserErrorCollector tokenizer_error_collector_; io::Tokenizer tokenizer_; @@ -1007,6 +1164,7 @@ class TextFormat::Parser::ParserImpl { const bool allow_unknown_field_; const bool allow_unknown_enum_; const bool allow_field_number_; + const bool allow_partial_; bool had_errors_; }; @@ -1015,7 +1173,8 @@ class TextFormat::Parser::ParserImpl { // =========================================================================== // Internal class for writing text to the io::ZeroCopyOutputStream. Adapted // from the Printer found in //google/protobuf/io/printer.h -class TextFormat::Printer::TextGenerator { +class TextFormat::Printer::TextGenerator + : public TextFormat::BaseTextGenerator { public: explicit TextGenerator(io::ZeroCopyOutputStream* output, int initial_indent_level) @@ -1024,9 +1183,8 @@ class TextFormat::Printer::TextGenerator { buffer_size_(0), at_start_of_line_(true), failed_(false), - indent_(""), + indent_level_(initial_indent_level), initial_indent_level_(initial_indent_level) { - indent_.resize(initial_indent_level_ * 2, ' '); } ~TextGenerator() { @@ -1040,51 +1198,44 @@ class TextFormat::Printer::TextGenerator { // Indent text by two spaces. After calling Indent(), two spaces will be // inserted at the beginning of each line of text. Indent() may be called // multiple times to produce deeper indents. - void Indent() { - indent_ += " "; - } + void Indent() override { ++indent_level_; } // Reduces the current indent level by two spaces, or crashes if the indent // level is zero. - void Outdent() { - if (indent_.empty() || - indent_.size() < initial_indent_level_ * 2) { + void Outdent() override { + if (indent_level_ == 0 || + indent_level_ < initial_indent_level_) { GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent()."; return; } - indent_.resize(indent_.size() - 2); + --indent_level_; } // Print text to the output stream. - void Print(const string& str) { - Print(str.data(), str.size()); - } - - // Print text to the output stream. - void Print(const char* text) { - Print(text, strlen(text)); - } - - // Print text to the output stream. - void Print(const char* text, int size) { - int pos = 0; // The number of bytes we've written so far. - - for (int i = 0; i < size; i++) { - if (text[i] == '\n') { - // Saw newline. If there is more text, we may need to insert an indent - // here. So, write what we have so far, including the '\n'. - Write(text + pos, i - pos + 1); - pos = i + 1; - - // Setting this true will cause the next Write() to insert an indent - // first. + void Print(const char* text, size_t size) override { + if (indent_level_ > 0) { + size_t pos = 0; // The number of bytes we've written so far. + for (size_t i = 0; i < size; i++) { + if (text[i] == '\n') { + // Saw newline. If there is more text, we may need to insert an + // indent here. So, write what we have so far, including the '\n'. + Write(text + pos, i - pos + 1); + pos = i + 1; + + // Setting this true will cause the next Write() to insert an indent + // first. + at_start_of_line_ = true; + } + } + // Write the rest. + Write(text + pos, size - pos); + } else { + Write(text, size); + if (size > 0 && text[size - 1] == '\n') { at_start_of_line_ = true; } } - - // Write the rest. - Write(text + pos, size - pos); } // True if any write to the underlying stream failed. (We don't just @@ -1095,23 +1246,47 @@ class TextFormat::Printer::TextGenerator { private: GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator); - void Write(const char* data, int size) { + void Write(const char* data, size_t size) { if (failed_) return; if (size == 0) return; if (at_start_of_line_) { // Insert an indent. at_start_of_line_ = false; - Write(indent_.data(), indent_.size()); + WriteIndent(); if (failed_) return; } while (size > buffer_size_) { // Data exceeds space in the buffer. Copy what we can and request a // new buffer. - if (buffer_size_ > 0) + if (buffer_size_ > 0) { memcpy(buffer_, data, buffer_size_); - data += buffer_size_; + data += buffer_size_; + size -= buffer_size_; + } + void* void_buffer = NULL; + failed_ = !output_->Next(&void_buffer, &buffer_size_); + if (failed_) return; + buffer_ = reinterpret_cast(void_buffer); + } + + // Buffer is big enough to receive the data; copy it. + memcpy(buffer_, data, size); + buffer_ += size; + buffer_size_ -= size; + } + + void WriteIndent() { + if (indent_level_ == 0) { return; } + GOOGLE_DCHECK(!failed_); + int size = 2 * indent_level_; + + while (size > buffer_size_) { + // Data exceeds space in the buffer. Write what we can and request a new + // buffer. + if (buffer_) + memset(buffer_, ' ', buffer_size_); size -= buffer_size_; void* void_buffer; failed_ = !output_->Next(&void_buffer, &buffer_size_); @@ -1120,7 +1295,7 @@ class TextFormat::Printer::TextGenerator { } // Buffer is big enough to receive the data; copy it. - memcpy(buffer_, data, size); + memset(buffer_, ' ', size); buffer_ += size; buffer_size_ -= size; } @@ -1131,15 +1306,28 @@ class TextFormat::Printer::TextGenerator { bool at_start_of_line_; bool failed_; - string indent_; + int indent_level_; int initial_indent_level_; }; // =========================================================================== - +// Implementation of the default Finder for extensions. TextFormat::Finder::~Finder() { } +const FieldDescriptor* TextFormat::Finder::FindExtension( + Message* message, const string& name) const { + return DefaultFinderFindExtension(message, name); +} + +const Descriptor* TextFormat::Finder::FindAnyType(const Message& message, + const string& prefix, + const string& name) const { + return DefaultFinderFindAnyType(message, prefix, name); +} + +// =========================================================================== + TextFormat::Parser::Parser() : error_collector_(NULL), finder_(NULL), @@ -1169,7 +1357,7 @@ bool TextFormat::Parser::Parse(io::ZeroCopyInputStream* input, overwrites_policy, allow_case_insensitive_field_, allow_unknown_field_, allow_unknown_enum_, allow_field_number_, - allow_relaxed_whitespace_); + allow_relaxed_whitespace_, allow_partial_); return MergeUsingImpl(input, output, &parser); } @@ -1179,6 +1367,7 @@ bool TextFormat::Parser::ParseFromString(const string& input, return Parse(&input_stream, output); } + bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, Message* output) { ParserImpl parser(output->GetDescriptor(), input, error_collector_, @@ -1186,7 +1375,7 @@ bool TextFormat::Parser::Merge(io::ZeroCopyInputStream* input, ParserImpl::ALLOW_SINGULAR_OVERWRITES, allow_case_insensitive_field_, allow_unknown_field_, allow_unknown_enum_, allow_field_number_, - allow_relaxed_whitespace_); + allow_relaxed_whitespace_, allow_partial_); return MergeUsingImpl(input, output, &parser); } @@ -1196,15 +1385,17 @@ bool TextFormat::Parser::MergeFromString(const string& input, return Merge(&input_stream, output); } + bool TextFormat::Parser::MergeUsingImpl(io::ZeroCopyInputStream* /* input */, Message* output, ParserImpl* parser_impl) { if (!parser_impl->Parse(output)) return false; if (!allow_partial_ && !output->IsInitialized()) { - vector missing_fields; + std::vector missing_fields; output->FindInitializationErrors(&missing_fields); - parser_impl->ReportError(-1, 0, "Message missing required fields: " + - Join(missing_fields, ", ")); + parser_impl->ReportError(-1, 0, + "Message missing required fields: " + + Join(missing_fields, ", ")); return false; } return true; @@ -1220,7 +1411,7 @@ bool TextFormat::Parser::ParseFieldValueFromString( ParserImpl::ALLOW_SINGULAR_OVERWRITES, allow_case_insensitive_field_, allow_unknown_field_, allow_unknown_enum_, allow_field_number_, - allow_relaxed_whitespace_); + allow_relaxed_whitespace_, allow_partial_); return parser.ParseField(field, output); } @@ -1244,89 +1435,290 @@ bool TextFormat::Parser::ParseFieldValueFromString( return Parser().MergeFromString(input, output); } + // =========================================================================== -// The default implementation for FieldValuePrinter. The base class just -// does simple formatting. That way, deriving classes could decide to fallback -// to that behavior. +TextFormat::BaseTextGenerator::~BaseTextGenerator() {} + +namespace { + +// A BaseTextGenerator that writes to a string. +class StringBaseTextGenerator : public TextFormat::BaseTextGenerator { + public: + void Print(const char* text, size_t size) { output_.append(text, size); } + +// Some compilers do not support ref-qualifiers even in C++11 mode. +// Disable the optimization for now and revisit it later. +#if 0 // LANG_CXX11 + string Consume() && { return std::move(output_); } +#else // !LANG_CXX11 + const string& Get() { return output_; } +#endif // LANG_CXX11 + + private: + string output_; +}; + +} // namespace + +// The default implementation for FieldValuePrinter. We just delegate the +// implementation to the default FastFieldValuePrinter to avoid duplicating the +// logic. TextFormat::FieldValuePrinter::FieldValuePrinter() {} TextFormat::FieldValuePrinter::~FieldValuePrinter() {} + +#if 0 // LANG_CXX11 +#define FORWARD_IMPL(fn, ...) \ + StringBaseTextGenerator generator; \ + delegate_.fn(__VA_ARGS__, &generator); \ + return std::move(generator).Consume() +#else // !LANG_CXX11 +#define FORWARD_IMPL(fn, ...) \ + StringBaseTextGenerator generator; \ + delegate_.fn(__VA_ARGS__, &generator); \ + return generator.Get() +#endif // LANG_CXX11 + string TextFormat::FieldValuePrinter::PrintBool(bool val) const { - return val ? "true" : "false"; + FORWARD_IMPL(PrintBool, val); } string TextFormat::FieldValuePrinter::PrintInt32(int32 val) const { - return SimpleItoa(val); + FORWARD_IMPL(PrintInt32, val); } string TextFormat::FieldValuePrinter::PrintUInt32(uint32 val) const { - return SimpleItoa(val); + FORWARD_IMPL(PrintUInt32, val); } string TextFormat::FieldValuePrinter::PrintInt64(int64 val) const { - return SimpleItoa(val); + FORWARD_IMPL(PrintInt64, val); } string TextFormat::FieldValuePrinter::PrintUInt64(uint64 val) const { - return SimpleItoa(val); + FORWARD_IMPL(PrintUInt64, val); } string TextFormat::FieldValuePrinter::PrintFloat(float val) const { - return SimpleFtoa(val); + FORWARD_IMPL(PrintFloat, val); } string TextFormat::FieldValuePrinter::PrintDouble(double val) const { - return SimpleDtoa(val); + FORWARD_IMPL(PrintDouble, val); } string TextFormat::FieldValuePrinter::PrintString(const string& val) const { - return StrCat("\"", CEscape(val), "\""); + FORWARD_IMPL(PrintString, val); } string TextFormat::FieldValuePrinter::PrintBytes(const string& val) const { return PrintString(val); } string TextFormat::FieldValuePrinter::PrintEnum(int32 val, const string& name) const { - return name; + FORWARD_IMPL(PrintEnum, val, name); } string TextFormat::FieldValuePrinter::PrintFieldName( const Message& message, const Reflection* reflection, const FieldDescriptor* field) const { - if (field->is_extension()) { - // We special-case MessageSet elements for compatibility with proto1. - if (field->containing_type()->options().message_set_wire_format() - && field->type() == FieldDescriptor::TYPE_MESSAGE - && field->is_optional() - && field->extension_scope() == field->message_type()) { - return StrCat("[", field->message_type()->full_name(), "]"); - } else { - return StrCat("[", field->full_name(), "]"); - } - } else if (field->type() == FieldDescriptor::TYPE_GROUP) { - // Groups must be serialized with their original capitalization. - return field->message_type()->name(); - } else { - return field->name(); - } + FORWARD_IMPL(PrintFieldName, message, reflection, field); } string TextFormat::FieldValuePrinter::PrintMessageStart( const Message& message, int field_index, int field_count, bool single_line_mode) const { - return single_line_mode ? " { " : " {\n"; + FORWARD_IMPL(PrintMessageStart, message, field_index, field_count, + single_line_mode); } string TextFormat::FieldValuePrinter::PrintMessageEnd( const Message& message, int field_index, int field_count, bool single_line_mode) const { - return single_line_mode ? "} " : "}\n"; + FORWARD_IMPL(PrintMessageEnd, message, field_index, field_count, + single_line_mode); +} +#undef FORWARD_IMPL + +TextFormat::FastFieldValuePrinter::FastFieldValuePrinter() {} +TextFormat::FastFieldValuePrinter::~FastFieldValuePrinter() {} +void TextFormat::FastFieldValuePrinter::PrintBool( + bool val, BaseTextGenerator* generator) const { + if (val) { + generator->PrintLiteral("true"); + } else { + generator->PrintLiteral("false"); + } +} +void TextFormat::FastFieldValuePrinter::PrintInt32( + int32 val, BaseTextGenerator* generator) const { + generator->PrintString(SimpleItoa(val)); +} +void TextFormat::FastFieldValuePrinter::PrintUInt32( + uint32 val, BaseTextGenerator* generator) const { + generator->PrintString(SimpleItoa(val)); +} +void TextFormat::FastFieldValuePrinter::PrintInt64( + int64 val, BaseTextGenerator* generator) const { + generator->PrintString(SimpleItoa(val)); +} +void TextFormat::FastFieldValuePrinter::PrintUInt64( + uint64 val, BaseTextGenerator* generator) const { + generator->PrintString(SimpleItoa(val)); +} +void TextFormat::FastFieldValuePrinter::PrintFloat( + float val, BaseTextGenerator* generator) const { + generator->PrintString(SimpleFtoa(val)); +} +void TextFormat::FastFieldValuePrinter::PrintDouble( + double val, BaseTextGenerator* generator) const { + generator->PrintString(SimpleDtoa(val)); +} +void TextFormat::FastFieldValuePrinter::PrintEnum( + int32 val, const string& name, BaseTextGenerator* generator) const { + generator->PrintString(name); +} + +void TextFormat::FastFieldValuePrinter::PrintString( + const string& val, BaseTextGenerator* generator) const { + generator->PrintLiteral("\""); + generator->PrintString(CEscape(val)); + generator->PrintLiteral("\""); +} +void TextFormat::FastFieldValuePrinter::PrintBytes( + const string& val, BaseTextGenerator* generator) const { + PrintString(val, generator); +} +void TextFormat::FastFieldValuePrinter::PrintFieldName( + const Message& message, int field_index, int field_count, + const Reflection* reflection, const FieldDescriptor* field, + BaseTextGenerator* generator) const { + PrintFieldName(message, reflection, field, generator); +} +void TextFormat::FastFieldValuePrinter::PrintFieldName( + const Message& message, const Reflection* reflection, + const FieldDescriptor* field, BaseTextGenerator* generator) const { + if (field->is_extension()) { + generator->PrintLiteral("["); + // We special-case MessageSet elements for compatibility with proto1. + if (field->containing_type()->options().message_set_wire_format() && + field->type() == FieldDescriptor::TYPE_MESSAGE && + field->is_optional() && + field->extension_scope() == field->message_type()) { + generator->PrintString(field->message_type()->full_name()); + } else { + generator->PrintString(field->full_name()); + } + generator->PrintLiteral("]"); + } else if (field->type() == FieldDescriptor::TYPE_GROUP) { + // Groups must be serialized with their original capitalization. + generator->PrintString(field->message_type()->name()); + } else { + generator->PrintString(field->name()); + } +} +void TextFormat::FastFieldValuePrinter::PrintMessageStart( + const Message& message, int field_index, int field_count, + bool single_line_mode, BaseTextGenerator* generator) const { + if (single_line_mode) { + generator->PrintLiteral(" { "); + } else { + generator->PrintLiteral(" {\n"); + } +} +void TextFormat::FastFieldValuePrinter::PrintMessageEnd( + const Message& message, int field_index, int field_count, + bool single_line_mode, BaseTextGenerator* generator) const { + if (single_line_mode) { + generator->PrintLiteral("} "); + } else { + generator->PrintLiteral("}\n"); + } } namespace { + +// A legacy compatibility wrapper. Takes ownership of the delegate. +class FieldValuePrinterWrapper : public TextFormat::FastFieldValuePrinter { + public: + explicit FieldValuePrinterWrapper( + const TextFormat::FieldValuePrinter* delegate) + : delegate_(delegate) {} + + void SetDelegate(const TextFormat::FieldValuePrinter* delegate) { + delegate_.reset(delegate); + } + + void PrintBool(bool val, TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintBool(val)); + } + void PrintInt32(int32 val, TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintInt32(val)); + } + void PrintUInt32(uint32 val, TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintUInt32(val)); + } + void PrintInt64(int64 val, TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintInt64(val)); + } + void PrintUInt64(uint64 val, TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintUInt64(val)); + } + void PrintFloat(float val, TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintFloat(val)); + } + void PrintDouble(double val, TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintDouble(val)); + } + void PrintString(const string& val, + TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintString(val)); + } + void PrintBytes(const string& val, + TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintBytes(val)); + } + void PrintEnum(int32 val, const string& name, + TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintEnum(val, name)); + } + void PrintFieldName(const Message& message, int field_index, int field_count, + const Reflection* reflection, + const FieldDescriptor* field, + TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintFieldName( + message, reflection, field)); + } + void PrintFieldName(const Message& message, const Reflection* reflection, + const FieldDescriptor* field, + TextFormat::BaseTextGenerator* generator) const { + generator->PrintString( + delegate_->PrintFieldName(message, reflection, field)); + } + void PrintMessageStart(const Message& message, int field_index, + int field_count, bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintMessageStart( + message, field_index, field_count, single_line_mode)); + } + void PrintMessageEnd(const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const { + generator->PrintString(delegate_->PrintMessageEnd( + message, field_index, field_count, single_line_mode)); + } + + private: + std::unique_ptr delegate_; +}; + // Our own specialization: for UTF8 escaped strings. -class FieldValuePrinterUtf8Escaping : public TextFormat::FieldValuePrinter { +class FastFieldValuePrinterUtf8Escaping + : public TextFormat::FastFieldValuePrinter { public: - virtual string PrintString(const string& val) const { - return StrCat("\"", strings::Utf8SafeCEscape(val), "\""); + void PrintString(const string& val, + TextFormat::BaseTextGenerator* generator) const { + generator->PrintLiteral("\""); + generator->PrintString(strings::Utf8SafeCEscape(val)); + generator->PrintLiteral("\""); } - virtual string PrintBytes(const string& val) const { - return TextFormat::FieldValuePrinter::PrintString(val); + void PrintBytes(const string& val, + TextFormat::BaseTextGenerator* generator) const { + return FastFieldValuePrinter::PrintString(val, generator); } }; @@ -1338,31 +1730,61 @@ TextFormat::Printer::Printer() use_field_number_(false), use_short_repeated_primitives_(false), hide_unknown_fields_(false), - print_message_fields_in_index_order_(false) { + print_message_fields_in_index_order_(false), + expand_any_(false), + truncate_string_field_longer_than_(0LL), + finder_(NULL) { SetUseUtf8StringEscaping(false); } TextFormat::Printer::~Printer() { STLDeleteValues(&custom_printers_); + STLDeleteValues(&custom_message_printers_); } void TextFormat::Printer::SetUseUtf8StringEscaping(bool as_utf8) { - SetDefaultFieldValuePrinter(as_utf8 - ? new FieldValuePrinterUtf8Escaping() - : new FieldValuePrinter()); + SetDefaultFieldValuePrinter(as_utf8 ? new FastFieldValuePrinterUtf8Escaping() + : new FastFieldValuePrinter()); } void TextFormat::Printer::SetDefaultFieldValuePrinter( const FieldValuePrinter* printer) { + default_field_value_printer_.reset(new FieldValuePrinterWrapper(printer)); +} + +void TextFormat::Printer::SetDefaultFieldValuePrinter( + const FastFieldValuePrinter* printer) { default_field_value_printer_.reset(printer); } bool TextFormat::Printer::RegisterFieldValuePrinter( const FieldDescriptor* field, const FieldValuePrinter* printer) { - return field != NULL - && printer != NULL - && custom_printers_.insert(make_pair(field, printer)).second; + if (field == NULL || printer == NULL) { + return false; + } + FieldValuePrinterWrapper* const wrapper = + new FieldValuePrinterWrapper(nullptr); + if (custom_printers_.insert(std::make_pair(field, wrapper)).second) { + wrapper->SetDelegate(printer); + return true; + } else { + delete wrapper; + return false; + } +} + +bool TextFormat::Printer::RegisterFieldValuePrinter( + const FieldDescriptor* field, const FastFieldValuePrinter* printer) { + return field != NULL && printer != NULL && + custom_printers_.insert(std::make_pair(field, printer)).second; +} + +bool TextFormat::Printer::RegisterMessagePrinter( + const Descriptor* descriptor, const MessagePrinter* printer) { + return descriptor != nullptr && printer != nullptr && + custom_message_printers_.insert(std::make_pair(descriptor, printer)) + .second; } bool TextFormat::Printer::PrintToString(const Message& message, @@ -1389,7 +1811,7 @@ bool TextFormat::Printer::Print(const Message& message, io::ZeroCopyOutputStream* output) const { TextGenerator generator(output, initial_indent_level_); - Print(message, generator); + Print(message, &generator); // Output false if the generator failed internally. return !generator.failed(); @@ -1400,7 +1822,7 @@ bool TextFormat::Printer::PrintUnknownFields( io::ZeroCopyOutputStream* output) const { TextGenerator generator(output, initial_indent_level_); - PrintUnknownFields(unknown_fields, generator); + PrintUnknownFields(unknown_fields, &generator); // Output false if the generator failed internally. return !generator.failed(); @@ -1408,21 +1830,89 @@ bool TextFormat::Printer::PrintUnknownFields( namespace { // Comparison functor for sorting FieldDescriptors by field index. +// Normal fields have higher precedence than extensions. struct FieldIndexSorter { bool operator()(const FieldDescriptor* left, const FieldDescriptor* right) const { - return left->index() < right->index(); + if (left->is_extension() && right->is_extension()) { + return left->number() < right->number(); + } else if (left->is_extension()) { + return false; + } else if (right->is_extension()) { + return true; + } else { + return left->index() < right->index(); + } } }; + } // namespace +bool TextFormat::Printer::PrintAny(const Message& message, + TextGenerator* generator) const { + const FieldDescriptor* type_url_field; + const FieldDescriptor* value_field; + if (!internal::GetAnyFieldDescriptors(message, &type_url_field, + &value_field)) { + return false; + } + + const Reflection* reflection = message.GetReflection(); + + // Extract the full type name from the type_url field. + const string& type_url = reflection->GetString(message, type_url_field); + string url_prefix; + string full_type_name; + if (!internal::ParseAnyTypeUrl(type_url, &url_prefix, &full_type_name)) { + return false; + } + + // Print the "value" in text. + const google::protobuf::Descriptor* value_descriptor = + finder_ ? finder_->FindAnyType(message, url_prefix, full_type_name) + : DefaultFinderFindAnyType(message, url_prefix, full_type_name); + if (value_descriptor == NULL) { + GOOGLE_LOG(WARNING) << "Proto type " << type_url << " not found"; + return false; + } + DynamicMessageFactory factory; + std::unique_ptr value_message( + factory.GetPrototype(value_descriptor)->New()); + string serialized_value = reflection->GetString(message, value_field); + if (!value_message->ParseFromString(serialized_value)) { + GOOGLE_LOG(WARNING) << type_url << ": failed to parse contents"; + return false; + } + generator->PrintLiteral("["); + generator->PrintString(type_url); + generator->PrintLiteral("]"); + const FastFieldValuePrinter* printer = FindWithDefault( + custom_printers_, value_field, default_field_value_printer_.get()); + printer->PrintMessageStart(message, -1, 0, single_line_mode_, generator); + generator->Indent(); + Print(*value_message, generator); + generator->Outdent(); + printer->PrintMessageEnd(message, -1, 0, single_line_mode_, generator); + return true; +} + void TextFormat::Printer::Print(const Message& message, - TextGenerator& generator) const { + TextGenerator* generator) const { + const Descriptor* descriptor = message.GetDescriptor(); + auto itr = custom_message_printers_.find(descriptor); + if (itr != custom_message_printers_.end()) { + itr->second->Print(message, single_line_mode_, generator); + return; + } const Reflection* reflection = message.GetReflection(); - vector fields; + if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ && + PrintAny(message, generator)) { + return; + } + std::vector fields; reflection->ListFields(message, &fields); if (print_message_fields_in_index_order_) { - sort(fields.begin(), fields.end(), FieldIndexSorter()); + std::sort(fields.begin(), fields.end(), FieldIndexSorter()); } for (int i = 0; i < fields.size(); i++) { PrintField(message, reflection, fields[i], generator); @@ -1437,20 +1927,19 @@ void TextFormat::Printer::PrintFieldValueToString( const FieldDescriptor* field, int index, string* output) const { - GOOGLE_DCHECK(output) << "output specified is NULL"; output->clear(); io::StringOutputStream output_stream(output); TextGenerator generator(&output_stream, initial_indent_level_); - PrintFieldValue(message, message.GetReflection(), field, index, generator); + PrintFieldValue(message, message.GetReflection(), field, index, &generator); } void TextFormat::Printer::PrintField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator) const { + TextGenerator* generator) const { if (use_short_repeated_primitives_ && field->is_repeated() && field->cpp_type() != FieldDescriptor::CPPTYPE_STRING && @@ -1467,97 +1956,102 @@ void TextFormat::Printer::PrintField(const Message& message, count = 1; } + std::vector map_entries; + const bool is_map = field->is_map(); + if (is_map) { + map_entries = DynamicMapSorter::Sort(message, count, reflection, field); + } + for (int j = 0; j < count; ++j) { const int field_index = field->is_repeated() ? j : -1; - PrintFieldName(message, reflection, field, generator); + PrintFieldName(message, field_index, count, reflection, field, generator); if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) { - const FieldValuePrinter* printer = FindWithDefault( + const FastFieldValuePrinter* printer = FindWithDefault( custom_printers_, field, default_field_value_printer_.get()); const Message& sub_message = - field->is_repeated() - ? reflection->GetRepeatedMessage(message, field, j) + field->is_repeated() + ? (is_map ? *map_entries[j] + : reflection->GetRepeatedMessage(message, field, j)) : reflection->GetMessage(message, field); - generator.Print( - printer->PrintMessageStart( - sub_message, field_index, count, single_line_mode_)); - generator.Indent(); + printer->PrintMessageStart(sub_message, field_index, count, + single_line_mode_, generator); + generator->Indent(); Print(sub_message, generator); - generator.Outdent(); - generator.Print( - printer->PrintMessageEnd( - sub_message, field_index, count, single_line_mode_)); + generator->Outdent(); + printer->PrintMessageEnd(sub_message, field_index, count, + single_line_mode_, generator); } else { - generator.Print(": "); + generator->PrintLiteral(": "); // Write the field value. PrintFieldValue(message, reflection, field, field_index, generator); if (single_line_mode_) { - generator.Print(" "); + generator->PrintLiteral(" "); } else { - generator.Print("\n"); + generator->PrintLiteral("\n"); } } } } void TextFormat::Printer::PrintShortRepeatedField( - const Message& message, - const Reflection* reflection, - const FieldDescriptor* field, - TextGenerator& generator) const { + const Message& message, const Reflection* reflection, + const FieldDescriptor* field, TextGenerator* generator) const { // Print primitive repeated field in short form. - PrintFieldName(message, reflection, field, generator); - int size = reflection->FieldSize(message, field); - generator.Print(": ["); + PrintFieldName(message, /*field_index=*/-1, /*field_count=*/size, reflection, + field, generator); + generator->PrintLiteral(": ["); for (int i = 0; i < size; i++) { - if (i > 0) generator.Print(", "); + if (i > 0) generator->PrintLiteral(", "); PrintFieldValue(message, reflection, field, i, generator); } if (single_line_mode_) { - generator.Print("] "); + generator->PrintLiteral("] "); } else { - generator.Print("]\n"); + generator->PrintLiteral("]\n"); } } void TextFormat::Printer::PrintFieldName(const Message& message, + int field_index, int field_count, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator) const { + TextGenerator* generator) const { // if use_field_number_ is true, prints field number instead // of field name. if (use_field_number_) { - generator.Print(SimpleItoa(field->number())); + generator->PrintString(SimpleItoa(field->number())); return; } - const FieldValuePrinter* printer = FindWithDefault( + const FastFieldValuePrinter* printer = FindWithDefault( custom_printers_, field, default_field_value_printer_.get()); - generator.Print(printer->PrintFieldName(message, reflection, field)); + printer->PrintFieldName(message, field_index, field_count, reflection, field, + generator); } -void TextFormat::Printer::PrintFieldValue( - const Message& message, - const Reflection* reflection, - const FieldDescriptor* field, - int index, - TextGenerator& generator) const { +void TextFormat::Printer::PrintFieldValue(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + int index, + TextGenerator* generator) const { GOOGLE_DCHECK(field->is_repeated() || (index == -1)) << "Index must be -1 for non-repeated fields"; - const FieldValuePrinter* printer - = FindWithDefault(custom_printers_, field, - default_field_value_printer_.get()); + const FastFieldValuePrinter* printer = FindWithDefault( + custom_printers_, field, default_field_value_printer_.get()); switch (field->cpp_type()) { -#define OUTPUT_FIELD(CPPTYPE, METHOD) \ - case FieldDescriptor::CPPTYPE_##CPPTYPE: \ - generator.Print(printer->Print##METHOD(field->is_repeated() \ - ? reflection->GetRepeated##METHOD(message, field, index) \ - : reflection->Get##METHOD(message, field))); \ - break +#define OUTPUT_FIELD(CPPTYPE, METHOD) \ + case FieldDescriptor::CPPTYPE_##CPPTYPE: \ + printer->Print##METHOD( \ + field->is_repeated() \ + ? reflection->GetRepeated##METHOD(message, field, index) \ + : reflection->Get##METHOD(message, field), \ + generator); \ + break OUTPUT_FIELD( INT32, Int32); OUTPUT_FIELD( INT64, Int64); @@ -1574,20 +2068,41 @@ void TextFormat::Printer::PrintFieldValue( ? reflection->GetRepeatedStringReference( message, field, index, &scratch) : reflection->GetStringReference(message, field, &scratch); + const string* value_to_print = &value; + string truncated_value; + if (truncate_string_field_longer_than_ > 0 && + truncate_string_field_longer_than_ < value.size()) { + truncated_value = value.substr(0, truncate_string_field_longer_than_) + + "......"; + value_to_print = &truncated_value; + } if (field->type() == FieldDescriptor::TYPE_STRING) { - generator.Print(printer->PrintString(value)); + printer->PrintString(*value_to_print, generator); } else { GOOGLE_DCHECK_EQ(field->type(), FieldDescriptor::TYPE_BYTES); - generator.Print(printer->PrintBytes(value)); + printer->PrintBytes(*value_to_print, generator); } break; } case FieldDescriptor::CPPTYPE_ENUM: { - const EnumValueDescriptor *enum_val = field->is_repeated() - ? reflection->GetRepeatedEnum(message, field, index) - : reflection->GetEnum(message, field); - generator.Print(printer->PrintEnum(enum_val->number(), enum_val->name())); + int enum_value = field->is_repeated() + ? reflection->GetRepeatedEnumValue(message, field, index) + : reflection->GetEnumValue(message, field); + const EnumValueDescriptor* enum_desc = + field->enum_type()->FindValueByNumber(enum_value); + if (enum_desc != NULL) { + printer->PrintEnum(enum_value, enum_desc->name(), generator); + } else { + // Ordinarily, enum_desc should not be null, because proto2 has the + // invariant that set enum field values must be in-range, but with the + // new integer-based API for enums (or the RepeatedField loophole), + // it is possible for the user to force an unknown integer value. So we + // simply use the integer value itself as the enum value name in this + // case. + printer->PrintEnum(enum_value, StringPrintf("%d", enum_value), + generator); + } break; } @@ -1649,94 +2164,93 @@ static string PaddedHex(IntType value) { } void TextFormat::Printer::PrintUnknownFields( - const UnknownFieldSet& unknown_fields, TextGenerator& generator) const { + const UnknownFieldSet& unknown_fields, TextGenerator* generator) const { for (int i = 0; i < unknown_fields.field_count(); i++) { const UnknownField& field = unknown_fields.field(i); string field_number = SimpleItoa(field.number()); switch (field.type()) { case UnknownField::TYPE_VARINT: - generator.Print(field_number); - generator.Print(": "); - generator.Print(SimpleItoa(field.varint())); + generator->PrintString(field_number); + generator->PrintLiteral(": "); + generator->PrintString(SimpleItoa(field.varint())); if (single_line_mode_) { - generator.Print(" "); + generator->PrintLiteral(" "); } else { - generator.Print("\n"); + generator->PrintLiteral("\n"); } break; case UnknownField::TYPE_FIXED32: { - generator.Print(field_number); - generator.Print(": 0x"); - char buffer[kFastToBufferSize]; - generator.Print(FastHex32ToBuffer(field.fixed32(), buffer)); + generator->PrintString(field_number); + generator->PrintLiteral(": 0x"); + generator->PrintString( + StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8))); if (single_line_mode_) { - generator.Print(" "); + generator->PrintLiteral(" "); } else { - generator.Print("\n"); + generator->PrintLiteral("\n"); } break; } case UnknownField::TYPE_FIXED64: { - generator.Print(field_number); - generator.Print(": 0x"); - char buffer[kFastToBufferSize]; - generator.Print(FastHex64ToBuffer(field.fixed64(), buffer)); + generator->PrintString(field_number); + generator->PrintLiteral(": 0x"); + generator->PrintString( + StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16))); if (single_line_mode_) { - generator.Print(" "); + generator->PrintLiteral(" "); } else { - generator.Print("\n"); + generator->PrintLiteral("\n"); } break; } case UnknownField::TYPE_LENGTH_DELIMITED: { - generator.Print(field_number); + generator->PrintString(field_number); const string& value = field.length_delimited(); UnknownFieldSet embedded_unknown_fields; if (!value.empty() && embedded_unknown_fields.ParseFromString(value)) { // This field is parseable as a Message. // So it is probably an embedded message. if (single_line_mode_) { - generator.Print(" { "); + generator->PrintLiteral(" { "); } else { - generator.Print(" {\n"); - generator.Indent(); + generator->PrintLiteral(" {\n"); + generator->Indent(); } PrintUnknownFields(embedded_unknown_fields, generator); if (single_line_mode_) { - generator.Print("} "); + generator->PrintLiteral("} "); } else { - generator.Outdent(); - generator.Print("}\n"); + generator->Outdent(); + generator->PrintLiteral("}\n"); } } else { // This field is not parseable as a Message. // So it is probably just a plain string. - generator.Print(": \""); - generator.Print(CEscape(value)); - generator.Print("\""); + generator->PrintLiteral(": \""); + generator->PrintString(CEscape(value)); if (single_line_mode_) { - generator.Print(" "); + generator->PrintLiteral("\" "); } else { - generator.Print("\n"); + generator->PrintLiteral("\"\n"); } } break; } case UnknownField::TYPE_GROUP: - generator.Print(field_number); + generator->PrintString(field_number); if (single_line_mode_) { - generator.Print(" { "); + generator->PrintLiteral(" { "); } else { - generator.Print(" {\n"); - generator.Indent(); + generator->PrintLiteral(" {\n"); + generator->Indent(); } PrintUnknownFields(field.group(), generator); if (single_line_mode_) { - generator.Print("} "); + generator->PrintLiteral("} "); } else { - generator.Outdent(); - generator.Print("}\n"); + generator->Outdent(); + generator->PrintLiteral("}\n"); } break; } diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/text_format.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/text_format.h similarity index 66% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/text_format.h rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/text_format.h index 295494108..d6f3e16bf 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/text_format.h +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/text_format.h @@ -46,6 +46,7 @@ #include #include #include +#include namespace google { namespace protobuf { @@ -62,19 +63,22 @@ namespace io { class LIBPROTOBUF_EXPORT TextFormat { public: // Outputs a textual representation of the given message to the given - // output stream. + // output stream. Returns false if printing fails. static bool Print(const Message& message, io::ZeroCopyOutputStream* output); // Print the fields in an UnknownFieldSet. They are printed by tag number // only. Embedded messages are heuristically identified by attempting to - // parse them. + // parse them. Returns false if printing fails. static bool PrintUnknownFields(const UnknownFieldSet& unknown_fields, io::ZeroCopyOutputStream* output); // Like Print(), but outputs directly to a string. + // Note: output will be cleared prior to printing, and will be left empty + // even if printing fails. Returns false if printing fails. static bool PrintToString(const Message& message, string* output); - // Like PrintUnknownFields(), but outputs directly to a string. + // Like PrintUnknownFields(), but outputs directly to a string. Returns false + // if printing fails. static bool PrintUnknownFieldsToString(const UnknownFieldSet& unknown_fields, string* output); @@ -87,12 +91,66 @@ class LIBPROTOBUF_EXPORT TextFormat { int index, string* output); - // The default printer that converts scalar values from fields into - // their string representation. - // You can derive from this FieldValuePrinter if you want to have - // fields to be printed in a different way and register it at the - // Printer. - class LIBPROTOBUF_EXPORT FieldValuePrinter { + class LIBPROTOBUF_EXPORT BaseTextGenerator { + public: + virtual ~BaseTextGenerator(); + + virtual void Indent() {} + virtual void Outdent() {} + + // Print text to the output stream. + virtual void Print(const char* text, size_t size) = 0; + + void PrintString(const string& str) { Print(str.data(), str.size()); } + + template + void PrintLiteral(const char (&text)[n]) { + Print(text, n - 1); // n includes the terminating zero character. + } + }; + + // The default printer that converts scalar values from fields into their + // string representation. + // You can derive from this FastFieldValuePrinter if you want to have fields + // to be printed in a different way and register it at the Printer. + class LIBPROTOBUF_EXPORT FastFieldValuePrinter { + public: + FastFieldValuePrinter(); + virtual ~FastFieldValuePrinter(); + virtual void PrintBool(bool val, BaseTextGenerator* generator) const; + virtual void PrintInt32(int32 val, BaseTextGenerator* generator) const; + virtual void PrintUInt32(uint32 val, BaseTextGenerator* generator) const; + virtual void PrintInt64(int64 val, BaseTextGenerator* generator) const; + virtual void PrintUInt64(uint64 val, BaseTextGenerator* generator) const; + virtual void PrintFloat(float val, BaseTextGenerator* generator) const; + virtual void PrintDouble(double val, BaseTextGenerator* generator) const; + virtual void PrintString(const string& val, + BaseTextGenerator* generator) const; + virtual void PrintBytes(const string& val, + BaseTextGenerator* generator) const; + virtual void PrintEnum(int32 val, const string& name, + BaseTextGenerator* generator) const; + virtual void PrintFieldName(const Message& message, int field_index, + int field_count, const Reflection* reflection, + const FieldDescriptor* field, + BaseTextGenerator* generator) const; + virtual void PrintFieldName(const Message& message, + const Reflection* reflection, + const FieldDescriptor* field, + BaseTextGenerator* generator) const; + virtual void PrintMessageStart(const Message& message, int field_index, + int field_count, bool single_line_mode, + BaseTextGenerator* generator) const; + virtual void PrintMessageEnd(const Message& message, int field_index, + int field_count, bool single_line_mode, + BaseTextGenerator* generator) const; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastFieldValuePrinter); + }; + + class LIBPROTOBUF_EXPORT PROTOBUF_RUNTIME_DEPRECATED("Please use FastFieldValuePrinter") + FieldValuePrinter { public: FieldValuePrinter(); virtual ~FieldValuePrinter(); @@ -119,9 +177,44 @@ class LIBPROTOBUF_EXPORT TextFormat { bool single_line_mode) const; private: + FastFieldValuePrinter delegate_; GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter); }; + class LIBPROTOBUF_EXPORT MessagePrinter { + public: + MessagePrinter() {} + virtual ~MessagePrinter() {} + virtual void Print(const Message& message, bool single_line_mode, + BaseTextGenerator* generator) const = 0; + + private: + GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessagePrinter); + }; + + // Interface that Printers or Parsers can use to find extensions, or types + // referenced in Any messages. + class LIBPROTOBUF_EXPORT Finder { + public: + virtual ~Finder(); + + // Try to find an extension of *message by fully-qualified field + // name. Returns NULL if no extension is known for this name or number. + // The base implementation uses the extensions already known by the message. + virtual const FieldDescriptor* FindExtension( + Message* message, + const string& name) const; + + // Find the message type for an Any proto. + // Returns NULL if no message is known for this name. + // The base implementation only accepts prefixes of type.googleprod.com/ or + // type.googleapis.com/, and searches the DescriptorPool of the parent + // message. + virtual const Descriptor* FindAnyType(const Message& message, + const string& prefix, + const string& name) const; + }; + // Class for those users which require more fine-grained control over how // a protobuffer message is printed out. class LIBPROTOBUF_EXPORT Printer { @@ -157,7 +250,7 @@ class LIBPROTOBUF_EXPORT TextFormat { single_line_mode_ = single_line_mode; } - bool IsInSingleLineMode() { + bool IsInSingleLineMode() const { return single_line_mode_; } @@ -178,12 +271,13 @@ class LIBPROTOBUF_EXPORT TextFormat { // Set true to output UTF-8 instead of ASCII. The only difference // is that bytes >= 0x80 in string fields will not be escaped, // because they are assumed to be part of UTF-8 multi-byte - // sequences. This will change the default FieldValuePrinter. + // sequences. This will change the default FastFieldValuePrinter. void SetUseUtf8StringEscaping(bool as_utf8); - // Set the default FieldValuePrinter that is used for all fields that + // Set the default (Fast)FieldValuePrinter that is used for all fields that // don't have a field-specific printer registered. // Takes ownership of the printer. + void SetDefaultFieldValuePrinter(const FastFieldValuePrinter* printer); void SetDefaultFieldValuePrinter(const FieldValuePrinter* printer); // Sets whether we want to hide unknown fields or not. @@ -196,22 +290,61 @@ class LIBPROTOBUF_EXPORT TextFormat { hide_unknown_fields_ = hide; } - // If print_message_fields_in_index_order is true, print fields of a proto - // message using the order defined in source code instead of the field - // number. By default, use the field number order. + // If print_message_fields_in_index_order is true, fields of a proto message + // will be printed using the order defined in source code instead of the + // field number, extensions will be printed at the end of the message + // and their relative order is determined by the extension number. + // By default, use the field number order. void SetPrintMessageFieldsInIndexOrder( bool print_message_fields_in_index_order) { print_message_fields_in_index_order_ = print_message_fields_in_index_order; } - // Register a custom field-specific FieldValuePrinter for fields + // If expand==true, expand google.protobuf.Any payloads. The output + // will be of form + // [type_url] { } + // + // If expand==false, print Any using the default printer. The output will + // look like + // type_url: "" value: "serialized_content" + void SetExpandAny(bool expand) { + expand_any_ = expand; + } + + // Set how parser finds message for Any payloads. + void SetFinder(Finder* finder) { + finder_ = finder; + } + + // If non-zero, we truncate all string fields that are longer than this + // threshold. This is useful when the proto message has very long strings, + // e.g., dump of encoded image file. + // + // NOTE(hfgong): Setting a non-zero value breaks round-trip safe + // property of TextFormat::Printer. That is, from the printed message, we + // cannot fully recover the original string field any more. + void SetTruncateStringFieldLongerThan( + const int64 truncate_string_field_longer_than) { + truncate_string_field_longer_than_ = truncate_string_field_longer_than; + } + + // Register a custom field-specific (Fast)FieldValuePrinter for fields // with a particular FieldDescriptor. // Returns "true" if the registration succeeded, or "false", if there is // already a printer for that FieldDescriptor. // Takes ownership of the printer on successful registration. bool RegisterFieldValuePrinter(const FieldDescriptor* field, const FieldValuePrinter* printer); + bool RegisterFieldValuePrinter(const FieldDescriptor* field, + const FastFieldValuePrinter* printer); + + // Register a custom message-specific MessagePrinter for messages with a + // particular Descriptor. + // Returns "true" if the registration succeeded, or "false" if there is + // already a printer for that Descriptor. + bool RegisterMessagePrinter(const Descriptor* descriptor, + const MessagePrinter* printer); private: // Forward declaration of an internal class used to print the text @@ -220,41 +353,39 @@ class LIBPROTOBUF_EXPORT TextFormat { // Internal Print method, used for writing to the OutputStream via // the TextGenerator class. - void Print(const Message& message, - TextGenerator& generator) const; + void Print(const Message& message, TextGenerator* generator) const; // Print a single field. - void PrintField(const Message& message, - const Reflection* reflection, + void PrintField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator) const; + TextGenerator* generator) const; // Print a repeated primitive field in short form. void PrintShortRepeatedField(const Message& message, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator) const; + TextGenerator* generator) const; // Print the name of a field -- i.e. everything that comes before the // ':' for a single name/value pair. - void PrintFieldName(const Message& message, - const Reflection* reflection, + void PrintFieldName(const Message& message, int field_index, + int field_count, const Reflection* reflection, const FieldDescriptor* field, - TextGenerator& generator) const; + TextGenerator* generator) const; // Outputs a textual representation of the value of the field supplied on // the message supplied or the default value if not set. - void PrintFieldValue(const Message& message, - const Reflection* reflection, - const FieldDescriptor* field, - int index, - TextGenerator& generator) const; + void PrintFieldValue(const Message& message, const Reflection* reflection, + const FieldDescriptor* field, int index, + TextGenerator* generator) const; // Print the fields in an UnknownFieldSet. They are printed by tag number // only. Embedded messages are heuristically identified by attempting to // parse them. void PrintUnknownFields(const UnknownFieldSet& unknown_fields, - TextGenerator& generator) const; + TextGenerator* generator) const; + + bool PrintAny(const Message& message, TextGenerator* generator) const; int initial_indent_level_; @@ -268,15 +399,37 @@ class LIBPROTOBUF_EXPORT TextFormat { bool print_message_fields_in_index_order_; - scoped_ptr default_field_value_printer_; - typedef map CustomPrinterMap; + bool expand_any_; + + int64 truncate_string_field_longer_than_; + + std::unique_ptr default_field_value_printer_; + typedef std::map + CustomPrinterMap; CustomPrinterMap custom_printers_; + + typedef std::map + CustomMessagePrinterMap; + CustomMessagePrinterMap custom_message_printers_; + + const Finder* finder_; }; // Parses a text-format protocol message from the given input stream to - // the given message object. This function parses the format written - // by Print(). + // the given message object. This function parses the human-readable format + // written by Print(). Returns true on success. The message is cleared first, + // even if the function fails -- See Merge() to avoid this behavior. + // + // Example input: "user {\n id: 123 extra { gender: MALE language: 'en' }\n}" + // + // One use for this function is parsing handwritten strings in test code. + // Another use is to parse the output from google::protobuf::Message::DebugString() + // (or ShortDebugString()), because these functions output using + // google::protobuf::TextFormat::Print(). + // + // If you would like to read a protocol buffer serialized in the + // (non-human-readable) binary wire format, see + // google::protobuf::MessageLite::ParseFromString(). static bool Parse(io::ZeroCopyInputStream* input, Message* output); // Like Parse(), but reads directly from a string. static bool ParseFromString(const string& input, Message* output); @@ -294,20 +447,6 @@ class LIBPROTOBUF_EXPORT TextFormat { const FieldDescriptor* field, Message* message); - // Interface that TextFormat::Parser can use to find extensions. - // This class may be extended in the future to find more information - // like fields, etc. - class LIBPROTOBUF_EXPORT Finder { - public: - virtual ~Finder(); - - // Try to find an extension of *message by fully-qualified field - // name. Returns NULL if no extension is known for this name or number. - virtual const FieldDescriptor* FindExtension( - Message* message, - const string& name) const = 0; - }; - // A location in the parsed text. struct ParseLocation { int line; @@ -347,11 +486,13 @@ class LIBPROTOBUF_EXPORT TextFormat { ParseInfoTree* CreateNested(const FieldDescriptor* field); // Defines the map from the index-th field descriptor to its parse location. - typedef map > LocationMap; + typedef std::map > LocationMap; // Defines the map from the index-th field descriptor to the nested parse // info tree. - typedef map > NestedMap; + typedef std::map > NestedMap; LocationMap locations_; NestedMap nested_; @@ -429,7 +570,7 @@ class LIBPROTOBUF_EXPORT TextFormat { ParserImpl* parser_impl); io::ErrorCollector* error_collector_; - Finder* finder_; + const Finder* finder_; ParseInfoTree* parse_info_tree_; bool allow_partial_; bool allow_case_insensitive_field_; diff --git a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/text_format_unittest.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/text_format_unittest.cc similarity index 75% rename from cdk/protobuf/protobuf-2.6.1/src/google/protobuf/text_format_unittest.cc rename to cdk/protobuf/protobuf-3.6.1/src/google/protobuf/text_format_unittest.cc index 55732688a..544c37e25 100644 --- a/cdk/protobuf/protobuf-2.6.1/src/google/protobuf/text_format_unittest.cc +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/text_format_unittest.cc @@ -32,23 +32,31 @@ // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. +#include + #include #include #include +#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include -#include +#include +#include +#include -#include -#include -#include -#include #include #include +#include +#include +#include + namespace google { namespace protobuf { @@ -56,11 +64,6 @@ namespace protobuf { // Can't use an anonymous namespace here due to brokenness of Tru64 compiler. namespace text_format_unittest { -inline bool IsNaN(double value) { - // NaN is never equal to anything, even itself. - return value != value; -} - // A basic string with different escapable characters for testing. const string kEscapeTestString = "\"A string with ' characters \n and \r newlines and \t tabs and \001 " @@ -152,7 +155,21 @@ TEST_F(TextFormatTest, ShortPrimitiveRepeateds) { TextFormat::Printer printer; printer.SetUseShortRepeatedPrimitives(true); string text; - printer.PrintToString(proto_, &text); + EXPECT_TRUE(printer.PrintToString(proto_, &text)); + + EXPECT_EQ("optional_int32: 123\n" + "repeated_int32: [456, 789]\n" + "repeated_string: \"foo\"\n" + "repeated_string: \"bar\"\n" + "repeated_nested_message {\n bb: 2\n}\n" + "repeated_nested_message {\n bb: 3\n}\n" + "repeated_nested_enum: [FOO, BAR]\n", + text); + + // Verify that any existing data in the string is cleared when + // PrintToString() is called. + text = "just some data here...\n\nblah blah"; + EXPECT_TRUE(printer.PrintToString(proto_, &text)); EXPECT_EQ("optional_int32: 123\n" "repeated_int32: [456, 789]\n" @@ -165,7 +182,7 @@ TEST_F(TextFormatTest, ShortPrimitiveRepeateds) { // Try in single-line mode. printer.SetSingleLineMode(true); - printer.PrintToString(proto_, &text); + EXPECT_TRUE(printer.PrintToString(proto_, &text)); EXPECT_EQ("optional_int32: 123 " "repeated_int32: [456, 789] " @@ -263,7 +280,7 @@ TEST_F(TextFormatTest, PrintUnknownFields) { } TEST_F(TextFormatTest, PrintUnknownFieldsHidden) { - // Test printing of unknown fields in a message when supressed. + // Test printing of unknown fields in a message when suppressed. unittest::OneString message; message.set_data("data"); @@ -435,23 +452,39 @@ TEST_F(TextFormatTest, FieldSpecificCustomPrinter) { EXPECT_EQ("optional_int32: value-is(42)\nrepeated_int32: 42\n", text); } +TEST_F(TextFormatTest, FieldSpecificCustomPrinterRegisterSameFieldTwice) { + protobuf_unittest::TestAllTypes message; + TextFormat::Printer printer; + const FieldDescriptor* const field = + message.GetDescriptor()->FindFieldByName("optional_int32"); + ASSERT_TRUE(printer.RegisterFieldValuePrinter( + field, new CustomInt32FieldValuePrinter())); + const TextFormat::FieldValuePrinter* const rejected = + new CustomInt32FieldValuePrinter(); + ASSERT_FALSE(printer.RegisterFieldValuePrinter(field, rejected)); + delete rejected; +} + TEST_F(TextFormatTest, ErrorCasesRegisteringFieldValuePrinterShouldFail) { protobuf_unittest::TestAllTypes message; TextFormat::Printer printer; // NULL printer. EXPECT_FALSE(printer.RegisterFieldValuePrinter( message.GetDescriptor()->FindFieldByName("optional_int32"), - NULL)); + static_cast(nullptr))); + EXPECT_FALSE(printer.RegisterFieldValuePrinter( + message.GetDescriptor()->FindFieldByName("optional_int32"), + static_cast(nullptr))); // Because registration fails, the ownership of this printer is never taken. TextFormat::FieldValuePrinter my_field_printer; // NULL field - EXPECT_FALSE(printer.RegisterFieldValuePrinter(NULL, &my_field_printer)); + EXPECT_FALSE(printer.RegisterFieldValuePrinter(nullptr, &my_field_printer)); } class CustomMessageFieldValuePrinter : public TextFormat::FieldValuePrinter { public: virtual string PrintInt32(int32 v) const { - return StrCat(FieldValuePrinter::PrintInt32(v), " # x", ToHex(v)); + return StrCat(FieldValuePrinter::PrintInt32(v), " # x", strings::Hex(v)); } virtual string PrintMessageStart(const Message& message, @@ -528,6 +561,143 @@ TEST_F(TextFormatTest, CustomPrinterForMultilineComments) { text); } +// Achieve effects similar to SetUseShortRepeatedPrimitives for messages, using +// RegisterFieldValuePrinter. Use this to test the version of PrintFieldName +// that accepts repeated field index and count. +class CompactRepeatedFieldPrinter : public TextFormat::FastFieldValuePrinter { + public: + void PrintFieldName(const Message& message, int field_index, int field_count, + const Reflection* reflection, + const FieldDescriptor* field, + TextFormat::BaseTextGenerator* generator) const override { + if (field_index == 0 || field_index == -1) { + generator->PrintString(field->name()); + } + } + void PrintMessageStart( + const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { + if (field_index == 0 || field_index == -1) { + if (single_line_mode) { + generator->PrintLiteral(" { "); + } else { + generator->PrintLiteral(" {\n"); + } + } + } + void PrintMessageEnd( + const Message& message, int field_index, int field_count, + bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { + if (field_index == field_count - 1 || field_index == -1) { + if (single_line_mode) { + generator->PrintLiteral("} "); + } else { + generator->PrintLiteral("}\n"); + } + } + } +}; + +TEST_F(TextFormatTest, CompactRepeatedFieldPrinter) { + TextFormat::Printer printer; + ASSERT_TRUE(printer.RegisterFieldValuePrinter( + unittest::TestAllTypes::default_instance() + .descriptor() + ->FindFieldByNumber( + unittest::TestAllTypes::kRepeatedNestedMessageFieldNumber), + new CompactRepeatedFieldPrinter)); + + protobuf_unittest::TestAllTypes message; + message.add_repeated_nested_message()->set_bb(1); + message.add_repeated_nested_message()->set_bb(2); + message.add_repeated_nested_message()->set_bb(3); + + string text; + ASSERT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ( + "repeated_nested_message {\n" + " bb: 1\n" + " bb: 2\n" + " bb: 3\n" + "}\n", + text); +} + +// Print strings into multiple line, with indention. Use this to test +// BaseTextGenerator::Indent and BaseTextGenerator::Outdent. +class MultilineStringPrinter : public TextFormat::FastFieldValuePrinter { + public: + void PrintString(const string& val, + TextFormat::BaseTextGenerator* generator) const override { + generator->Indent(); + int last_pos = 0; + int newline_pos = val.find('\n'); + while (newline_pos != string::npos) { + generator->PrintLiteral("\n"); + TextFormat::FastFieldValuePrinter::PrintString( + val.substr(last_pos, newline_pos + 1 - last_pos), generator); + last_pos = newline_pos + 1; + newline_pos = val.find('\n', last_pos); + } + if (last_pos < val.size()) { + generator->PrintLiteral("\n"); + TextFormat::FastFieldValuePrinter::PrintString(val.substr(last_pos), + generator); + } + generator->Outdent(); + } +}; + +TEST_F(TextFormatTest, MultilineStringPrinter) { + TextFormat::Printer printer; + ASSERT_TRUE(printer.RegisterFieldValuePrinter( + unittest::TestAllTypes::default_instance() + .descriptor() + ->FindFieldByNumber( + unittest::TestAllTypes::kOptionalStringFieldNumber), + new MultilineStringPrinter)); + + protobuf_unittest::TestAllTypes message; + message.set_optional_string("first line\nsecond line\nthird line"); + + string text; + ASSERT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ( + "optional_string: \n" + " \"first line\\n\"\n" + " \"second line\\n\"\n" + " \"third line\"\n", + text); +} + +class CustomNestedMessagePrinter : public TextFormat::MessagePrinter { + public: + CustomNestedMessagePrinter() {} + ~CustomNestedMessagePrinter() override {} + void Print(const Message& message, bool single_line_mode, + TextFormat::BaseTextGenerator* generator) const override { + generator->PrintLiteral("custom"); + } +}; + +TEST_F(TextFormatTest, CustomMessagePrinter) { + TextFormat::Printer printer; + printer.RegisterMessagePrinter( + unittest::TestAllTypes::NestedMessage::default_instance().descriptor(), + new CustomNestedMessagePrinter); + + unittest::TestAllTypes message; + string text; + EXPECT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ("", text); + + message.mutable_optional_nested_message()->set_bb(1); + EXPECT_TRUE(printer.PrintToString(message, &text)); + EXPECT_EQ("optional_nested_message {\n custom}\n", text); +} + TEST_F(TextFormatTest, ParseBasic) { io::ArrayInputStream input_stream(proto_debug_string_.data(), proto_debug_string_.size()); @@ -586,7 +756,7 @@ TEST_F(TextFormatTest, ParseConcatenatedString) { // Compare. EXPECT_EQ("foobar", proto_.optional_string()); - // Create a parse string with multiple parts on seperate lines. + // Create a parse string with multiple parts on separate lines. parse_string = "optional_string: \"foo\"\n" "\"bar\"\n"; @@ -654,6 +824,87 @@ TEST_F(TextFormatTest, ParseShortRepeatedForm) { EXPECT_EQ(4, proto_.repeatedgroup(1).a()); } +TEST_F(TextFormatTest, ParseShortRepeatedWithTrailingComma) { + string parse_string = "repeated_int32: [456,]\n"; + ASSERT_FALSE(TextFormat::ParseFromString(parse_string, &proto_)); + parse_string = "repeated_nested_enum: [ FOO , ]"; + ASSERT_FALSE(TextFormat::ParseFromString(parse_string, &proto_)); + parse_string = "repeated_string: [ \"foo\", ]"; + ASSERT_FALSE(TextFormat::ParseFromString(parse_string, &proto_)); + parse_string = "repeated_nested_message: [ { bb: 1 }, ]"; + ASSERT_FALSE(TextFormat::ParseFromString(parse_string, &proto_)); + parse_string = "RepeatedGroup [{ a: 3 },]\n"; +} + +TEST_F(TextFormatTest, ParseShortRepeatedEmpty) { + string parse_string = + "repeated_int32: []\n" + "repeated_nested_enum: []\n" + "repeated_string: []\n" + "repeated_nested_message: []\n" + "RepeatedGroup []\n"; + + ASSERT_TRUE(TextFormat::ParseFromString(parse_string, &proto_)); + + EXPECT_EQ(0, proto_.repeated_int32_size()); + EXPECT_EQ(0, proto_.repeated_nested_enum_size()); + EXPECT_EQ(0, proto_.repeated_string_size()); + EXPECT_EQ(0, proto_.repeated_nested_message_size()); + EXPECT_EQ(0, proto_.repeatedgroup_size()); +} + +TEST_F(TextFormatTest, ParseShortRepeatedConcatenatedWithEmpty) { + string parse_string = + // Starting with empty [] should have no impact. + "repeated_int32: []\n" + "repeated_nested_enum: []\n" + "repeated_string: []\n" + "repeated_nested_message: []\n" + "RepeatedGroup []\n" + // Mixed short-form and long-form are simply concatenated. + "repeated_int32: 1\n" + "repeated_int32: [456, 789]\n" + "repeated_nested_enum: [ FOO ,BAR, # comment\n" + " 3]\n" + // Note that while the printer won't print repeated strings in short-form, + // the parser will accept them. + "repeated_string: [ \"foo\", 'bar' ]\n" + // Repeated message + "repeated_nested_message: [ { bb: 1 }, { bb : 2 }]\n" + // Repeated group + "RepeatedGroup [{ a: 3 },{ a: 4 }]\n" + // Adding empty [] should have no impact. + "repeated_int32: []\n" + "repeated_nested_enum: []\n" + "repeated_string: []\n" + "repeated_nested_message: []\n" + "RepeatedGroup []\n"; + + ASSERT_TRUE(TextFormat::ParseFromString(parse_string, &proto_)); + + ASSERT_EQ(3, proto_.repeated_int32_size()); + EXPECT_EQ(1, proto_.repeated_int32(0)); + EXPECT_EQ(456, proto_.repeated_int32(1)); + EXPECT_EQ(789, proto_.repeated_int32(2)); + + ASSERT_EQ(3, proto_.repeated_nested_enum_size()); + EXPECT_EQ(unittest::TestAllTypes::FOO, proto_.repeated_nested_enum(0)); + EXPECT_EQ(unittest::TestAllTypes::BAR, proto_.repeated_nested_enum(1)); + EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.repeated_nested_enum(2)); + + ASSERT_EQ(2, proto_.repeated_string_size()); + EXPECT_EQ("foo", proto_.repeated_string(0)); + EXPECT_EQ("bar", proto_.repeated_string(1)); + + ASSERT_EQ(2, proto_.repeated_nested_message_size()); + EXPECT_EQ(1, proto_.repeated_nested_message(0).bb()); + EXPECT_EQ(2, proto_.repeated_nested_message(1).bb()); + + ASSERT_EQ(2, proto_.repeatedgroup_size()); + EXPECT_EQ(3, proto_.repeatedgroup(0).a()); + EXPECT_EQ(4, proto_.repeatedgroup(1).a()); +} + TEST_F(TextFormatTest, Comments) { // Test that comments are ignored. @@ -893,12 +1144,16 @@ TEST_F(TextFormatTest, ParseExotic) { EXPECT_EQ(1.235E22 , message.repeated_double(4)); EXPECT_EQ(1.235E-18 , message.repeated_double(5)); EXPECT_EQ(123.456789, message.repeated_double(6)); - EXPECT_EQ(message.repeated_double(7), numeric_limits::infinity()); - EXPECT_EQ(message.repeated_double(8), numeric_limits::infinity()); - EXPECT_EQ(message.repeated_double(9), -numeric_limits::infinity()); - EXPECT_EQ(message.repeated_double(10), -numeric_limits::infinity()); - EXPECT_TRUE(IsNaN(message.repeated_double(11))); - EXPECT_TRUE(IsNaN(message.repeated_double(12))); + EXPECT_EQ(message.repeated_double(7), + std::numeric_limits::infinity()); + EXPECT_EQ(message.repeated_double(8), + std::numeric_limits::infinity()); + EXPECT_EQ(message.repeated_double(9), + -std::numeric_limits::infinity()); + EXPECT_EQ(message.repeated_double(10), + -std::numeric_limits::infinity()); + EXPECT_TRUE(MathLimits::IsNaN(message.repeated_double(11))); + EXPECT_TRUE(MathLimits::IsNaN(message.repeated_double(12))); // Note: Since these string literals have \0's in them, we must explicitly // pass their sizes to string's constructor. @@ -910,29 +1165,93 @@ TEST_F(TextFormatTest, ParseExotic) { TEST_F(TextFormatTest, PrintFieldsInIndexOrder) { protobuf_unittest::TestFieldOrderings message; // Fields are listed in index order instead of field number. - message.set_my_string("Test String"); // Field number 11 + message.set_my_string("str"); // Field number 11 message.set_my_int(12345); // Field number 1 message.set_my_float(0.999); // Field number 101 + // Extensions are listed based on the order of extension number. + // Extension number 12. + message + .MutableExtension( + protobuf_unittest::TestExtensionOrderings2::test_ext_orderings2) + ->set_my_string("ext_str2"); + // Extension number 13. + message + .MutableExtension( + protobuf_unittest::TestExtensionOrderings1::test_ext_orderings1) + ->set_my_string("ext_str1"); + // Extension number 14. + message + .MutableExtension(protobuf_unittest::TestExtensionOrderings2:: + TestExtensionOrderings3::test_ext_orderings3) + ->set_my_string("ext_str3"); + // Extension number 50. + *message.MutableExtension(protobuf_unittest::my_extension_string) = "ext_str0"; + TextFormat::Printer printer; string text; // By default, print in field number order. + // my_int: 12345 + // my_string: "str" + // [protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] { + // my_string: "ext_str2" + // } + // [protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] { + // my_string: "ext_str1" + // } + // [protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3.test_ext_orderings3] + // { + // my_string: "ext_str3" + // } + // [protobuf_unittest.my_extension_string]: "ext_str0" + // my_float: 0.999 printer.PrintToString(message, &text); - EXPECT_EQ("my_int: 12345\nmy_string: \"Test String\"\nmy_float: 0.999\n", - text); + EXPECT_EQ( + "my_int: 12345\nmy_string: " + "\"str\"\n[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] " + "{\n my_string: " + "\"ext_str2\"\n}\n[protobuf_unittest.TestExtensionOrderings1.test_ext_" + "orderings1] {\n my_string: " + "\"ext_str1\"\n}\n[protobuf_unittest.TestExtensionOrderings2." + "TestExtensionOrderings3.test_ext_orderings3] {\n my_string: " + "\"ext_str3\"\n}\n[protobuf_unittest.my_extension_string]: " + "\"ext_str0\"\nmy_float: 0.999\n", + text); // Print in index order. + // my_string: "str" + // my_int: 12345 + // my_float: 0.999 + // [protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] { + // my_string: "ext_str2" + // } + // [protobuf_unittest.TestExtensionOrderings1.test_ext_orderings1] { + // my_string: "ext_str1" + // } + // [protobuf_unittest.TestExtensionOrderings2.TestExtensionOrderings3.test_ext_orderings3] + // { + // my_string: "ext_str3" + // } + // [protobuf_unittest.my_extension_string]: "ext_str0" printer.SetPrintMessageFieldsInIndexOrder(true); printer.PrintToString(message, &text); - EXPECT_EQ("my_string: \"Test String\"\nmy_int: 12345\nmy_float: 0.999\n", - text); + EXPECT_EQ( + "my_string: \"str\"\nmy_int: 12345\nmy_float: " + "0.999\n[protobuf_unittest.TestExtensionOrderings2.test_ext_orderings2] " + "{\n my_string: " + "\"ext_str2\"\n}\n[protobuf_unittest.TestExtensionOrderings1.test_ext_" + "orderings1] {\n my_string: " + "\"ext_str1\"\n}\n[protobuf_unittest.TestExtensionOrderings2." + "TestExtensionOrderings3.test_ext_orderings3] {\n my_string: " + "\"ext_str3\"\n}\n[protobuf_unittest.my_extension_string]: \"ext_str0\"\n", + text); } class TextFormatParserTest : public testing::Test { protected: void ExpectFailure(const string& input, const string& message, int line, int col) { - scoped_ptr proto(new unittest::TestAllTypes); + std::unique_ptr proto(new unittest::TestAllTypes); ExpectFailure(input, message, line, col, proto.get()); } @@ -993,7 +1312,7 @@ class TextFormatParserTest : public testing::Test { }; TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) { - scoped_ptr message(new unittest::TestAllTypes); + std::unique_ptr message(new unittest::TestAllTypes); const Descriptor* d = message->GetDescriptor(); string stringData = @@ -1058,7 +1377,7 @@ TEST_F(TextFormatParserTest, ParseInfoTreeBuilding) { } TEST_F(TextFormatParserTest, ParseFieldValueFromString) { - scoped_ptr message(new unittest::TestAllTypes); + std::unique_ptr message(new unittest::TestAllTypes); const Descriptor* d = message->GetDescriptor(); #define EXPECT_FIELD(name, value, valuestring) \ @@ -1191,11 +1510,13 @@ TEST_F(TextFormatParserTest, ParseFieldValueFromString) { TEST_F(TextFormatParserTest, InvalidToken) { - ExpectFailure("optional_bool: true\n-5\n", "Expected identifier.", + ExpectFailure("optional_bool: true\n-5\n", "Expected identifier, got: -", 2, 1); - ExpectFailure("optional_bool: true!\n", "Expected identifier.", 1, 20); - ExpectFailure("\"some string\"", "Expected identifier.", 1, 1); + ExpectFailure("optional_bool: true!\n", "Expected identifier, got: !", 1, + 20); + ExpectFailure("\"some string\"", + "Expected identifier, got: \"some string\"", 1, 1); } TEST_F(TextFormatParserTest, InvalidFieldName) { @@ -1243,46 +1564,52 @@ TEST_F(TextFormatParserTest, AllowIgnoreCapitalizationError) { TEST_F(TextFormatParserTest, InvalidFieldValues) { // Invalid values for a double/float field. - ExpectFailure("optional_double: \"hello\"\n", "Expected double.", 1, 18); - ExpectFailure("optional_double: true\n", "Expected double.", 1, 18); - ExpectFailure("optional_double: !\n", "Expected double.", 1, 18); + ExpectFailure("optional_double: \"hello\"\n", + "Expected double, got: \"hello\"", 1, 18); + ExpectFailure("optional_double: true\n", "Expected double, got: true", 1, + 18); + ExpectFailure("optional_double: !\n", "Expected double, got: !", 1, 18); ExpectFailure("optional_double {\n \n}\n", "Expected \":\", found \"{\".", 1, 17); // Invalid values for a signed integer field. - ExpectFailure("optional_int32: \"hello\"\n", "Expected integer.", 1, 17); - ExpectFailure("optional_int32: true\n", "Expected integer.", 1, 17); - ExpectFailure("optional_int32: 4.5\n", "Expected integer.", 1, 17); - ExpectFailure("optional_int32: !\n", "Expected integer.", 1, 17); + ExpectFailure("optional_int32: \"hello\"\n", + "Expected integer, got: \"hello\"", 1, 17); + ExpectFailure("optional_int32: true\n", "Expected integer, got: true", 1, 17); + ExpectFailure("optional_int32: 4.5\n", "Expected integer, got: 4.5", 1, 17); + ExpectFailure("optional_int32: !\n", "Expected integer, got: !", 1, 17); ExpectFailure("optional_int32 {\n \n}\n", "Expected \":\", found \"{\".", 1, 16); ExpectFailure("optional_int32: 0x80000000\n", - "Integer out of range.", 1, 17); + "Integer out of range (0x80000000)", 1, 17); ExpectFailure("optional_int64: 0x8000000000000000\n", - "Integer out of range.", 1, 17); + "Integer out of range (0x8000000000000000)", 1, 17); ExpectFailure("optional_int32: -0x80000001\n", - "Integer out of range.", 1, 18); + "Integer out of range (0x80000001)", 1, 18); ExpectFailure("optional_int64: -0x8000000000000001\n", - "Integer out of range.", 1, 18); + "Integer out of range (0x8000000000000001)", 1, 18); // Invalid values for an unsigned integer field. - ExpectFailure("optional_uint64: \"hello\"\n", "Expected integer.", 1, 18); - ExpectFailure("optional_uint64: true\n", "Expected integer.", 1, 18); - ExpectFailure("optional_uint64: 4.5\n", "Expected integer.", 1, 18); - ExpectFailure("optional_uint64: -5\n", "Expected integer.", 1, 18); - ExpectFailure("optional_uint64: !\n", "Expected integer.", 1, 18); + ExpectFailure("optional_uint64: \"hello\"\n", + "Expected integer, got: \"hello\"", 1, 18); + ExpectFailure("optional_uint64: true\n", + "Expected integer, got: true", 1, 18); + ExpectFailure("optional_uint64: 4.5\n", "Expected integer, got: 4.5", 1, 18); + ExpectFailure("optional_uint64: -5\n", "Expected integer, got: -", 1, 18); + ExpectFailure("optional_uint64: !\n", "Expected integer, got: !", 1, 18); ExpectFailure("optional_uint64 {\n \n}\n", "Expected \":\", found \"{\".", 1, 17); ExpectFailure("optional_uint32: 0x100000000\n", - "Integer out of range.", 1, 18); + "Integer out of range (0x100000000)", 1, 18); ExpectFailure("optional_uint64: 0x10000000000000000\n", - "Integer out of range.", 1, 18); + "Integer out of range (0x10000000000000000)", 1, 18); // Invalid values for a boolean field. - ExpectFailure("optional_bool: \"hello\"\n", "Expected identifier.", 1, 16); - ExpectFailure("optional_bool: 5\n", "Integer out of range.", 1, 16); - ExpectFailure("optional_bool: -7.5\n", "Expected identifier.", 1, 16); - ExpectFailure("optional_bool: !\n", "Expected identifier.", 1, 16); + ExpectFailure("optional_bool: \"hello\"\n", + "Expected identifier, got: \"hello\"", 1, 16); + ExpectFailure("optional_bool: 5\n", "Integer out of range (5)", 1, 16); + ExpectFailure("optional_bool: -7.5\n", "Expected identifier, got: -", 1, 16); + ExpectFailure("optional_bool: !\n", "Expected identifier, got: !", 1, 16); ExpectFailure( "optional_bool: meh\n", @@ -1293,16 +1620,16 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { 1, 15); // Invalid values for a string field. - ExpectFailure("optional_string: true\n", "Expected string.", 1, 18); - ExpectFailure("optional_string: 5\n", "Expected string.", 1, 18); - ExpectFailure("optional_string: -7.5\n", "Expected string.", 1, 18); - ExpectFailure("optional_string: !\n", "Expected string.", 1, 18); + ExpectFailure("optional_string: true\n", "Expected string, got: true", 1, 18); + ExpectFailure("optional_string: 5\n", "Expected string, got: 5", 1, 18); + ExpectFailure("optional_string: -7.5\n", "Expected string, got: -", 1, 18); + ExpectFailure("optional_string: !\n", "Expected string, got: !", 1, 18); ExpectFailure("optional_string {\n \n}\n", "Expected \":\", found \"{\".", 1, 17); // Invalid values for an enumeration field. ExpectFailure("optional_nested_enum: \"hello\"\n", - "Expected integer or identifier.", 1, 23); + "Expected integer or identifier, got: \"hello\"", 1, 23); // Valid token, but enum value is not defined. ExpectFailure("optional_nested_enum: 5\n", @@ -1310,9 +1637,10 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { "\"optional_nested_enum\".", 2, 1); // We consume the negative sign, so the error position starts one character // later. - ExpectFailure("optional_nested_enum: -7.5\n", "Expected integer.", 1, 24); + ExpectFailure("optional_nested_enum: -7.5\n", "Expected integer, got: 7.5", 1, + 24); ExpectFailure("optional_nested_enum: !\n", - "Expected integer or identifier.", 1, 23); + "Expected integer or identifier, got: !", 1, 23); ExpectFailure( "optional_nested_enum: grah\n", @@ -1324,23 +1652,23 @@ TEST_F(TextFormatParserTest, InvalidFieldValues) { "Expected \":\", found \"{\".", 1, 22); } -TEST_F(TextFormatParserTest, MessageDelimeters) { - // Non-matching delimeters. +TEST_F(TextFormatParserTest, MessageDelimiters) { + // Non-matching delimiters. ExpectFailure("OptionalGroup <\n \n}\n", "Expected \">\", found \"}\".", 3, 1); - // Invalid delimeters. + // Invalid delimiters. ExpectFailure("OptionalGroup [\n \n]\n", "Expected \"{\", found \"[\".", 1, 15); // Unending message. ExpectFailure("optional_nested_message {\n \nbb: 118\n", - "Expected identifier.", + "Expected identifier, got: ", 4, 1); } TEST_F(TextFormatParserTest, UnknownExtension) { - // Non-matching delimeters. + // Non-matching delimiters. ExpectFailure("[blahblah]: 123", "Extension \"blahblah\" is not defined or is not an " "extension of \"protobuf_unittest.TestAllTypes\".", @@ -1391,7 +1719,7 @@ TEST_F(TextFormatParserTest, ExplicitDelimiters) { } TEST_F(TextFormatParserTest, PrintErrorsToStderr) { - vector errors; + std::vector errors; { ScopedMemoryLog log; @@ -1408,7 +1736,7 @@ TEST_F(TextFormatParserTest, PrintErrorsToStderr) { } TEST_F(TextFormatParserTest, FailsOnTokenizationError) { - vector errors; + std::vector errors; { ScopedMemoryLog log; @@ -1467,7 +1795,7 @@ TEST_F(TextFormatMessageSetTest, Deserialize) { protobuf_unittest::TestMessageSetExtension2::message_set_extension).str()); // Ensure that these are the only entries present. - vector descriptors; + std::vector descriptors; proto.message_set().GetReflection()->ListFields( proto.message_set(), &descriptors); EXPECT_EQ(2, descriptors.size()); diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/timestamp.pb.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/timestamp.pb.cc new file mode 100644 index 000000000..8e6b5f23f --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/timestamp.pb.cc @@ -0,0 +1,423 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +// This is a temporary google only hack +#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS +#include "third_party/protobuf/version.h" +#endif +// @@protoc_insertion_point(includes) + +namespace google { +namespace protobuf { +class TimestampDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _Timestamp_default_instance_; +} // namespace protobuf +} // namespace google +namespace protobuf_google_2fprotobuf_2ftimestamp_2eproto { +static void InitDefaultsTimestamp() { + GOOGLE_PROTOBUF_VERIFY_VERSION; + + { + void* ptr = &::google::protobuf::_Timestamp_default_instance_; + new (ptr) ::google::protobuf::Timestamp(); + ::google::protobuf::internal::OnShutdownDestroyMessage(ptr); + } + ::google::protobuf::Timestamp::InitAsDefaultInstance(); +} + +LIBPROTOBUF_EXPORT ::google::protobuf::internal::SCCInfo<0> scc_info_Timestamp = + {{ATOMIC_VAR_INIT(::google::protobuf::internal::SCCInfoBase::kUninitialized), 0, InitDefaultsTimestamp}, {}}; + +void InitDefaults() { + ::google::protobuf::internal::InitSCC(&scc_info_Timestamp.base); +} + +::google::protobuf::Metadata file_level_metadata[1]; + +const ::google::protobuf::uint32 TableStruct::offsets[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + ~0u, // no _has_bits_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Timestamp, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Timestamp, seconds_), + GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(::google::protobuf::Timestamp, nanos_), +}; +static const ::google::protobuf::internal::MigrationSchema schemas[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + { 0, -1, sizeof(::google::protobuf::Timestamp)}, +}; + +static ::google::protobuf::Message const * const file_default_instances[] = { + reinterpret_cast(&::google::protobuf::_Timestamp_default_instance_), +}; + +void protobuf_AssignDescriptors() { + AddDescriptors(); + AssignDescriptors( + "google/protobuf/timestamp.proto", schemas, file_default_instances, TableStruct::offsets, + file_level_metadata, NULL, NULL); +} + +void protobuf_AssignDescriptorsOnce() { + static ::google::protobuf::internal::once_flag once; + ::google::protobuf::internal::call_once(once, protobuf_AssignDescriptors); +} + +void protobuf_RegisterTypes(const ::std::string&) GOOGLE_PROTOBUF_ATTRIBUTE_COLD; +void protobuf_RegisterTypes(const ::std::string&) { + protobuf_AssignDescriptorsOnce(); + ::google::protobuf::internal::RegisterAllTypes(file_level_metadata, 1); +} + +void AddDescriptorsImpl() { + InitDefaults(); + static const char descriptor[] GOOGLE_PROTOBUF_ATTRIBUTE_SECTION_VARIABLE(protodesc_cold) = { + "\n\037google/protobuf/timestamp.proto\022\017googl" + "e.protobuf\"+\n\tTimestamp\022\017\n\007seconds\030\001 \001(\003" + "\022\r\n\005nanos\030\002 \001(\005B~\n\023com.google.protobufB\016" + "TimestampProtoP\001Z+github.com/golang/prot" + "obuf/ptypes/timestamp\370\001\001\242\002\003GPB\252\002\036Google." + "Protobuf.WellKnownTypesb\006proto3" + }; + ::google::protobuf::DescriptorPool::InternalAddGeneratedFile( + descriptor, 231); + ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile( + "google/protobuf/timestamp.proto", &protobuf_RegisterTypes); +} + +void AddDescriptors() { + static ::google::protobuf::internal::once_flag once; + ::google::protobuf::internal::call_once(once, AddDescriptorsImpl); +} +// Force AddDescriptors() to be called at dynamic initialization time. +struct StaticDescriptorInitializer { + StaticDescriptorInitializer() { + AddDescriptors(); + } +} static_descriptor_initializer; +} // namespace protobuf_google_2fprotobuf_2ftimestamp_2eproto +namespace google { +namespace protobuf { + +// =================================================================== + +void Timestamp::InitAsDefaultInstance() { +} +#if !defined(_MSC_VER) || _MSC_VER >= 1900 +const int Timestamp::kSecondsFieldNumber; +const int Timestamp::kNanosFieldNumber; +#endif // !defined(_MSC_VER) || _MSC_VER >= 1900 + +Timestamp::Timestamp() + : ::google::protobuf::Message(), _internal_metadata_(NULL) { + ::google::protobuf::internal::InitSCC( + &protobuf_google_2fprotobuf_2ftimestamp_2eproto::scc_info_Timestamp.base); + SharedCtor(); + // @@protoc_insertion_point(constructor:google.protobuf.Timestamp) +} +Timestamp::Timestamp(::google::protobuf::Arena* arena) + : ::google::protobuf::Message(), + _internal_metadata_(arena) { + ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2ftimestamp_2eproto::scc_info_Timestamp.base); + SharedCtor(); + RegisterArenaDtor(arena); + // @@protoc_insertion_point(arena_constructor:google.protobuf.Timestamp) +} +Timestamp::Timestamp(const Timestamp& from) + : ::google::protobuf::Message(), + _internal_metadata_(NULL) { + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::memcpy(&seconds_, &from.seconds_, + static_cast(reinterpret_cast(&nanos_) - + reinterpret_cast(&seconds_)) + sizeof(nanos_)); + // @@protoc_insertion_point(copy_constructor:google.protobuf.Timestamp) +} + +void Timestamp::SharedCtor() { + ::memset(&seconds_, 0, static_cast( + reinterpret_cast(&nanos_) - + reinterpret_cast(&seconds_)) + sizeof(nanos_)); +} + +Timestamp::~Timestamp() { + // @@protoc_insertion_point(destructor:google.protobuf.Timestamp) + SharedDtor(); +} + +void Timestamp::SharedDtor() { + GOOGLE_DCHECK(GetArenaNoVirtual() == NULL); +} + +void Timestamp::ArenaDtor(void* object) { + Timestamp* _this = reinterpret_cast< Timestamp* >(object); + (void)_this; +} +void Timestamp::RegisterArenaDtor(::google::protobuf::Arena* arena) { +} +void Timestamp::SetCachedSize(int size) const { + _cached_size_.Set(size); +} +const ::google::protobuf::Descriptor* Timestamp::descriptor() { + ::protobuf_google_2fprotobuf_2ftimestamp_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2ftimestamp_2eproto::file_level_metadata[kIndexInFileMessages].descriptor; +} + +const Timestamp& Timestamp::default_instance() { + ::google::protobuf::internal::InitSCC(&protobuf_google_2fprotobuf_2ftimestamp_2eproto::scc_info_Timestamp.base); + return *internal_default_instance(); +} + + +void Timestamp::Clear() { +// @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp) + ::google::protobuf::uint32 cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + ::memset(&seconds_, 0, static_cast( + reinterpret_cast(&nanos_) - + reinterpret_cast(&seconds_)) + sizeof(nanos_)); + _internal_metadata_.Clear(); +} + +bool Timestamp::MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) { +#define DO_(EXPRESSION) if (!GOOGLE_PREDICT_TRUE(EXPRESSION)) goto failure + ::google::protobuf::uint32 tag; + // @@protoc_insertion_point(parse_start:google.protobuf.Timestamp) + for (;;) { + ::std::pair<::google::protobuf::uint32, bool> p = input->ReadTagWithCutoffNoLastTag(127u); + tag = p.first; + if (!p.second) goto handle_unusual; + switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) { + // int64 seconds = 1; + case 1: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(8u /* 8 & 0xFF */)) { + + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int64, ::google::protobuf::internal::WireFormatLite::TYPE_INT64>( + input, &seconds_))); + } else { + goto handle_unusual; + } + break; + } + + // int32 nanos = 2; + case 2: { + if (static_cast< ::google::protobuf::uint8>(tag) == + static_cast< ::google::protobuf::uint8>(16u /* 16 & 0xFF */)) { + + DO_((::google::protobuf::internal::WireFormatLite::ReadPrimitive< + ::google::protobuf::int32, ::google::protobuf::internal::WireFormatLite::TYPE_INT32>( + input, &nanos_))); + } else { + goto handle_unusual; + } + break; + } + + default: { + handle_unusual: + if (tag == 0) { + goto success; + } + DO_(::google::protobuf::internal::WireFormat::SkipField( + input, tag, _internal_metadata_.mutable_unknown_fields())); + break; + } + } + } +success: + // @@protoc_insertion_point(parse_success:google.protobuf.Timestamp) + return true; +failure: + // @@protoc_insertion_point(parse_failure:google.protobuf.Timestamp) + return false; +#undef DO_ +} + +void Timestamp::SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const { + // @@protoc_insertion_point(serialize_start:google.protobuf.Timestamp) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int64 seconds = 1; + if (this->seconds() != 0) { + ::google::protobuf::internal::WireFormatLite::WriteInt64(1, this->seconds(), output); + } + + // int32 nanos = 2; + if (this->nanos() != 0) { + ::google::protobuf::internal::WireFormatLite::WriteInt32(2, this->nanos(), output); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + ::google::protobuf::internal::WireFormat::SerializeUnknownFields( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), output); + } + // @@protoc_insertion_point(serialize_end:google.protobuf.Timestamp) +} + +::google::protobuf::uint8* Timestamp::InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const { + (void)deterministic; // Unused + // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp) + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + // int64 seconds = 1; + if (this->seconds() != 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt64ToArray(1, this->seconds(), target); + } + + // int32 nanos = 2; + if (this->nanos() != 0) { + target = ::google::protobuf::internal::WireFormatLite::WriteInt32ToArray(2, this->nanos(), target); + } + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance()), target); + } + // @@protoc_insertion_point(serialize_to_array_end:google.protobuf.Timestamp) + return target; +} + +size_t Timestamp::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp) + size_t total_size = 0; + + if ((_internal_metadata_.have_unknown_fields() && ::google::protobuf::internal::GetProto3PreserveUnknownsDefault())) { + total_size += + ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize( + (::google::protobuf::internal::GetProto3PreserveUnknownsDefault() ? _internal_metadata_.unknown_fields() : _internal_metadata_.default_instance())); + } + // int64 seconds = 1; + if (this->seconds() != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int64Size( + this->seconds()); + } + + // int32 nanos = 2; + if (this->nanos() != 0) { + total_size += 1 + + ::google::protobuf::internal::WireFormatLite::Int32Size( + this->nanos()); + } + + int cached_size = ::google::protobuf::internal::ToCachedSize(total_size); + SetCachedSize(cached_size); + return total_size; +} + +void Timestamp::MergeFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_merge_from_start:google.protobuf.Timestamp) + GOOGLE_DCHECK_NE(&from, this); + const Timestamp* source = + ::google::protobuf::internal::DynamicCastToGenerated( + &from); + if (source == NULL) { + // @@protoc_insertion_point(generalized_merge_from_cast_fail:google.protobuf.Timestamp) + ::google::protobuf::internal::ReflectionOps::Merge(from, this); + } else { + // @@protoc_insertion_point(generalized_merge_from_cast_success:google.protobuf.Timestamp) + MergeFrom(*source); + } +} + +void Timestamp::MergeFrom(const Timestamp& from) { +// @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp) + GOOGLE_DCHECK_NE(&from, this); + _internal_metadata_.MergeFrom(from._internal_metadata_); + ::google::protobuf::uint32 cached_has_bits = 0; + (void) cached_has_bits; + + if (from.seconds() != 0) { + set_seconds(from.seconds()); + } + if (from.nanos() != 0) { + set_nanos(from.nanos()); + } +} + +void Timestamp::CopyFrom(const ::google::protobuf::Message& from) { +// @@protoc_insertion_point(generalized_copy_from_start:google.protobuf.Timestamp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +void Timestamp::CopyFrom(const Timestamp& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:google.protobuf.Timestamp) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool Timestamp::IsInitialized() const { + return true; +} + +void Timestamp::Swap(Timestamp* other) { + if (other == this) return; + if (GetArenaNoVirtual() == other->GetArenaNoVirtual()) { + InternalSwap(other); + } else { + Timestamp* temp = New(GetArenaNoVirtual()); + temp->MergeFrom(*other); + other->CopyFrom(*this); + InternalSwap(temp); + if (GetArenaNoVirtual() == NULL) { + delete temp; + } + } +} +void Timestamp::UnsafeArenaSwap(Timestamp* other) { + if (other == this) return; + GOOGLE_DCHECK(GetArenaNoVirtual() == other->GetArenaNoVirtual()); + InternalSwap(other); +} +void Timestamp::InternalSwap(Timestamp* other) { + using std::swap; + swap(seconds_, other->seconds_); + swap(nanos_, other->nanos_); + _internal_metadata_.Swap(&other->_internal_metadata_); +} + +::google::protobuf::Metadata Timestamp::GetMetadata() const { + protobuf_google_2fprotobuf_2ftimestamp_2eproto::protobuf_AssignDescriptorsOnce(); + return ::protobuf_google_2fprotobuf_2ftimestamp_2eproto::file_level_metadata[kIndexInFileMessages]; +} + + +// @@protoc_insertion_point(namespace_scope) +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { +template<> GOOGLE_PROTOBUF_ATTRIBUTE_NOINLINE ::google::protobuf::Timestamp* Arena::CreateMaybeMessage< ::google::protobuf::Timestamp >(Arena* arena) { + return Arena::CreateMessageInternal< ::google::protobuf::Timestamp >(arena); +} +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/timestamp.pb.h b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/timestamp.pb.h new file mode 100644 index 000000000..6e79b733e --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/timestamp.pb.h @@ -0,0 +1,238 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/timestamp.proto + +#ifndef PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto +#define PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto + +#include + +#include + +#if GOOGLE_PROTOBUF_VERSION < 3006001 +#error This file was generated by a newer version of protoc which is +#error incompatible with your Protocol Buffer headers. Please update +#error your headers. +#endif +#if 3006001 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION +#error This file was generated by an older version of protoc which is +#error incompatible with your Protocol Buffer headers. Please +#error regenerate this file with a newer version of protoc. +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include // IWYU pragma: export +#include // IWYU pragma: export +#include +// @@protoc_insertion_point(includes) +#define PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2ftimestamp_2eproto LIBPROTOBUF_EXPORT + +namespace protobuf_google_2fprotobuf_2ftimestamp_2eproto { +// Internal implementation detail -- do not use these members. +struct LIBPROTOBUF_EXPORT TableStruct { + static const ::google::protobuf::internal::ParseTableField entries[]; + static const ::google::protobuf::internal::AuxillaryParseTableField aux[]; + static const ::google::protobuf::internal::ParseTable schema[1]; + static const ::google::protobuf::internal::FieldMetadata field_metadata[]; + static const ::google::protobuf::internal::SerializationTable serialization_table[]; + static const ::google::protobuf::uint32 offsets[]; +}; +void LIBPROTOBUF_EXPORT AddDescriptors(); +} // namespace protobuf_google_2fprotobuf_2ftimestamp_2eproto +namespace google { +namespace protobuf { +class Timestamp; +class TimestampDefaultTypeInternal; +LIBPROTOBUF_EXPORT extern TimestampDefaultTypeInternal _Timestamp_default_instance_; +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { +template<> LIBPROTOBUF_EXPORT ::google::protobuf::Timestamp* Arena::CreateMaybeMessage<::google::protobuf::Timestamp>(Arena*); +} // namespace protobuf +} // namespace google +namespace google { +namespace protobuf { + +// =================================================================== + +class LIBPROTOBUF_EXPORT Timestamp : public ::google::protobuf::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Timestamp) */ { + public: + Timestamp(); + virtual ~Timestamp(); + + Timestamp(const Timestamp& from); + + inline Timestamp& operator=(const Timestamp& from) { + CopyFrom(from); + return *this; + } + #if LANG_CXX11 + Timestamp(Timestamp&& from) noexcept + : Timestamp() { + *this = ::std::move(from); + } + + inline Timestamp& operator=(Timestamp&& from) noexcept { + if (GetArenaNoVirtual() == from.GetArenaNoVirtual()) { + if (this != &from) InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + #endif + inline ::google::protobuf::Arena* GetArena() const final { + return GetArenaNoVirtual(); + } + inline void* GetMaybeArenaPointer() const final { + return MaybeArenaPtr(); + } + static const ::google::protobuf::Descriptor* descriptor(); + static const Timestamp& default_instance(); + + static void InitAsDefaultInstance(); // FOR INTERNAL USE ONLY + static inline const Timestamp* internal_default_instance() { + return reinterpret_cast( + &_Timestamp_default_instance_); + } + static constexpr int kIndexInFileMessages = + 0; + + void UnsafeArenaSwap(Timestamp* other); + void Swap(Timestamp* other); + friend void swap(Timestamp& a, Timestamp& b) { + a.Swap(&b); + } + + // implements Message ---------------------------------------------- + + inline Timestamp* New() const final { + return CreateMaybeMessage(NULL); + } + + Timestamp* New(::google::protobuf::Arena* arena) const final { + return CreateMaybeMessage(arena); + } + void CopyFrom(const ::google::protobuf::Message& from) final; + void MergeFrom(const ::google::protobuf::Message& from) final; + void CopyFrom(const Timestamp& from); + void MergeFrom(const Timestamp& from); + void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + bool MergePartialFromCodedStream( + ::google::protobuf::io::CodedInputStream* input) final; + void SerializeWithCachedSizes( + ::google::protobuf::io::CodedOutputStream* output) const final; + ::google::protobuf::uint8* InternalSerializeWithCachedSizesToArray( + bool deterministic, ::google::protobuf::uint8* target) const final; + int GetCachedSize() const final { return _cached_size_.Get(); } + + private: + void SharedCtor(); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(Timestamp* other); + protected: + explicit Timestamp(::google::protobuf::Arena* arena); + private: + static void ArenaDtor(void* object); + inline void RegisterArenaDtor(::google::protobuf::Arena* arena); + private: + inline ::google::protobuf::Arena* GetArenaNoVirtual() const { + return _internal_metadata_.arena(); + } + inline void* MaybeArenaPtr() const { + return _internal_metadata_.raw_arena_ptr(); + } + public: + + ::google::protobuf::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + // int64 seconds = 1; + void clear_seconds(); + static const int kSecondsFieldNumber = 1; + ::google::protobuf::int64 seconds() const; + void set_seconds(::google::protobuf::int64 value); + + // int32 nanos = 2; + void clear_nanos(); + static const int kNanosFieldNumber = 2; + ::google::protobuf::int32 nanos() const; + void set_nanos(::google::protobuf::int32 value); + + // @@protoc_insertion_point(class_scope:google.protobuf.Timestamp) + private: + + ::google::protobuf::internal::InternalMetadataWithArena _internal_metadata_; + template friend class ::google::protobuf::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + ::google::protobuf::int64 seconds_; + ::google::protobuf::int32 nanos_; + mutable ::google::protobuf::internal::CachedSize _cached_size_; + friend struct ::protobuf_google_2fprotobuf_2ftimestamp_2eproto::TableStruct; +}; +// =================================================================== + + +// =================================================================== + +#ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif // __GNUC__ +// Timestamp + +// int64 seconds = 1; +inline void Timestamp::clear_seconds() { + seconds_ = GOOGLE_LONGLONG(0); +} +inline ::google::protobuf::int64 Timestamp::seconds() const { + // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds) + return seconds_; +} +inline void Timestamp::set_seconds(::google::protobuf::int64 value) { + + seconds_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds) +} + +// int32 nanos = 2; +inline void Timestamp::clear_nanos() { + nanos_ = 0; +} +inline ::google::protobuf::int32 Timestamp::nanos() const { + // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos) + return nanos_; +} +inline void Timestamp::set_nanos(::google::protobuf::int32 value) { + + nanos_ = value; + // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos) +} + +#ifdef __GNUC__ + #pragma GCC diagnostic pop +#endif // __GNUC__ + +// @@protoc_insertion_point(namespace_scope) + +} // namespace protobuf +} // namespace google + +// @@protoc_insertion_point(global_scope) + +#endif // PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/timestamp.proto b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/timestamp.proto new file mode 100644 index 000000000..eafb3fa03 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/timestamp.proto @@ -0,0 +1,135 @@ +// Protocol Buffers - Google's data interchange format +// Copyright 2008 Google Inc. All rights reserved. +// https://developers.google.com/protocol-buffers/ +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "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 THE COPYRIGHT +// OWNER OR CONTRIBUTORS 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. + +syntax = "proto3"; + +package google.protobuf; + +option csharp_namespace = "Google.Protobuf.WellKnownTypes"; +option cc_enable_arenas = true; +option go_package = "github.com/golang/protobuf/ptypes/timestamp"; +option java_package = "com.google.protobuf"; +option java_outer_classname = "TimestampProto"; +option java_multiple_files = true; +option objc_class_prefix = "GPB"; + +// A Timestamp represents a point in time independent of any time zone +// or calendar, represented as seconds and fractions of seconds at +// nanosecond resolution in UTC Epoch time. It is encoded using the +// Proleptic Gregorian Calendar which extends the Gregorian calendar +// backwards to year one. It is encoded assuming all minutes are 60 +// seconds long, i.e. leap seconds are "smeared" so that no leap second +// table is needed for interpretation. Range is from +// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. +// By restricting to that range, we ensure that we can convert to +// and from RFC 3339 date strings. +// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt). +// +// # Examples +// +// Example 1: Compute Timestamp from POSIX `time()`. +// +// Timestamp timestamp; +// timestamp.set_seconds(time(NULL)); +// timestamp.set_nanos(0); +// +// Example 2: Compute Timestamp from POSIX `gettimeofday()`. +// +// struct timeval tv; +// gettimeofday(&tv, NULL); +// +// Timestamp timestamp; +// timestamp.set_seconds(tv.tv_sec); +// timestamp.set_nanos(tv.tv_usec * 1000); +// +// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. +// +// FILETIME ft; +// GetSystemTimeAsFileTime(&ft); +// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; +// +// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z +// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. +// Timestamp timestamp; +// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); +// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); +// +// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. +// +// long millis = System.currentTimeMillis(); +// +// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) +// .setNanos((int) ((millis % 1000) * 1000000)).build(); +// +// +// Example 5: Compute Timestamp from current time in Python. +// +// timestamp = Timestamp() +// timestamp.GetCurrentTime() +// +// # JSON Mapping +// +// In JSON format, the Timestamp type is encoded as a string in the +// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the +// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" +// where {year} is always expressed using four digits while {month}, {day}, +// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional +// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), +// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone +// is required. A proto3 JSON serializer should always use UTC (as indicated by +// "Z") when printing the Timestamp type and a proto3 JSON parser should be +// able to accept both UTC and other timezones (as indicated by an offset). +// +// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past +// 01:30 UTC on January 15, 2017. +// +// In JavaScript, one can convert a Date object to this format using the +// standard [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString] +// method. In Python, a standard `datetime.datetime` object can be converted +// to this format using [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) +// with the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one +// can use the Joda Time's [`ISODateTimeFormat.dateTime()`]( +// http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime-- +// ) to obtain a formatter capable of generating timestamps in this format. +// +// +message Timestamp { + + // Represents seconds of UTC time since Unix epoch + // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + // 9999-12-31T23:59:59Z inclusive. + int64 seconds = 1; + + // Non-negative fractions of a second at nanosecond resolution. Negative + // second values with fractions must still have non-negative nanos values + // that count forward in time. Must be from 0 to 999,999,999 + // inclusive. + int32 nanos = 2; +} diff --git a/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/type.pb.cc b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/type.pb.cc new file mode 100644 index 000000000..130af52a3 --- /dev/null +++ b/cdk/protobuf/protobuf-3.6.1/src/google/protobuf/type.pb.cc @@ -0,0 +1,2805 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/protobuf/type.proto + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +// This is a temporary google only hack +#ifdef GOOGLE_PROTOBUF_ENFORCE_UNIQUENESS +#include "third_party/protobuf/version.h" +#endif +// @@protoc_insertion_point(includes) + +namespace protobuf_google_2fprotobuf_2fany_2eproto { +extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fany_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_Any; +} // namespace protobuf_google_2fprotobuf_2fany_2eproto +namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto { +extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto ::google::protobuf::internal::SCCInfo<0> scc_info_SourceContext; +} // namespace protobuf_google_2fprotobuf_2fsource_5fcontext_2eproto +namespace protobuf_google_2fprotobuf_2ftype_2eproto { +extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2ftype_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_EnumValue; +extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2ftype_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_Field; +extern PROTOBUF_INTERNAL_EXPORT_protobuf_google_2fprotobuf_2ftype_2eproto ::google::protobuf::internal::SCCInfo<1> scc_info_Option; +} // namespace protobuf_google_2fprotobuf_2ftype_2eproto +namespace google { +namespace protobuf { +class TypeDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _Type_default_instance_; +class FieldDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _Field_default_instance_; +class EnumDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _Enum_default_instance_; +class EnumValueDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed + _instance; +} _EnumValue_default_instance_; +class OptionDefaultTypeInternal { + public: + ::google::protobuf::internal::ExplicitlyConstructed